Check-in [48c3c19745]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Introduced wrapper macros snew(), snewn() and sresize() for the malloc functions, which automatically cast to the same type they're allocating the size of. Should prevent any future errors involving mallocing the size of the wrong structure type, and will also make life easier if we ever need to turn the PuTTY core code from real C into C++-friendly C. I haven't touched the Mac frontend in this checkin because I couldn't compile or test it.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 48c3c1974567b7c214b941b182e0cb5cb5540312
User & Date: simon 2003-03-29 10:14:26.000
Context
2003-03-29
10:47
Added uxsel.c, into which I've moved those parts of the uxnet.c functionality that deal with selectable fds in general. The idea is that pty.c will stop passing its fd straight to pterm.c and hand it to this module instead, and pterm.c will start requesting a general list of fds from this module rather than expecting a single one from pty.c, with the ultimate aim of pterm.c being able to form the basis of a Unix PuTTY as well as pterm proper. check-in: b740285f7b user: simon tags: trunk
10:14
Introduced wrapper macros snew(), snewn() and sresize() for the malloc functions, which automatically cast to the same type they're allocating the size of. Should prevent any future errors involving mallocing the size of the wrong structure type, and will also make life easier if we ever need to turn the PuTTY core code from real C into C++-friendly C. I haven't touched the Mac frontend in this checkin because I couldn't compile or test it. check-in: 48c3c19745 user: simon tags: trunk
07:54
Fix off-by-one in selection update while scrolling. Thanks Richard B. check-in: f99ffbf1c3 user: simon tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to cmdline.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 */
static struct cmdline_saved_param_set saves[NPRIORITIES];

static void cmdline_save_param(char *p, char *value, int pri)
{
    if (saves[pri].nsaved >= saves[pri].savesize) {
	saves[pri].savesize = saves[pri].nsaved + 32;
	saves[pri].params =
	    srealloc(saves[pri].params,
		     saves[pri].savesize*sizeof(*saves[pri].params));
    }
    saves[pri].params[saves[pri].nsaved].p = p;
    saves[pri].params[saves[pri].nsaved].value = value;
    saves[pri].nsaved++;
}

#define SAVEABLE(pri) do { \







|
|
<







39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
 */
static struct cmdline_saved_param_set saves[NPRIORITIES];

static void cmdline_save_param(char *p, char *value, int pri)
{
    if (saves[pri].nsaved >= saves[pri].savesize) {
	saves[pri].savesize = saves[pri].nsaved + 32;
	saves[pri].params = sresize(saves[pri].params, saves[pri].savesize,
				    struct cmdline_saved_param);

    }
    saves[pri].params[saves[pri].nsaved].p = p;
    saves[pri].params[saves[pri].nsaved].value = value;
    saves[pri].nsaved++;
}

#define SAVEABLE(pri) do { \
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
	do {
	    c = fgetc(fp);
	    d = c;
	    if (c == EOF)
		d = 0;
	    if (cmdlen >= cmdsize) {
		cmdsize = cmdlen + 512;
		command = srealloc(command, cmdsize);
	    }
	    command[cmdlen++] = d;
	} while (c != EOF);
	cfg->remote_cmd_ptr = command;
	cfg->remote_cmd_ptr2 = NULL;
	cfg->nopty = TRUE;      /* command => no terminal */
    }







|







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
	do {
	    c = fgetc(fp);
	    d = c;
	    if (c == EOF)
		d = 0;
	    if (cmdlen >= cmdsize) {
		cmdsize = cmdlen + 512;
		command = sresize(command, cmdsize, char);
	    }
	    command[cmdlen++] = d;
	} while (c != EOF);
	cfg->remote_cmd_ptr = command;
	cfg->remote_cmd_ptr2 = NULL;
	cfg->nopty = TRUE;      /* command => no terminal */
    }
Changes to config.c.
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
    ccd = (struct charclass_data *)
	ctrl_alloc(b, sizeof(struct charclass_data));
    ccd->listbox = ctrl_listbox(s, "Character classes:", 'e',
				HELPCTX(selection_charclasses),
				charclass_handler, P(ccd));
    ccd->listbox->listbox.multisel = 1;
    ccd->listbox->listbox.ncols = 4;
    ccd->listbox->listbox.percentages = smalloc(4*sizeof(int));
    ccd->listbox->listbox.percentages[0] = 15;
    ccd->listbox->listbox.percentages[1] = 25;
    ccd->listbox->listbox.percentages[2] = 20;
    ccd->listbox->listbox.percentages[3] = 40;
    ctrl_columns(s, 2, 67, 33);
    ccd->editbox = ctrl_editbox(s, "Set to class", 't', 50,
				HELPCTX(selection_charclasses),







|







1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
    ccd = (struct charclass_data *)
	ctrl_alloc(b, sizeof(struct charclass_data));
    ccd->listbox = ctrl_listbox(s, "Character classes:", 'e',
				HELPCTX(selection_charclasses),
				charclass_handler, P(ccd));
    ccd->listbox->listbox.multisel = 1;
    ccd->listbox->listbox.ncols = 4;
    ccd->listbox->listbox.percentages = snewn(4, int);
    ccd->listbox->listbox.percentages[0] = 15;
    ccd->listbox->listbox.percentages[1] = 25;
    ccd->listbox->listbox.percentages[2] = 20;
    ccd->listbox->listbox.percentages[3] = 40;
    ctrl_columns(s, 2, 67, 33);
    ccd->editbox = ctrl_editbox(s, "Set to class", 't', 50,
				HELPCTX(selection_charclasses),
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
	    ed->rembutton->generic.column = 1;
	    ctrl_columns(s, 1, 100);
	    ed->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
				       HELPCTX(telnet_environ),
				       environ_handler, P(ed));
	    ed->listbox->listbox.height = 3;
	    ed->listbox->listbox.ncols = 2;
	    ed->listbox->listbox.percentages = smalloc(2*sizeof(int));
	    ed->listbox->listbox.percentages[0] = 30;
	    ed->listbox->listbox.percentages[1] = 70;
	}

	s = ctrl_getset(b, "Connection/Telnet", "protocol",
			"Telnet protocol adjustments");








|







1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
	    ed->rembutton->generic.column = 1;
	    ctrl_columns(s, 1, 100);
	    ed->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
				       HELPCTX(telnet_environ),
				       environ_handler, P(ed));
	    ed->listbox->listbox.height = 3;
	    ed->listbox->listbox.ncols = 2;
	    ed->listbox->listbox.percentages = snewn(2, int);
	    ed->listbox->listbox.percentages[0] = 30;
	    ed->listbox->listbox.percentages[1] = 70;
	}

	s = ctrl_getset(b, "Connection/Telnet", "protocol",
			"Telnet protocol adjustments");

1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
	pfd->rembutton->generic.column = 2;
	pfd->rembutton->generic.tabdelay = 1;
	pfd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
				    HELPCTX(ssh_tunnels_portfwd),
				    portfwd_handler, P(pfd));
	pfd->listbox->listbox.height = 3;
	pfd->listbox->listbox.ncols = 2;
	pfd->listbox->listbox.percentages = smalloc(2*sizeof(int));
	pfd->listbox->listbox.percentages[0] = 20;
	pfd->listbox->listbox.percentages[1] = 80;
	ctrl_tabdelay(s, pfd->rembutton);
	ctrl_text(s, "Add new forwarded port:", HELPCTX(ssh_tunnels_portfwd));
	/* You want to enter source, destination and type, _then_ hit Add.
	 * Again, we adjust the tab order to reflect this. */
	pfd->addbutton = ctrl_pushbutton(s, "Add", 'd',







|







1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
	pfd->rembutton->generic.column = 2;
	pfd->rembutton->generic.tabdelay = 1;
	pfd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
				    HELPCTX(ssh_tunnels_portfwd),
				    portfwd_handler, P(pfd));
	pfd->listbox->listbox.height = 3;
	pfd->listbox->listbox.ncols = 2;
	pfd->listbox->listbox.percentages = snewn(2, int);
	pfd->listbox->listbox.percentages[0] = 20;
	pfd->listbox->listbox.percentages[1] = 80;
	ctrl_tabdelay(s, pfd->rembutton);
	ctrl_text(s, "Add new forwarded port:", HELPCTX(ssh_tunnels_portfwd));
	/* You want to enter source, destination and type, _then_ hit Add.
	 * Again, we adjust the tab order to reflect this. */
	pfd->addbutton = ctrl_pushbutton(s, "Add", 'd',
Changes to dialog.c.
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	p1++, p2++;
    }
    return INT_MAX;		       /* exact match */
}

struct controlbox *ctrl_new_box(void)
{
    struct controlbox *ret = smalloc(sizeof(struct controlbox));

    ret->nctrlsets = ret->ctrlsetsize = 0;
    ret->ctrlsets = NULL;
    ret->nfrees = ret->freesize = 0;
    ret->frees = NULL;

    return ret;







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	p1++, p2++;
    }
    return INT_MAX;		       /* exact match */
}

struct controlbox *ctrl_new_box(void)
{
    struct controlbox *ret = snew(struct controlbox);

    ret->nctrlsets = ret->ctrlsetsize = 0;
    ret->ctrlsets = NULL;
    ret->nfrees = ret->freesize = 0;
    ret->frees = NULL;

    return ret;
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
}

/* Set up a panel title. */
struct controlset *ctrl_settitle(struct controlbox *b,
				 char *path, char *title)
{
    
    struct controlset *s = smalloc(sizeof(struct controlset));
    int index = ctrl_find_set(b, path, 1);
    s->pathname = dupstr(path);
    s->boxname = NULL;
    s->boxtitle = dupstr(title);
    s->ncontrols = s->ctrlsize = 0;
    s->ncolumns = 0;		       /* this is a title! */
    s->ctrls = NULL;
    if (b->nctrlsets >= b->ctrlsetsize) {
	b->ctrlsetsize = b->nctrlsets + 32;
	b->ctrlsets = srealloc(b->ctrlsets,
			       b->ctrlsetsize*sizeof(*b->ctrlsets));
    }
    if (index < b->nctrlsets)
	memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
		(b->nctrlsets-index) * sizeof(*b->ctrlsets));
    b->ctrlsets[index] = s;
    b->nctrlsets++;
    return s;







|









|
<







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
}

/* Set up a panel title. */
struct controlset *ctrl_settitle(struct controlbox *b,
				 char *path, char *title)
{
    
    struct controlset *s = snew(struct controlset);
    int index = ctrl_find_set(b, path, 1);
    s->pathname = dupstr(path);
    s->boxname = NULL;
    s->boxtitle = dupstr(title);
    s->ncontrols = s->ctrlsize = 0;
    s->ncolumns = 0;		       /* this is a title! */
    s->ctrls = NULL;
    if (b->nctrlsets >= b->ctrlsetsize) {
	b->ctrlsetsize = b->nctrlsets + 32;
	b->ctrlsets = sresize(b->ctrlsets, b->ctrlsetsize,struct controlset *);

    }
    if (index < b->nctrlsets)
	memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
		(b->nctrlsets-index) * sizeof(*b->ctrlsets));
    b->ctrlsets[index] = s;
    b->nctrlsets++;
    return s;
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188




189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
    while (index < b->nctrlsets &&
	   !strcmp(b->ctrlsets[index]->pathname, path)) {
	if (b->ctrlsets[index]->boxname &&
	    !strcmp(b->ctrlsets[index]->boxname, name))
	    return b->ctrlsets[index];
	index++;
    }
    s = smalloc(sizeof(struct controlset));
    s->pathname = dupstr(path);
    s->boxname = dupstr(name);
    s->boxtitle = boxtitle ? dupstr(boxtitle) : NULL;
    s->ncolumns = 1;
    s->ncontrols = s->ctrlsize = 0;
    s->ctrls = NULL;
    if (b->nctrlsets >= b->ctrlsetsize) {
	b->ctrlsetsize = b->nctrlsets + 32;
	b->ctrlsets = srealloc(b->ctrlsets,
			       b->ctrlsetsize*sizeof(*b->ctrlsets));
    }
    if (index < b->nctrlsets)
	memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
		(b->nctrlsets-index) * sizeof(*b->ctrlsets));
    b->ctrlsets[index] = s;
    b->nctrlsets++;
    return s;
}

/* Allocate some private data in a controlbox. */
void *ctrl_alloc(struct controlbox *b, size_t size)
{
    void *p;




    p = smalloc(size);
    if (b->nfrees >= b->freesize) {
	b->freesize = b->nfrees + 32;
	b->frees = srealloc(b->frees, b->freesize*sizeof(*b->frees));
    }
    b->frees[b->nfrees++] = p;
    return p;
}

static union control *ctrl_new(struct controlset *s, int type,
			       intorptr helpctx, handler_fn handler,
			       intorptr context)
{
    union control *c = smalloc(sizeof(union control));
    if (s->ncontrols >= s->ctrlsize) {
	s->ctrlsize = s->ncontrols + 32;
	s->ctrls = srealloc(s->ctrls, s->ctrlsize * sizeof(*s->ctrls));
    }
    s->ctrls[s->ncontrols++] = c;
    /*
     * Fill in the standard fields.
     */
    c->generic.type = type;
    c->generic.tabdelay = 0;







|








|
<













>
>
>
>



|









|


|







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
    while (index < b->nctrlsets &&
	   !strcmp(b->ctrlsets[index]->pathname, path)) {
	if (b->ctrlsets[index]->boxname &&
	    !strcmp(b->ctrlsets[index]->boxname, name))
	    return b->ctrlsets[index];
	index++;
    }
    s = snew(struct controlset);
    s->pathname = dupstr(path);
    s->boxname = dupstr(name);
    s->boxtitle = boxtitle ? dupstr(boxtitle) : NULL;
    s->ncolumns = 1;
    s->ncontrols = s->ctrlsize = 0;
    s->ctrls = NULL;
    if (b->nctrlsets >= b->ctrlsetsize) {
	b->ctrlsetsize = b->nctrlsets + 32;
	b->ctrlsets = sresize(b->ctrlsets, b->ctrlsetsize,struct controlset *);

    }
    if (index < b->nctrlsets)
	memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
		(b->nctrlsets-index) * sizeof(*b->ctrlsets));
    b->ctrlsets[index] = s;
    b->nctrlsets++;
    return s;
}

/* Allocate some private data in a controlbox. */
void *ctrl_alloc(struct controlbox *b, size_t size)
{
    void *p;
    /*
     * This is an internal allocation routine, so it's allowed to
     * use smalloc directly.
     */
    p = smalloc(size);
    if (b->nfrees >= b->freesize) {
	b->freesize = b->nfrees + 32;
	b->frees = sresize(b->frees, b->freesize, void *);
    }
    b->frees[b->nfrees++] = p;
    return p;
}

static union control *ctrl_new(struct controlset *s, int type,
			       intorptr helpctx, handler_fn handler,
			       intorptr context)
{
    union control *c = snew(union control);
    if (s->ncontrols >= s->ctrlsize) {
	s->ctrlsize = s->ncontrols + 32;
	s->ctrls = sresize(s->ctrls, s->ctrlsize, union control *);
    }
    s->ctrls[s->ncontrols++] = c;
    /*
     * Fill in the standard fields.
     */
    c->generic.type = type;
    c->generic.tabdelay = 0;
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
    c->columns.ncols = ncolumns;
    s->ncolumns = ncolumns;
    if (ncolumns == 1) {
	c->columns.percentages = NULL;
    } else {
	va_list ap;
	int i;
	c->columns.percentages = smalloc(ncolumns * sizeof(int));
	va_start(ap, ncolumns);
	for (i = 0; i < ncolumns; i++)
	    c->columns.percentages[i] = va_arg(ap, int);
	va_end(ap);
    }
    return c;
}







|







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
    c->columns.ncols = ncolumns;
    s->ncolumns = ncolumns;
    if (ncolumns == 1) {
	c->columns.percentages = NULL;
    } else {
	va_list ap;
	int i;
	c->columns.percentages = snewn(ncolumns, int);
	va_start(ap, ncolumns);
	for (i = 0; i < ncolumns; i++)
	    c->columns.percentages[i] = va_arg(ap, int);
	va_end(ap);
    }
    return c;
}
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
	if (c->radio.shortcut == NO_SHORTCUT)
	    (void)va_arg(ap, int);     /* char promotes to int in arg lists */
	(void)va_arg(ap, intorptr);
    }
    va_end(ap);
    c->radio.nbuttons = i;
    if (c->radio.shortcut == NO_SHORTCUT)
	c->radio.shortcuts = smalloc(c->radio.nbuttons * sizeof(char));
    else
	c->radio.shortcuts = NULL;
    c->radio.buttons = smalloc(c->radio.nbuttons * sizeof(char *));
    c->radio.buttondata = smalloc(c->radio.nbuttons * sizeof(intorptr));
    /*
     * Second pass along variable argument list to actually fill in
     * the structure.
     */
    va_start(ap, context);
    for (i = 0; i < c->radio.nbuttons; i++) {
	c->radio.buttons[i] = dupstr(va_arg(ap, char *));







|


|
|







298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
	if (c->radio.shortcut == NO_SHORTCUT)
	    (void)va_arg(ap, int);     /* char promotes to int in arg lists */
	(void)va_arg(ap, intorptr);
    }
    va_end(ap);
    c->radio.nbuttons = i;
    if (c->radio.shortcut == NO_SHORTCUT)
	c->radio.shortcuts = snewn(c->radio.nbuttons, char);
    else
	c->radio.shortcuts = NULL;
    c->radio.buttons = snewn(c->radio.nbuttons, char *);
    c->radio.buttondata = snewn(c->radio.nbuttons, intorptr);
    /*
     * Second pass along variable argument list to actually fill in
     * the structure.
     */
    va_start(ap, context);
    for (i = 0; i < c->radio.nbuttons; i++) {
	c->radio.buttons[i] = dupstr(va_arg(ap, char *));
Changes to import.c.
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    FILE *fp;
    char buffer[256];
    char *errmsg, *p;
    int headers_done;
    char base64_bit[4];
    int base64_chars = 0;

    ret = smalloc(sizeof(*ret));
    ret->keyblob = NULL;
    ret->keyblob_len = ret->keyblob_size = 0;
    ret->encrypted = 0;
    memset(ret->iv, 0, sizeof(ret->iv));

    fp = f_open(*filename, "r");
    if (!fp) {







|







322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    FILE *fp;
    char buffer[256];
    char *errmsg, *p;
    int headers_done;
    char base64_bit[4];
    int base64_chars = 0;

    ret = snew(struct openssh_key);
    ret->keyblob = NULL;
    ret->keyblob_len = ret->keyblob_size = 0;
    ret->encrypted = 0;
    memset(ret->iv, 0, sizeof(ret->iv));

    fp = f_open(*filename, "r");
    if (!fp) {
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
                    if (len <= 0) {
                        errmsg = "Invalid base64 encoding";
                        goto error;
                    }

                    if (ret->keyblob_len + len > ret->keyblob_size) {
                        ret->keyblob_size = ret->keyblob_len + len + 256;
                        ret->keyblob = srealloc(ret->keyblob, ret->keyblob_size);

                    }

                    memcpy(ret->keyblob + ret->keyblob_len, out, len);
                    ret->keyblob_len += len;

                    memset(out, 0, sizeof(out));
                }







|
>







412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
                    if (len <= 0) {
                        errmsg = "Invalid base64 encoding";
                        goto error;
                    }

                    if (ret->keyblob_len + len > ret->keyblob_size) {
                        ret->keyblob_size = ret->keyblob_len + len + 256;
                        ret->keyblob = sresize(ret->keyblob, ret->keyblob_size,
					       unsigned char);
                    }

                    memcpy(ret->keyblob + ret->keyblob_len, out, len);
                    ret->keyblob_len += len;

                    memset(out, 0, sizeof(out));
                }
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
    else if (key->type == OSSH_DSA)
	num_integers = 6;

    /*
     * Space to create key blob in.
     */
    blobsize = 256+key->keyblob_len;
    blob = smalloc(blobsize);
    PUT_32BIT(blob, 7);
    if (key->type == OSSH_DSA)
	memcpy(blob+4, "ssh-dss", 7);
    else if (key->type == OSSH_RSA)
	memcpy(blob+4, "ssh-rsa", 7);
    blobptr = 4+7;
    privptr = -1;







|







561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
    else if (key->type == OSSH_DSA)
	num_integers = 6;

    /*
     * Space to create key blob in.
     */
    blobsize = 256+key->keyblob_len;
    blob = snewn(blobsize, unsigned char);
    PUT_32BIT(blob, 7);
    if (key->type == OSSH_DSA)
	memcpy(blob+4, "ssh-dss", 7);
    else if (key->type == OSSH_RSA)
	memcpy(blob+4, "ssh-rsa", 7);
    blobptr = 4+7;
    privptr = -1;
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
    /*
     * Now put together the actual key. Simplest way to do this is
     * to assemble our own key blobs and feed them to the createkey
     * functions; this is a bit faffy but it does mean we get all
     * the sanity checks for free.
     */
    assert(privptr > 0);	       /* should have bombed by now if not */
    retkey = smalloc(sizeof(struct ssh2_userkey));
    retkey->alg = (key->type == OSSH_RSA ? &ssh_rsa : &ssh_dss);
    retkey->data = retkey->alg->createkey(blob, privptr,
					  blob+privptr, blobptr-privptr);
    if (!retkey->data) {
	sfree(retkey);
	errmsg = "unable to create key data structure";
	goto error;







|







633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
    /*
     * Now put together the actual key. Simplest way to do this is
     * to assemble our own key blobs and feed them to the createkey
     * functions; this is a bit faffy but it does mean we get all
     * the sanity checks for free.
     */
    assert(privptr > 0);	       /* should have bombed by now if not */
    retkey = snew(struct ssh2_userkey);
    retkey->alg = (key->type == OSSH_RSA ? &ssh_rsa : &ssh_dss);
    retkey->data = retkey->alg->createkey(blob, privptr,
					  blob+privptr, blobptr-privptr);
    if (!retkey->data) {
	sfree(retkey);
	errmsg = "unable to create key data structure";
	goto error;
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
        freebn(bd);
        freebn(bp);
        freebn(bq);

        dmp1.bytes = (bignum_bitcount(bdmp1)+8)/8;
        dmq1.bytes = (bignum_bitcount(bdmq1)+8)/8;
        sparelen = dmp1.bytes + dmq1.bytes;
        spareblob = smalloc(sparelen);
        dmp1.start = spareblob;
        dmq1.start = spareblob + dmp1.bytes;
        for (i = 0; i < dmp1.bytes; i++)
            spareblob[i] = bignum_byte(bdmp1, dmp1.bytes-1 - i);
        for (i = 0; i < dmq1.bytes; i++)
            spareblob[i+dmp1.bytes] = bignum_byte(bdmq1, dmq1.bytes-1 - i);
        freebn(bdmp1);







|







716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
        freebn(bd);
        freebn(bp);
        freebn(bq);

        dmp1.bytes = (bignum_bitcount(bdmp1)+8)/8;
        dmq1.bytes = (bignum_bitcount(bdmq1)+8)/8;
        sparelen = dmp1.bytes + dmq1.bytes;
        spareblob = snewn(sparelen, unsigned char);
        dmp1.start = spareblob;
        dmq1.start = spareblob + dmp1.bytes;
        for (i = 0; i < dmp1.bytes; i++)
            spareblob[i] = bignum_byte(bdmp1, dmp1.bytes-1 - i);
        for (i = 0; i < dmq1.bytes; i++)
            spareblob[i+dmp1.bytes] = bignum_byte(bdmq1, dmq1.bytes-1 - i);
        freebn(bdmp1);
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
    outlen = len;
    if (passphrase)
	outlen = (outlen+8) &~ 7;

    /*
     * Now we know how big outblob needs to be. Allocate it.
     */
    outblob = smalloc(outlen);

    /*
     * And write the data into it.
     */
    pos = 0;
    pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
    for (i = 0; i < nnumbers; i++) {







|







788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
    outlen = len;
    if (passphrase)
	outlen = (outlen+8) &~ 7;

    /*
     * Now we know how big outblob needs to be. Allocate it.
     */
    outblob = snewn(outlen, unsigned char);

    /*
     * And write the data into it.
     */
    pos = 0;
    pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
    for (i = 0; i < nnumbers; i++) {
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
    char buffer[256];
    int len;
    char *errmsg, *p;
    int headers_done;
    char base64_bit[4];
    int base64_chars = 0;

    ret = smalloc(sizeof(*ret));
    ret->comment[0] = '\0';
    ret->keyblob = NULL;
    ret->keyblob_len = ret->keyblob_size = 0;

    fp = f_open(*filename, "r");
    if (!fp) {
	errmsg = "Unable to open key file";







|







993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
    char buffer[256];
    int len;
    char *errmsg, *p;
    int headers_done;
    char base64_bit[4];
    int base64_chars = 0;

    ret = snew(struct sshcom_key);
    ret->comment[0] = '\0';
    ret->keyblob = NULL;
    ret->keyblob_len = ret->keyblob_size = 0;

    fp = f_open(*filename, "r");
    if (!fp) {
	errmsg = "Unable to open key file";
1068
1069
1070
1071
1072
1073
1074
1075

1076
1077
1078
1079
1080
1081
1082
                    if (len <= 0) {
                        errmsg = "Invalid base64 encoding";
                        goto error;
                    }

                    if (ret->keyblob_len + len > ret->keyblob_size) {
                        ret->keyblob_size = ret->keyblob_len + len + 256;
                        ret->keyblob = srealloc(ret->keyblob, ret->keyblob_size);

                    }

                    memcpy(ret->keyblob + ret->keyblob_len, out, len);
                    ret->keyblob_len += len;
                }

		p++;







|
>







1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
                    if (len <= 0) {
                        errmsg = "Invalid base64 encoding";
                        goto error;
                    }

                    if (ret->keyblob_len + len > ret->keyblob_size) {
                        ret->keyblob_size = ret->keyblob_len + len + 256;
                        ret->keyblob = sresize(ret->keyblob, ret->keyblob_size,
					       unsigned char);
                    }

                    memcpy(ret->keyblob + ret->keyblob_len, out, len);
                    ret->keyblob_len += len;
                }

		p++;
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343

    /*
     * Now we break down into RSA versus DSA. In either case we'll
     * construct public and private blobs in our own format, and
     * end up feeding them to alg->createkey().
     */
    blobsize = cipherlen + 256;
    blob = smalloc(blobsize);
    privlen = 0;
    if (type == RSA) {
        struct mpint_pos n, e, d, u, p, q;
        int pos = 0;
        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &e);
        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &d);
        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &n);







|







1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345

    /*
     * Now we break down into RSA versus DSA. In either case we'll
     * construct public and private blobs in our own format, and
     * end up feeding them to alg->createkey().
     */
    blobsize = cipherlen + 256;
    blob = snewn(blobsize, unsigned char);
    privlen = 0;
    if (type == RSA) {
        struct mpint_pos n, e, d, u, p, q;
        int pos = 0;
        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &e);
        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &d);
        pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &n);
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
        publen = pos;
        pos += put_mp(blob+pos, x.start, x.bytes);
        privlen = pos - publen;
    }

    assert(privlen > 0);	       /* should have bombed by now if not */

    retkey = smalloc(sizeof(struct ssh2_userkey));
    retkey->alg = alg;
    retkey->data = alg->createkey(blob, publen, blob+publen, privlen);
    if (!retkey->data) {
	sfree(retkey);
	errmsg = "unable to create key data structure";
	goto error;
    }







|







1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
        publen = pos;
        pos += put_mp(blob+pos, x.start, x.bytes);
        privlen = pos - publen;
    }

    assert(privlen > 0);	       /* should have bombed by now if not */

    retkey = snew(struct ssh2_userkey);
    retkey->alg = alg;
    retkey->data = alg->createkey(blob, publen, blob+publen, privlen);
    if (!retkey->data) {
	sfree(retkey);
	errmsg = "unable to create key data structure";
	goto error;
    }
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
     * Total size of key blob will be somewhere under 512 plus
     * combined length of integers. We'll calculate the more
     * precise size as we construct the blob.
     */
    outlen = 512;
    for (i = 0; i < nnumbers; i++)
	outlen += 4 + numbers[i].bytes;
    outblob = smalloc(outlen);

    /*
     * Create the unencrypted key blob.
     */
    pos = 0;
    PUT_32BIT(outblob+pos, SSHCOM_MAGIC_NUMBER); pos += 4;
    pos += 4;			       /* length field, fill in later */







|







1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
     * Total size of key blob will be somewhere under 512 plus
     * combined length of integers. We'll calculate the more
     * precise size as we construct the blob.
     */
    outlen = 512;
    for (i = 0; i < nnumbers; i++)
	outlen += 4 + numbers[i].bytes;
    outblob = snewn(outlen, unsigned char);

    /*
     * Create the unencrypted key blob.
     */
    pos = 0;
    PUT_32BIT(outblob+pos, SSHCOM_MAGIC_NUMBER); pos += 4;
    pos += 4;			       /* length field, fill in later */
Changes to ldisc.c.
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#define CTRL(x) (x^'@')
#define KCTRL(x) ((x^'@') | 0x100)

void *ldisc_create(Config *mycfg, Terminal *term,
		   Backend *back, void *backhandle,
		   void *frontend)
{
    Ldisc ldisc = smalloc(sizeof(*ldisc));

    ldisc->buf = NULL;
    ldisc->buflen = 0;
    ldisc->bufsiz = 0;
    ldisc->quotenext = 0;

    ldisc->cfg = mycfg;







|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#define CTRL(x) (x^'@')
#define KCTRL(x) ((x^'@') | 0x100)

void *ldisc_create(Config *mycfg, Terminal *term,
		   Backend *back, void *backhandle,
		   void *frontend)
{
    Ldisc ldisc = snew(struct ldisc_tag);

    ldisc->buf = NULL;
    ldisc->buflen = 0;
    ldisc->bufsiz = 0;
    ldisc->quotenext = 0;

    ldisc->cfg = mycfg;
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
		    break;
		}
		/* FALLTHROUGH */
	      default:		       /* get to this label from ^V handler */
                default_case:
		if (ldisc->buflen >= ldisc->bufsiz) {
		    ldisc->bufsiz = ldisc->buflen + 256;
		    ldisc->buf = srealloc(ldisc->buf, ldisc->bufsiz);
		}
		ldisc->buf[ldisc->buflen++] = c;
		if (ECHOING)
		    pwrite(ldisc, (unsigned char) c);
		ldisc->quotenext = FALSE;
		break;
	    }







|







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
		    break;
		}
		/* FALLTHROUGH */
	      default:		       /* get to this label from ^V handler */
                default_case:
		if (ldisc->buflen >= ldisc->bufsiz) {
		    ldisc->bufsiz = ldisc->buflen + 256;
		    ldisc->buf = sresize(ldisc->buf, ldisc->bufsiz, char);
		}
		ldisc->buf[ldisc->buflen++] = c;
		if (ECHOING)
		    pwrite(ldisc, (unsigned char) c);
		ldisc->quotenext = FALSE;
		break;
	    }
Changes to ldiscucs.c.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

    if (codepage < 0) {
	ldisc_send(ldisc, buf, len, interactive);
	return;
    }

    widesize = len * 2;
    widebuffer = smalloc(widesize * sizeof(wchar_t));

    wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize);
    luni_send(ldisc, widebuffer, wclen, interactive);

    sfree(widebuffer);
}

void luni_send(void *handle, wchar_t * widebuf, int len, int interactive)
{
    Ldisc ldisc = (Ldisc)handle;
    int ratio = (in_utf(ldisc->term))?3:1;
    char *linebuffer;
    int linesize;
    int i;
    char *p;

    linesize = len * ratio * 2;
    linebuffer = smalloc(linesize * sizeof(wchar_t));

    if (in_utf(ldisc->term)) {
	/* UTF is a simple algorithm */
	for (p = linebuffer, i = 0; i < len; i++) {
	    wchar_t ch = widebuf[i];
	    /* We only deal with 16-bit wide chars */
	    if ((ch&0xF800) == 0xD800) ch = '.';







|

















|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

    if (codepage < 0) {
	ldisc_send(ldisc, buf, len, interactive);
	return;
    }

    widesize = len * 2;
    widebuffer = snewn(widesize, wchar_t);

    wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize);
    luni_send(ldisc, widebuffer, wclen, interactive);

    sfree(widebuffer);
}

void luni_send(void *handle, wchar_t * widebuf, int len, int interactive)
{
    Ldisc ldisc = (Ldisc)handle;
    int ratio = (in_utf(ldisc->term))?3:1;
    char *linebuffer;
    int linesize;
    int i;
    char *p;

    linesize = len * ratio * 2;
    linebuffer = snewn(linesize, char);

    if (in_utf(ldisc->term)) {
	/* UTF is a simple algorithm */
	for (p = linebuffer, i = 0; i < len; i++) {
	    wchar_t ch = widebuf[i];
	    /* We only deal with 16-bit wide chars */
	    if ((ch&0xF800) == 0xD800) ch = '.';
Changes to logging.c.
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
	fclose(ctx->lgfp);
	ctx->lgfp = NULL;
    }
}

void *log_init(void *frontend, Config *cfg)
{
    struct LogContext *ctx = smalloc(sizeof(struct LogContext));
    ctx->lgfp = NULL;
    ctx->frontend = frontend;
    ctx->cfg = *cfg;		       /* STRUCTURE COPY */
    return ctx;
}

void log_free(void *handle)







|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
	fclose(ctx->lgfp);
	ctx->lgfp = NULL;
    }
}

void *log_init(void *frontend, Config *cfg)
{
    struct LogContext *ctx = snew(struct LogContext);
    ctx->lgfp = NULL;
    ctx->frontend = frontend;
    ctx->cfg = *cfg;		       /* STRUCTURE COPY */
    return ctx;
}

void log_free(void *handle)
Changes to misc.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* ----------------------------------------------------------------------
 * String handling routines.
 */

char *dupstr(const 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(const char *s1, ...)
{







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* ----------------------------------------------------------------------
 * String handling routines.
 */

char *dupstr(const char *s)
{
    int len = strlen(s);
    char *p = snewn(len + 1, char);
    strcpy(p, s);
    return p;
}

/* Allocate the concatenation of N strings. Terminate arg list with NULL. */
char *dupcat(const char *s1, ...)
{
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
	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)







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
	sn = va_arg(ap, char *);
	if (!sn)
	    break;
	len += strlen(sn);
    }
    va_end(ap);

    p = snewn(len + 1, char);
    strcpy(p, s1);
    q = p + strlen(p);

    va_start(ap, s1);
    while (1) {
	sn = va_arg(ap, char *);
	if (!sn)
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
    return ret;
}
char *dupvprintf(const char *fmt, va_list ap)
{
    char *buf;
    int len, size;

    buf = smalloc(512);
    size = 512;

    while (1) {
#ifdef _WINDOWS
#define vsnprintf _vsnprintf
#endif
	len = vsnprintf(buf, size, fmt, ap);
	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;
	}
	buf = srealloc(buf, size);
    }
}

/* ----------------------------------------------------------------------
 * Base64 encoding routine. This is required in public-key writing
 * but also in HTTP proxy handling, so it's centralised here.
 */







|




















|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
    return ret;
}
char *dupvprintf(const char *fmt, va_list ap)
{
    char *buf;
    int len, size;

    buf = snewn(512, char);
    size = 512;

    while (1) {
#ifdef _WINDOWS
#define vsnprintf _vsnprintf
#endif
	len = vsnprintf(buf, size, fmt, ap);
	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;
	}
	buf = sresize(buf, size, char);
    }
}

/* ----------------------------------------------------------------------
 * Base64 encoding routine. This is required in public-key writing
 * but also in HTTP proxy handling, so it's centralised here.
 */
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
	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;







|







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
	buf += copylen;
	len -= copylen;
	ch->tail->buflen += copylen;
    }
    while (len > 0) {
	int grainlen = min(len, BUFFER_GRANULE);
	struct bufchain_granule *newbuf;
	newbuf = snew(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;
Changes to pageant.c.
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
	    blob = ssh2_userkey_loadpub(&filename, NULL, &bloblen);
	    if (!blob) {
		MessageBox(NULL, "Couldn't load private key.", APPNAME,
			   MB_OK | MB_ICONERROR);
		return;
	    }
	    /* For our purposes we want the blob prefixed with its length */
	    blob2 = smalloc(bloblen+4);
	    PUT_32BIT(blob2, bloblen);
	    memcpy(blob2 + 4, blob, bloblen);
	    sfree(blob);
	    blob = blob2;

	    keylist = get_keylist2();
	}







|







415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
	    blob = ssh2_userkey_loadpub(&filename, NULL, &bloblen);
	    if (!blob) {
		MessageBox(NULL, "Couldn't load private key.", APPNAME,
			   MB_OK | MB_ICONERROR);
		return;
	    }
	    /* For our purposes we want the blob prefixed with its length */
	    blob2 = snewn(bloblen+4, unsigned char);
	    PUT_32BIT(blob2, bloblen);
	    memcpy(blob2 + 4, blob, bloblen);
	    sfree(blob);
	    blob = blob2;

	    keylist = get_keylist2();
	}
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469

    if (type == SSH_KEYTYPE_SSH1)
	needs_pass = rsakey_encrypted(&filename, &comment);
    else
	needs_pass = ssh2_userkey_encrypted(&filename, &comment);
    attempts = 0;
    if (type == SSH_KEYTYPE_SSH1)
	rkey = smalloc(sizeof(*rkey));
    pps.passphrase = passphrase;
    pps.comment = comment;
    original_pass = 0;
    do {
	if (needs_pass) {
	    /* try all the remembered passphrases first */
	    char *pp = index234(passphrases, attempts);







|







455
456
457
458
459
460
461
462
463
464
465
466
467
468
469

    if (type == SSH_KEYTYPE_SSH1)
	needs_pass = rsakey_encrypted(&filename, &comment);
    else
	needs_pass = ssh2_userkey_encrypted(&filename, &comment);
    attempts = 0;
    if (type == SSH_KEYTYPE_SSH1)
	rkey = snew(struct RSAKey);
    pps.passphrase = passphrase;
    pps.comment = comment;
    original_pass = 0;
    do {
	if (needs_pass) {
	    /* try all the remembered passphrases first */
	    char *pp = index234(passphrases, attempts);
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
		ssh1_bignum_length(rkey->exponent) +
		ssh1_bignum_length(rkey->private_exponent) +
		ssh1_bignum_length(rkey->iqmp) +
		ssh1_bignum_length(rkey->p) +
		ssh1_bignum_length(rkey->q) + 4 + clen	/* comment */
		;

	    request = smalloc(reqlen);

	    request[4] = SSH1_AGENTC_ADD_RSA_IDENTITY;
	    reqlen = 5;
	    PUT_32BIT(request + reqlen, bignum_bitcount(rkey->modulus));
	    reqlen += 4;
	    reqlen += ssh1_write_bignum(request + reqlen, rkey->modulus);
	    reqlen += ssh1_write_bignum(request + reqlen, rkey->exponent);







|







528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
		ssh1_bignum_length(rkey->exponent) +
		ssh1_bignum_length(rkey->private_exponent) +
		ssh1_bignum_length(rkey->iqmp) +
		ssh1_bignum_length(rkey->p) +
		ssh1_bignum_length(rkey->q) + 4 + clen	/* comment */
		;

	    request = snewn(reqlen, unsigned char);

	    request[4] = SSH1_AGENTC_ADD_RSA_IDENTITY;
	    reqlen = 5;
	    PUT_32BIT(request + reqlen, bignum_bitcount(rkey->modulus));
	    reqlen += 4;
	    reqlen += ssh1_write_bignum(request + reqlen, rkey->modulus);
	    reqlen += ssh1_write_bignum(request + reqlen, rkey->exponent);
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590

	    reqlen = 4 + 1 +	       /* length, message type */
		4 + alglen +	       /* algorithm name */
		keybloblen +	       /* key data */
		4 + clen	       /* comment */
		;

	    request = smalloc(reqlen);

	    request[4] = SSH2_AGENTC_ADD_IDENTITY;
	    reqlen = 5;
	    PUT_32BIT(request + reqlen, alglen);
	    reqlen += 4;
	    memcpy(request + reqlen, skey->alg->name, alglen);
	    reqlen += alglen;







|







576
577
578
579
580
581
582
583
584
585
586
587
588
589
590

	    reqlen = 4 + 1 +	       /* length, message type */
		4 + alglen +	       /* algorithm name */
		keybloblen +	       /* key data */
		4 + clen	       /* comment */
		;

	    request = snewn(reqlen, unsigned char);

	    request[4] = SSH2_AGENTC_ADD_IDENTITY;
	    reqlen = 5;
	    PUT_32BIT(request + reqlen, alglen);
	    reqlen += 4;
	    memcpy(request + reqlen, skey->alg->name, alglen);
	    reqlen += alglen;
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
	blob = rsa_public_blob(key, &bloblen);
	len += bloblen;
	sfree(blob);
	len += 4 + strlen(key->comment);
    }

    /* Allocate the buffer. */
    p = ret = smalloc(len);
    if (length) *length = len;

    PUT_32BIT(p, nkeys);
    p += 4;
    for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {
	blob = rsa_public_blob(key, &bloblen);
	memcpy(p, blob, bloblen);







|







635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
	blob = rsa_public_blob(key, &bloblen);
	len += bloblen;
	sfree(blob);
	len += 4 + strlen(key->comment);
    }

    /* Allocate the buffer. */
    p = ret = snewn(len, unsigned char);
    if (length) *length = len;

    PUT_32BIT(p, nkeys);
    p += 4;
    for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {
	blob = rsa_public_blob(key, &bloblen);
	memcpy(p, blob, bloblen);
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
	blob = key->alg->public_blob(key->data, &bloblen);
	len += bloblen;
	sfree(blob);
	len += 4 + strlen(key->comment);
    }

    /* Allocate the buffer. */
    p = ret = smalloc(len);
    if (length) *length = len;

    /*
     * Packet header is the obvious five bytes, plus four
     * bytes for the key count.
     */
    PUT_32BIT(p, nkeys);







|







680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
	blob = key->alg->public_blob(key->data, &bloblen);
	len += bloblen;
	sfree(blob);
	len += 4 + strlen(key->comment);
    }

    /* Allocate the buffer. */
    p = ret = snewn(len, unsigned char);
    if (length) *length = len;

    /*
     * Packet header is the obvious five bytes, plus four
     * bytes for the key count.
     */
    PUT_32BIT(p, nkeys);
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
	PUT_32BIT(request, 4);

	agent_query(request, 5, &vresponse, &resplen);
	response = vresponse;
	if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER)
	    return NULL;

	ret = smalloc(resplen-5);
	memcpy(ret, response+5, resplen-5);
	sfree(response);
    } else {
	ret = make_keylist1(NULL);
    }
    return ret;
}







|







726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
	PUT_32BIT(request, 4);

	agent_query(request, 5, &vresponse, &resplen);
	response = vresponse;
	if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER)
	    return NULL;

	ret = snewn(resplen-5, unsigned char);
	memcpy(ret, response+5, resplen-5);
	sfree(response);
    } else {
	ret = make_keylist1(NULL);
    }
    return ret;
}
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
	PUT_32BIT(request, 4);

	agent_query(request, 5, &vresponse, &resplen);
	response = vresponse;
	if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER)
	    return NULL;

	ret = smalloc(resplen-5);
	memcpy(ret, response+5, resplen-5);
	sfree(response);
    } else {
	ret = make_keylist2(NULL);
    }
    return ret;
}







|







757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
	PUT_32BIT(request, 4);

	agent_query(request, 5, &vresponse, &resplen);
	response = vresponse;
	if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER)
	    return NULL;

	ret = snewn(resplen-5, unsigned char);
	memcpy(ret, response+5, resplen-5);
	sfree(response);
    } else {
	ret = make_keylist2(NULL);
    }
    return ret;
}
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
	 * Add to the list and return SSH_AGENT_SUCCESS, or
	 * SSH_AGENT_FAILURE if the key was malformed.
	 */
	{
	    struct RSAKey *key;
	    char *comment;
            int commentlen;
	    key = smalloc(sizeof(struct RSAKey));
	    memset(key, 0, sizeof(struct RSAKey));
	    p += makekey(p, key, NULL, 1);
	    p += makeprivate(p, key);
	    p += ssh1_read_bignum(p, &key->iqmp);	/* p^-1 mod q */
	    p += ssh1_read_bignum(p, &key->p);	/* p */
	    p += ssh1_read_bignum(p, &key->q);	/* q */
            commentlen = GET_32BIT(p);
	    comment = smalloc(commentlen+1);
	    if (comment) {
		memcpy(comment, p + 4, commentlen);
                comment[commentlen] = '\0';
		key->comment = comment;
	    }
	    PUT_32BIT(ret, 1);
	    ret[4] = SSH_AGENT_FAILURE;







|







|







909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
	 * Add to the list and return SSH_AGENT_SUCCESS, or
	 * SSH_AGENT_FAILURE if the key was malformed.
	 */
	{
	    struct RSAKey *key;
	    char *comment;
            int commentlen;
	    key = snew(struct RSAKey);
	    memset(key, 0, sizeof(struct RSAKey));
	    p += makekey(p, key, NULL, 1);
	    p += makeprivate(p, key);
	    p += ssh1_read_bignum(p, &key->iqmp);	/* p^-1 mod q */
	    p += ssh1_read_bignum(p, &key->p);	/* p */
	    p += ssh1_read_bignum(p, &key->q);	/* q */
            commentlen = GET_32BIT(p);
	    comment = snewn(commentlen+1, char);
	    if (comment) {
		memcpy(comment, p + 4, commentlen);
                comment[commentlen] = '\0';
		key->comment = comment;
	    }
	    PUT_32BIT(ret, 1);
	    ret[4] = SSH_AGENT_FAILURE;
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
	 */
	{
	    struct ssh2_userkey *key;
	    char *comment, *alg;
	    int alglen, commlen;
	    int bloblen;

	    key = smalloc(sizeof(struct ssh2_userkey));

	    alglen = GET_32BIT(p);
	    p += 4;
	    alg = p;
	    p += alglen;
	    /* Add further algorithm names here. */
	    if (alglen == 7 && !memcmp(alg, "ssh-rsa", 7))







|







945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
	 */
	{
	    struct ssh2_userkey *key;
	    char *comment, *alg;
	    int alglen, commlen;
	    int bloblen;

	    key = snew(struct ssh2_userkey);

	    alglen = GET_32BIT(p);
	    p += 4;
	    alg = p;
	    p += alglen;
	    /* Add further algorithm names here. */
	    if (alglen == 7 && !memcmp(alg, "ssh-rsa", 7))
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
	    if (!key->data) {
		sfree(key);
		goto failure;
	    }
	    commlen = GET_32BIT(p);
	    p += 4;

	    comment = smalloc(commlen + 1);
	    if (comment) {
		memcpy(comment, p, commlen);
		comment[commlen] = '\0';
	    }
	    key->comment = comment;

	    PUT_32BIT(ret, 1);







|







973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
	    if (!key->data) {
		sfree(key);
		goto failure;
	    }
	    commlen = GET_32BIT(p);
	    p += 4;

	    comment = snewn(commlen + 1, char);
	    if (comment) {
		memcpy(comment, p, commlen);
		comment[commlen] = '\0';
	    }
	    key->comment = comment;

	    PUT_32BIT(ret, 1);
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
/*
 * Prompt for a key file to add, and add it.
 */
static void prompt_add_keyfile(void)
{
    OPENFILENAME of;
    char filename[FILENAME_MAX];
    char *filelist = smalloc(8192);
    char *filewalker;
    int n, dirlen;
	
    memset(&of, 0, sizeof(of));
#ifdef OPENFILENAME_SIZE_VERSION_400
    of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
#else







|







1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
/*
 * Prompt for a key file to add, and add it.
 */
static void prompt_add_keyfile(void)
{
    OPENFILENAME of;
    char filename[FILENAME_MAX];
    char *filelist = snewn(8192, char);
    char *filewalker;
    int n, dirlen;
	
    memset(&of, 0, sizeof(of));
#ifdef OPENFILENAME_SIZE_VERSION_400
    of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
#else
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
		/* none selected? that was silly */
		if (numSelected == 0) {
		    MessageBeep(0);
		    break;
		}

		/* get item indices in an array */
		selectedArray = smalloc(numSelected * sizeof(int));
		SendDlgItemMessage(hwnd, 100, LB_GETSELITEMS,
				numSelected, (WPARAM)selectedArray);
		
		itemNum = numSelected - 1;
		rCount = count234(rsakeys);
		sCount = count234(ssh2keys);
		







|







1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
		/* none selected? that was silly */
		if (numSelected == 0) {
		    MessageBeep(0);
		    break;
		}

		/* get item indices in an array */
		selectedArray = snewn(numSelected, int);
		SendDlgItemMessage(hwnd, 100, LB_GETSELITEMS,
				numSelected, (WPARAM)selectedArray);
		
		itemNum = numSelected - 1;
		rCount = count234(rsakeys);
		sCount = count234(ssh2keys);
		
Changes to pageantc.c.
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    cds.cbData = 1 + strlen(mapname);
    cds.lpData = mapname;
    id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) & cds);
    debug(("return is %d\n", id));
    if (id > 0) {
	retlen = 4 + GET_32BIT(p);
	debug(("len is %d\n", retlen));
	ret = smalloc(retlen);
	if (ret) {
	    memcpy(ret, p, retlen);
	    *out = ret;
	    *outlen = retlen;
	}
    }
    UnmapViewOfFile(p);







|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    cds.cbData = 1 + strlen(mapname);
    cds.lpData = mapname;
    id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) & cds);
    debug(("return is %d\n", id));
    if (id > 0) {
	retlen = 4 + GET_32BIT(p);
	debug(("len is %d\n", retlen));
	ret = snewn(retlen, unsigned char);
	if (ret) {
	    memcpy(ret, p, retlen);
	    *out = ret;
	    *outlen = retlen;
	}
    }
    UnmapViewOfFile(p);
Changes to plink.c.
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
		cmdlen = cmdsize = 0;
		command = NULL;

		while (argc) {
		    while (*p) {
			if (cmdlen >= cmdsize) {
			    cmdsize = cmdlen + 512;
			    command = srealloc(command, cmdsize);
			}
			command[cmdlen++]=*p++;
		    }
		    if (cmdlen >= cmdsize) {
			cmdsize = cmdlen + 512;
			command = srealloc(command, cmdsize);
		    }
		    command[cmdlen++]=' '; /* always add trailing space */
		    if (--argc) p = *++argv;
		}
		if (cmdlen) command[--cmdlen]='\0';
				       /* change trailing blank to NUL */
		cfg.remote_cmd_ptr = command;







|





|







406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
		cmdlen = cmdsize = 0;
		command = NULL;

		while (argc) {
		    while (*p) {
			if (cmdlen >= cmdsize) {
			    cmdsize = cmdlen + 512;
			    command = sresize(command, cmdsize, char);
			}
			command[cmdlen++]=*p++;
		    }
		    if (cmdlen >= cmdsize) {
			cmdsize = cmdlen + 512;
			command = sresize(command, cmdsize, char);
		    }
		    command[cmdlen++]=' '; /* always add trailing space */
		    if (--argc) p = *++argv;
		}
		if (cmdlen) command[--cmdlen]='\0';
				       /* change trailing blank to NUL */
		cfg.remote_cmd_ptr = command;
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
	    for (socket = first_socket(&socketstate);
		 socket != INVALID_SOCKET;
		 socket = next_socket(&socketstate)) i++;

	    /* Expand the buffer if necessary. */
	    if (i > sksize) {
		sksize = i + 16;
		sklist = srealloc(sklist, sksize * sizeof(*sklist));
	    }

	    /* Retrieve the sockets into sklist. */
	    skcount = 0;
	    for (socket = first_socket(&socketstate);
		 socket != INVALID_SOCKET;
		 socket = next_socket(&socketstate)) {







|







647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
	    for (socket = first_socket(&socketstate);
		 socket != INVALID_SOCKET;
		 socket = next_socket(&socketstate)) i++;

	    /* Expand the buffer if necessary. */
	    if (i > sksize) {
		sksize = i + 16;
		sklist = sresize(sklist, sksize, SOCKET);
	    }

	    /* Retrieve the sockets into sklist. */
	    skcount = 0;
	    for (socket = first_socket(&socketstate);
		 socket != INVALID_SOCKET;
		 socket = next_socket(&socketstate)) {
Changes to portfwd.c.
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    addr = name_lookup(hostname, port, &dummy_realhost, cfg);
    if ((err = sk_addr_error(addr)) != NULL)
	return err;

    /*
     * Open socket.
     */
    pr = (struct PFwdPrivate *) smalloc(sizeof(struct PFwdPrivate));
    pr->fn = &fn_table;
    pr->throttled = pr->throttle_override = 0;
    pr->ready = 1;
    pr->c = c;
    pr->backhandle = NULL;	       /* we shouldn't need this */

    pr->s = *s = new_connection(addr, dummy_realhost, port,







|







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    addr = name_lookup(hostname, port, &dummy_realhost, cfg);
    if ((err = sk_addr_error(addr)) != NULL)
	return err;

    /*
     * Open socket.
     */
    pr = snew(struct PFwdPrivate);
    pr->fn = &fn_table;
    pr->throttled = pr->throttle_override = 0;
    pr->ready = 1;
    pr->c = c;
    pr->backhandle = NULL;	       /* we shouldn't need this */

    pr->s = *s = new_connection(addr, dummy_realhost, port,
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
	NULL
    };
    struct PFwdPrivate *pr, *org;
    Socket s;
    char *err;

    org = (struct PFwdPrivate *)p;
    pr = (struct PFwdPrivate *) smalloc(sizeof(struct PFwdPrivate));
    pr->fn = &fn_table;

    pr->c = NULL;
    pr->backhandle = org->backhandle;

    pr->s = s = sk_register(sock, (Plug) pr);
    if ((err = sk_socket_error(s)) != NULL) {







|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
	NULL
    };
    struct PFwdPrivate *pr, *org;
    Socket s;
    char *err;

    org = (struct PFwdPrivate *)p;
    pr = snew(struct PFwdPrivate);
    pr->fn = &fn_table;

    pr->c = NULL;
    pr->backhandle = org->backhandle;

    pr->s = s = sk_register(sock, (Plug) pr);
    if ((err = sk_socket_error(s)) != NULL) {
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
    char *err;
    struct PFwdPrivate *pr;
    Socket s;

    /*
     * Open socket.
     */
    pr = (struct PFwdPrivate *) smalloc(sizeof(struct PFwdPrivate));
    pr->fn = &fn_table;
    pr->c = NULL;
    strcpy(pr->hostname, desthost);
    pr->port = destport;
    pr->throttled = pr->throttle_override = 0;
    pr->ready = 0;
    pr->waiting = NULL;







|







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
    char *err;
    struct PFwdPrivate *pr;
    Socket s;

    /*
     * Open socket.
     */
    pr = snew(struct PFwdPrivate);
    pr->fn = &fn_table;
    pr->c = NULL;
    strcpy(pr->hostname, desthost);
    pr->port = destport;
    pr->throttled = pr->throttle_override = 0;
    pr->ready = 0;
    pr->waiting = NULL;
Changes to printing.c.
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
};

static char *printer_add_enum(int param, char *buffer,
                              int offset, int *nprinters_ptr)
{
    DWORD needed, nprinters;

    buffer = srealloc(buffer, offset+512);

    /*
     * Exploratory call to EnumPrinters to determine how much space
     * we'll need for the output. Discard the return value since it
     * will almost certainly be a failure due to lack of space.
     */
    EnumPrinters(param, NULL, ENUM_LEVEL, buffer+offset, 512,
		 &needed, &nprinters);

    if (needed < 512)
        needed = 512;

    buffer = srealloc(buffer, offset+needed);

    if (EnumPrinters(param, NULL, ENUM_LEVEL, buffer+offset,
                     needed, &needed, &nprinters) == 0)
        return NULL;

    *nprinters_ptr += nprinters;

    return buffer;
}

printer_enum *printer_start_enum(int *nprinters_ptr)
{
    printer_enum *ret = smalloc(sizeof(printer_enum));
    char *buffer = NULL, *retval;

    *nprinters_ptr = 0;		       /* default return value */
    buffer = smalloc(512);

    retval = printer_add_enum(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
			      buffer, 0, nprinters_ptr);
    if (!retval)
        goto error;
    else
        buffer = retval;







|












|












|



|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
};

static char *printer_add_enum(int param, char *buffer,
                              int offset, int *nprinters_ptr)
{
    DWORD needed, nprinters;

    buffer = sresize(buffer, offset+512, char);

    /*
     * Exploratory call to EnumPrinters to determine how much space
     * we'll need for the output. Discard the return value since it
     * will almost certainly be a failure due to lack of space.
     */
    EnumPrinters(param, NULL, ENUM_LEVEL, buffer+offset, 512,
		 &needed, &nprinters);

    if (needed < 512)
        needed = 512;

    buffer = sresize(buffer, offset+needed, char);

    if (EnumPrinters(param, NULL, ENUM_LEVEL, buffer+offset,
                     needed, &needed, &nprinters) == 0)
        return NULL;

    *nprinters_ptr += nprinters;

    return buffer;
}

printer_enum *printer_start_enum(int *nprinters_ptr)
{
    printer_enum *ret = snew(printer_enum);
    char *buffer = NULL, *retval;

    *nprinters_ptr = 0;		       /* default return value */
    buffer = snewn(512, char);

    retval = printer_add_enum(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
			      buffer, 0, nprinters_ptr);
    if (!retval)
        goto error;
    else
        buffer = retval;
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
	return;
    sfree(pe->info);
    sfree(pe);
}

printer_job *printer_start_job(char *printer)
{
    printer_job *ret = smalloc(sizeof(printer_job));
    DOC_INFO_1 docinfo;
    int jobstarted = 0, pagestarted = 0;

    ret->hprinter = NULL;
    if (!OpenPrinter(printer, &ret->hprinter, NULL))
	goto error;








|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
	return;
    sfree(pe->info);
    sfree(pe);
}

printer_job *printer_start_job(char *printer)
{
    printer_job *ret = snew(printer_job);
    DOC_INFO_1 docinfo;
    int jobstarted = 0, pagestarted = 0;

    ret->hprinter = NULL;
    if (!OpenPrinter(printer, &ret->hprinter, NULL))
	goto error;

Changes to proxy.c.
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
	proxy_for_destination(addr, hostname, port, cfg))
    {
	Proxy_Socket ret;
	Proxy_Plug pplug;
	SockAddr proxy_addr;
	char *proxy_canonical_name, *err;

	ret = smalloc(sizeof(struct Socket_proxy_tag));
	ret->fn = &socket_fn_table;
	ret->cfg = *cfg;	       /* STRUCTURE COPY */
	ret->plug = plug;
	ret->remote_addr = addr;
	ret->remote_port = port;

	ret->error = NULL;







|







374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
	proxy_for_destination(addr, hostname, port, cfg))
    {
	Proxy_Socket ret;
	Proxy_Plug pplug;
	SockAddr proxy_addr;
	char *proxy_canonical_name, *err;

	ret = snew(struct Socket_proxy_tag);
	ret->fn = &socket_fn_table;
	ret->cfg = *cfg;	       /* STRUCTURE COPY */
	ret->plug = plug;
	ret->remote_addr = addr;
	ret->remote_port = port;

	ret->error = NULL;
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
	} else {
	    ret->error = "Proxy error: Unknown proxy method";
	    return (Socket) ret;
	}

	/* create the proxy plug to map calls from the actual
	 * socket into our proxy socket layer */
	pplug = smalloc(sizeof(struct Plug_proxy_tag));
	pplug->fn = &plug_fn_table;
	pplug->proxy_socket = ret;

	/* look-up proxy */
	proxy_addr = sk_namelookup(cfg->proxy_host,
				   &proxy_canonical_name);
	if ((err = sk_addr_error(proxy_addr)) != NULL) {







|







409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
	} else {
	    ret->error = "Proxy error: Unknown proxy method";
	    return (Socket) ret;
	}

	/* create the proxy plug to map calls from the actual
	 * socket into our proxy socket layer */
	pplug = snew(struct Plug_proxy_tag);
	pplug->fn = &plug_fn_table;
	pplug->proxy_socket = ret;

	/* look-up proxy */
	proxy_addr = sk_namelookup(cfg->proxy_host,
				   &proxy_canonical_name);
	if ((err = sk_addr_error(proxy_addr)) != NULL) {
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
	if (p->state == 1) {

	    int min_ver, maj_ver, status;

	    /* get the status line */
	    len = bufchain_size(&p->pending_input_data);
	    assert(len > 0);	       /* or we wouldn't be here */
	    data = smalloc(len);
	    bufchain_fetch(&p->pending_input_data, data, len);

	    eol = get_line_end(data, len);
	    if (eol < 0) {
		sfree(data);
		return 1;
	    }







|







575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
	if (p->state == 1) {

	    int min_ver, maj_ver, status;

	    /* get the status line */
	    len = bufchain_size(&p->pending_input_data);
	    assert(len > 0);	       /* or we wouldn't be here */
	    data = snewn(len, char);
	    bufchain_fetch(&p->pending_input_data, data, len);

	    eol = get_line_end(data, len);
	    if (eol < 0) {
		sfree(data);
		return 1;
	    }
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637

	    /* get headers. we're done when we get a
	     * header of length 2, (ie. just "\r\n")
	     */

	    len = bufchain_size(&p->pending_input_data);
	    assert(len > 0);	       /* or we wouldn't be here */
	    data = smalloc(len);
	    datap = data;
	    bufchain_fetch(&p->pending_input_data, data, len);

	    eol = get_line_end(datap, len);
	    if (eol < 0) {
		sfree(data);
		return 1;







|







623
624
625
626
627
628
629
630
631
632
633
634
635
636
637

	    /* get headers. we're done when we get a
	     * header of length 2, (ie. just "\r\n")
	     */

	    len = bufchain_size(&p->pending_input_data);
	    assert(len > 0);	       /* or we wouldn't be here */
	    data = snewn(len, char);
	    datap = data;
	    bufchain_fetch(&p->pending_input_data, data, len);

	    eol = get_line_end(datap, len);
	    if (eol < 0) {
		sfree(data);
		return 1;
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
	    sk_getaddr(p->remote_addr, hostname, lenof(hostname));
	    namelen = strlen(hostname) + 1;   /* include the NUL */
	    addr[0] = addr[1] = addr[2] = 0;
	    addr[3] = 1;
	}

	length = strlen(p->cfg.proxy_username) + namelen + 9;
	command = (char*) smalloc(length);
	strcpy(command + 8, p->cfg.proxy_username);

	command[0] = 4; /* version 4 */
	command[1] = 1; /* CONNECT command */

	/* port */
	command[2] = (char) (p->remote_port >> 8) & 0xff;







|







698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
	    sk_getaddr(p->remote_addr, hostname, lenof(hostname));
	    namelen = strlen(hostname) + 1;   /* include the NUL */
	    addr[0] = addr[1] = addr[2] = 0;
	    addr[3] = 1;
	}

	length = strlen(p->cfg.proxy_username) + namelen + 9;
	command = snewn(length, char);
	strcpy(command + 8, p->cfg.proxy_username);

	command[0] = 4; /* version 4 */
	command[1] = 1; /* CONNECT command */

	/* port */
	command[2] = (char) (p->remote_port >> 8) & 0xff;
Changes to psftp.c.
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
	    if (names->nnames == 0) {
		fxp_free_names(names);
		break;
	    }

	    if (nnames + names->nnames >= namesize) {
		namesize += names->nnames + 128;
		ournames =
		    srealloc(ournames, namesize * sizeof(*ournames));
	    }

	    for (i = 0; i < names->nnames; i++)
		ournames[nnames++] = fxp_dup_name(&names->names[i]);

	    fxp_free_names(names);
	}







|
<







241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
	    if (names->nnames == 0) {
		fxp_free_names(names);
		break;
	    }

	    if (nnames + names->nnames >= namesize) {
		namesize += names->nnames + 128;
		ournames = sresize(ournames, namesize, struct fxp_name *);

	    }

	    for (i = 0; i < names->nnames; i++)
		ournames[nnames++] = fxp_dup_name(&names->names[i]);

	    fxp_free_names(names);
	}
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
		      (LPTSTR)&message, 0, NULL);
	i = strcspn((char *)message, "\n");
	printf("lcd: unable to change directory: %.*s\n", i, (LPCTSTR)message);
	LocalFree(message);
	return 0;
    }

    currdir = smalloc(256);
    len = GetCurrentDirectory(256, currdir);
    if (len > 256)
	currdir = srealloc(currdir, len);
    GetCurrentDirectory(len, currdir);
    printf("New local directory is %s\n", currdir);
    sfree(currdir);

    return 1;
}

static int sftp_cmd_lpwd(struct sftp_command *cmd)
{
    char *currdir;
    int len;

    currdir = smalloc(256);
    len = GetCurrentDirectory(256, currdir);
    if (len > 256)
	currdir = srealloc(currdir, len);
    GetCurrentDirectory(len, currdir);
    printf("Current local directory is %s\n", currdir);
    sfree(currdir);

    return 1;
}








|


|












|


|







929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
		      (LPTSTR)&message, 0, NULL);
	i = strcspn((char *)message, "\n");
	printf("lcd: unable to change directory: %.*s\n", i, (LPCTSTR)message);
	LocalFree(message);
	return 0;
    }

    currdir = snewn(256, char);
    len = GetCurrentDirectory(256, currdir);
    if (len > 256)
	currdir = sresize(currdir, len, char);
    GetCurrentDirectory(len, currdir);
    printf("New local directory is %s\n", currdir);
    sfree(currdir);

    return 1;
}

static int sftp_cmd_lpwd(struct sftp_command *cmd)
{
    char *currdir;
    int len;

    currdir = snewn(256, char);
    len = GetCurrentDirectory(256, currdir);
    if (len > 256)
	currdir = sresize(currdir, len, char);
    GetCurrentDirectory(len, currdir);
    printf("Current local directory is %s\n", currdir);
    sfree(currdir);

    return 1;
}

1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
    int quoting;

    if ((mode == 0) || (modeflags & 1)) {
	printf("psftp> ");
    }
    fflush(stdout);

    cmd = smalloc(sizeof(struct sftp_command));
    cmd->words = NULL;
    cmd->nwords = 0;
    cmd->wordssize = 0;

    line = NULL;
    linesize = linelen = 0;
    while (1) {
	int len;
	char *ret;

	linesize += 512;
	line = srealloc(line, linesize);
	ret = fgets(line + linelen, linesize - linelen, fp);

	if (!ret || (linelen == 0 && line[0] == '\0')) {
	    cmd->obey = sftp_cmd_quit;
	    if ((mode == 0) || (modeflags & 1))
		printf("quit\n");
	    return cmd;		       /* eof */







|











|







1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
    int quoting;

    if ((mode == 0) || (modeflags & 1)) {
	printf("psftp> ");
    }
    fflush(stdout);

    cmd = snew(struct sftp_command);
    cmd->words = NULL;
    cmd->nwords = 0;
    cmd->wordssize = 0;

    line = NULL;
    linesize = linelen = 0;
    while (1) {
	int len;
	char *ret;

	linesize += 512;
	line = sresize(line, linesize, char);
	ret = fgets(line + linelen, linesize - linelen, fp);

	if (!ret || (linelen == 0 && line[0] == '\0')) {
	    cmd->obey = sftp_cmd_quit;
	    if ((mode == 0) || (modeflags & 1))
		printf("quit\n");
	    return cmd;		       /* eof */
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
    if (*p == '!') {
	/*
	 * Special case: the ! command. This is always parsed as
	 * exactly two words: one containing the !, and the second
	 * containing everything else on the line.
	 */
	cmd->nwords = cmd->wordssize = 2;
	cmd->words = srealloc(cmd->words, cmd->wordssize * sizeof(char *));
	cmd->words[0] = "!";
	cmd->words[1] = p+1;
    } else {

	/*
	 * Parse the command line into words. The syntax is:
	 *  - double quotes are removed, but cause spaces within to be







|







1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
    if (*p == '!') {
	/*
	 * Special case: the ! command. This is always parsed as
	 * exactly two words: one containing the !, and the second
	 * containing everything else on the line.
	 */
	cmd->nwords = cmd->wordssize = 2;
	cmd->words = sresize(cmd->words, cmd->wordssize, char *);
	cmd->words[0] = "!";
	cmd->words[1] = p+1;
    } else {

	/*
	 * Parse the command line into words. The syntax is:
	 *  - double quotes are removed, but cause spaces within to be
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
		    *r++ = *p++;
	    }
	    if (*p)
		p++;		       /* skip over the whitespace */
	    *r = '\0';
	    if (cmd->nwords >= cmd->wordssize) {
		cmd->wordssize = cmd->nwords + 16;
		cmd->words =
		    srealloc(cmd->words, cmd->wordssize * sizeof(char *));
	    }
	    cmd->words[cmd->nwords++] = q;
	}
    }

    /*
     * Now parse the first word and assign a function.







|
<







1336
1337
1338
1339
1340
1341
1342
1343

1344
1345
1346
1347
1348
1349
1350
		    *r++ = *p++;
	    }
	    if (*p)
		p++;		       /* skip over the whitespace */
	    *r = '\0';
	    if (cmd->nwords >= cmd->wordssize) {
		cmd->wordssize = cmd->nwords + 16;
		cmd->words = sresize(cmd->words, cmd->wordssize, char *);

	    }
	    cmd->words[cmd->nwords++] = q;
	}
    }

    /*
     * Now parse the first word and assign a function.
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
	p += used;
	len -= used;
    }

    if (len > 0) {
	if (pendsize < pendlen + len) {
	    pendsize = pendlen + len + 4096;
	    pending = (pending ? srealloc(pending, pendsize) :
		       smalloc(pendsize));
	    if (!pending)
		fatalbox("Out of memory");
	}
	memcpy(pending + pendlen, p, len);
	pendlen += len;
    }

    return 0;
}







|
<
<
<







1558
1559
1560
1561
1562
1563
1564
1565



1566
1567
1568
1569
1570
1571
1572
	p += used;
	len -= used;
    }

    if (len > 0) {
	if (pendsize < pendlen + len) {
	    pendsize = pendlen + len + 4096;
	    pending = sresize(pending, pendsize, unsigned char);



	}
	memcpy(pending + pendlen, p, len);
	pendlen += len;
    }

    return 0;
}
Changes to puttygen.c.
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
{
    unsigned char *pub_blob;
    char *buffer, *p;
    int pub_len;
    int i;

    pub_blob = key->alg->public_blob(key->data, &pub_len);
    buffer = smalloc(strlen(key->alg->name) + 4 * ((pub_len + 2) / 3) +
		     strlen(key->comment) + 3);
    strcpy(buffer, key->alg->name);
    p = buffer + strlen(buffer);
    *p++ = ' ';
    i = 0;
    while (i < pub_len) {
	int n = (pub_len - i < 3 ? pub_len - i : 3);
	base64_encode_atom(pub_blob + i, n, p);







|
|







385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
{
    unsigned char *pub_blob;
    char *buffer, *p;
    int pub_len;
    int i;

    pub_blob = key->alg->public_blob(key->data, &pub_len);
    buffer = snewn(strlen(key->alg->name) + 4 * ((pub_len + 2) / 3) +
		   strlen(key->comment) + 3, char);
    strcpy(buffer, key->alg->name);
    p = buffer + strlen(buffer);
    *p++ = ' ';
    i = 0;
    while (i < pub_len) {
	int n = (pub_len - i < 3 ? pub_len - i : 3);
	base64_encode_atom(pub_blob + i, n, p);
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
             * if the help file isn't present.
             */
        }
        requested_help = FALSE;
	SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG,
		    (LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(200)));

	state = smalloc(sizeof(*state));
	state->generation_thread_exists = FALSE;
	state->collecting_entropy = FALSE;
	state->entropy = NULL;
	state->key_exists = FALSE;
	SetWindowLong(hwnd, GWL_USERDATA, (LONG) state);
	{
	    HMENU menu, menu1;







|







816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
             * if the help file isn't present.
             */
        }
        requested_help = FALSE;
	SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG,
		    (LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(200)));

	state = snew(struct MainDlgState);
	state->generation_thread_exists = FALSE;
	state->collecting_entropy = FALSE;
	state->entropy = NULL;
	state->key_exists = FALSE;
	SetWindowLong(hwnd, GWL_USERDATA, (LONG) state);
	{
	    HMENU menu, menu1;
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
		state->collecting_entropy = FALSE;

		SetDlgItemText(hwnd, IDC_GENERATING, generating_msg);
		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0,
				   MAKELPARAM(0, PROGRESSRANGE));
		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0);

		params = smalloc(sizeof(*params));
		params->progressbar = GetDlgItem(hwnd, IDC_PROGRESS);
		params->dialog = hwnd;
		params->keysize = state->keysize;
		params->is_dsa = state->is_dsa;
		params->key = &state->key;
		params->dsskey = &state->dsskey;








|







970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
		state->collecting_entropy = FALSE;

		SetDlgItemText(hwnd, IDC_GENERATING, generating_msg);
		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0,
				   MAKELPARAM(0, PROGRESSRANGE));
		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0);

		params = snew(struct rsa_key_thread_params);
		params->progressbar = GetDlgItem(hwnd, IDC_PROGRESS);
		params->dialog = hwnd;
		params->keysize = state->keysize;
		params->is_dsa = state->is_dsa;
		params->key = &state->key;
		params->dsskey = &state->dsskey;

1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
		state = (struct MainDlgState *)
		    GetWindowLong(hwnd, GWL_USERDATA);
		if (state->key_exists) {
		    HWND editctl = GetDlgItem(hwnd, IDC_COMMENTEDIT);
		    int len = GetWindowTextLength(editctl);
		    if (*state->commentptr)
			sfree(*state->commentptr);
		    *state->commentptr = smalloc(len + 1);
		    GetWindowText(editctl, *state->commentptr, len + 1);
		    if (state->ssh2) {
			setupbigedit2(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC,
				      &state->ssh2key);
		    } else {
			setupbigedit1(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC,
				      &state->key);







|







1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
		state = (struct MainDlgState *)
		    GetWindowLong(hwnd, GWL_USERDATA);
		if (state->key_exists) {
		    HWND editctl = GetDlgItem(hwnd, IDC_COMMENTEDIT);
		    int len = GetWindowTextLength(editctl);
		    if (*state->commentptr)
			sfree(*state->commentptr);
		    *state->commentptr = snewn(len + 1, char);
		    GetWindowText(editctl, *state->commentptr, len + 1);
		    if (state->ssh2) {
			setupbigedit2(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC,
				      &state->ssh2key);
		    } else {
			setupbigedit1(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC,
				      &state->key);
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
		 * method, we require two words per mouse movement,
		 * so with 2 bits per mouse movement we expect 2
		 * bits every 2 words.
		 */
		state->entropy_required = (state->keysize / 2) * 2;
		state->entropy_got = 0;
		state->entropy_size = (state->entropy_required *
				       sizeof(*state->entropy));
		state->entropy = smalloc(state->entropy_size);

		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0,
				   MAKELPARAM(0, state->entropy_required));
		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0);
	    }
	    break;
	  case IDC_SAVE:







|
|







1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
		 * method, we require two words per mouse movement,
		 * so with 2 bits per mouse movement we expect 2
		 * bits every 2 words.
		 */
		state->entropy_required = (state->keysize / 2) * 2;
		state->entropy_got = 0;
		state->entropy_size = (state->entropy_required *
				       sizeof(unsigned));
		state->entropy = snewn(state->entropy_required, unsigned);

		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0,
				   MAKELPARAM(0, state->entropy_required));
		SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0);
	    }
	    break;
	  case IDC_SAVE:
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
	}
	/*
	 * Invent a comment for the key. We'll do this by including
	 * the date in it. This will be so horrifyingly ugly that
	 * the user will immediately want to change it, which is
	 * what we want :-)
	 */
	*state->commentptr = smalloc(30);
	{
	    time_t t;
	    struct tm *tm;
	    time(&t);
	    tm = localtime(&t);
	    if (state->is_dsa)
		strftime(*state->commentptr, 30, "dsa-key-%Y%m%d", tm);







|







1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
	}
	/*
	 * Invent a comment for the key. We'll do this by including
	 * the date in it. This will be so horrifyingly ugly that
	 * the user will immediately want to change it, which is
	 * what we want :-)
	 */
	*state->commentptr = snewn(30, char);
	{
	    time_t t;
	    struct tm *tm;
	    time(&t);
	    tm = localtime(&t);
	    if (state->is_dsa)
		strftime(*state->commentptr, 30, "dsa-key-%Y%m%d", tm);
Changes to puttymem.h.
21
22
23
24
25
26
27
28
29




30
31
32
33
34
35
36
37
#define sfree safefree
#endif

void *safemalloc(size_t);
void *saferealloc(void *, size_t);
void safefree(void *);


/* smalloc a thing */




#define smalloca(type) ((type *) smalloc (sizeof (type)))
/* smalloc a copy of a thing */
#define smallocc(ptr) memcpy (smalloc (sizeof (*ptr)), ptr, sizeof (*ptr))
/* smalloc n things */
#define smallocn(n,type) ((type *) smalloc ((n) * sizeof (type)))


#endif







|
|
>
>
>
>
|
<
<
<
|
|


21
22
23
24
25
26
27
28
29
30
31
32
33
34



35
36
37
38
#define sfree safefree
#endif

void *safemalloc(size_t);
void *saferealloc(void *, size_t);
void safefree(void *);

/*
 * Direct use of smalloc within the code should be avoided where
 * possible, in favour of these type-casting macros which ensure
 * you don't mistakenly allocate enough space for one sort of
 * structure and assign it to a different sort of pointer.
 */
#define snew(type) ((type *)smalloc(sizeof(type)))



#define snewn(n, type) ((type *)smalloc((n)*sizeof(type)))
#define sresize(ptr, n, type) ((type *)srealloc(ptr, (n)*sizeof(type)))

#endif
Changes to raw.c.
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
	raw_receive,
	raw_sent
    };
    SockAddr addr;
    char *err;
    Raw raw;

    raw = smalloc(sizeof(*raw));
    raw->fn = &fn_table;
    raw->s = NULL;
    *backend_handle = raw;

    raw->frontend = frontend_handle;

    /*







|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
	raw_receive,
	raw_sent
    };
    SockAddr addr;
    char *err;
    Raw raw;

    raw = snew(struct raw_backend_data);
    raw->fn = &fn_table;
    raw->s = NULL;
    *backend_handle = raw;

    raw->frontend = frontend_handle;

    /*
Changes to rlogin.c.
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
	rlogin_receive,
	rlogin_sent
    };
    SockAddr addr;
    char *err;
    Rlogin rlogin;

    rlogin = smalloc(sizeof(*rlogin));
    rlogin->fn = &fn_table;
    rlogin->s = NULL;
    rlogin->frontend = frontend_handle;
    rlogin->term_width = cfg->width;
    rlogin->term_height = cfg->height;
    rlogin->firstbyte = 1;
    *backend_handle = rlogin;







|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
	rlogin_receive,
	rlogin_sent
    };
    SockAddr addr;
    char *err;
    Rlogin rlogin;

    rlogin = snew(struct rlogin_tag);
    rlogin->fn = &fn_table;
    rlogin->s = NULL;
    rlogin->frontend = frontend_handle;
    rlogin->term_width = cfg->width;
    rlogin->term_height = cfg->height;
    rlogin->firstbyte = 1;
    *backend_handle = rlogin;
Changes to scp.c.
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
	p += used;
	len -= used;
    }

    if (len > 0) {
	if (pendsize < pendlen + len) {
	    pendsize = pendlen + len + 4096;
	    pending = (pending ? srealloc(pending, pendsize) :
		       smalloc(pendsize));
	    if (!pending)
		fatalbox("Out of memory");
	}
	memcpy(pending + pendlen, p, len);
	pendlen += len;
    }








|
<







349
350
351
352
353
354
355
356

357
358
359
360
361
362
363
	p += used;
	len -= used;
    }

    if (len > 0) {
	if (pendsize < pendlen + len) {
	    pendsize = pendlen + len + 4096;
	    pending = sresize(pending, pendsize, unsigned char);

	    if (!pending)
		fatalbox("Out of memory");
	}
	memcpy(pending + pendlen, p, len);
	pendlen += len;
    }

541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
    if (user != NULL && user[0] != '\0') {
	strncpy(cfg.username, user, sizeof(cfg.username) - 1);
	cfg.username[sizeof(cfg.username) - 1] = '\0';
    } else if (cfg.username[0] == '\0') {
	namelen = 0;
	if (GetUserName(user, &namelen) == FALSE)
	    bump("Empty user name");
	user = smalloc(namelen * sizeof(char));
	GetUserName(user, &namelen);
	if (verbose)
	    tell_user(stderr, "Guessing user name: %s", user);
	strncpy(cfg.username, user, sizeof(cfg.username) - 1);
	cfg.username[sizeof(cfg.username) - 1] = '\0';
	free(user);
    }







|







540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
    if (user != NULL && user[0] != '\0') {
	strncpy(cfg.username, user, sizeof(cfg.username) - 1);
	cfg.username[sizeof(cfg.username) - 1] = '\0';
    } else if (cfg.username[0] == '\0') {
	namelen = 0;
	if (GetUserName(user, &namelen) == FALSE)
	    bump("Empty user name");
	user = snewn(namelen, char);
	GetUserName(user, &namelen);
	if (verbose)
	    tell_user(stderr, "Guessing user name: %s", user);
	strncpy(cfg.username, user, sizeof(cfg.username) - 1);
	cfg.username[sizeof(cfg.username) - 1] = '\0';
	free(user);
    }
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
	    if (names->nnames == 0) {
		fxp_free_names(names);
		break;
	    }

	    if (nnames + names->nnames >= namesize) {
		namesize += names->nnames + 128;
		ournames =
		    srealloc(ournames, namesize * sizeof(*ournames));
	    }

	    for (i = 0; i < names->nnames; i++)
		ournames[nnames++] = names->names[i];

	    names->nnames = 0;	       /* prevent free_names */
	    fxp_free_names(names);







|
<







772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
	    if (names->nnames == 0) {
		fxp_free_names(names);
		break;
	    }

	    if (nnames + names->nnames >= namesize) {
		namesize += names->nnames + 128;
		ournames = sresize(ournames, namesize, struct fxp_name);

	    }

	    for (i = 0; i < names->nnames; i++)
		ournames[nnames++] = names->names[i];

	    names->nnames = 0;	       /* prevent free_names */
	    fxp_free_names(names);
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
	/*
	 * It's possible that the source string we've been given
	 * contains a wildcard. If so, we must split the directory
	 * away from the wildcard itself (throwing an error if any
	 * wildcardness comes before the final slash) and arrange
	 * things so that a dirstack entry will be set up.
	 */
	newsource = smalloc(1+strlen(source));
	if (!wc_unescape(newsource, source)) {
	    /* Yes, here we go; it's a wildcard. Bah. */
	    char *dupsource, *lastpart, *dirpart, *wildcard;
	    dupsource = dupstr(source);
	    lastpart = stripslashes(dupsource, 0);
	    wildcard = dupstr(lastpart);
	    *lastpart = '\0';







|







1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
	/*
	 * It's possible that the source string we've been given
	 * contains a wildcard. If so, we must split the directory
	 * away from the wildcard itself (throwing an error if any
	 * wildcardness comes before the final slash) and arrange
	 * things so that a dirstack entry will be set up.
	 */
	newsource = snewn(1+strlen(source), char);
	if (!wc_unescape(newsource, source)) {
	    /* Yes, here we go; it's a wildcard. Bah. */
	    char *dupsource, *lastpart, *dirpart, *wildcard;
	    dupsource = dupstr(source);
	    lastpart = stripslashes(dupsource, 0);
	    wildcard = dupstr(lastpart);
	    *lastpart = '\0';
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
	    /*
	     * Now we have separated our string into dupsource (the
	     * directory part) and wildcard. Both of these will
	     * need freeing at some point. Next step is to remove
	     * wildcard escapes from the directory part, throwing
	     * an error if it contains a real wildcard.
	     */
	    dirpart = smalloc(1+strlen(dupsource));
	    if (!wc_unescape(dirpart, dupsource)) {
		tell_user(stderr, "%s: multiple-level wildcards unsupported",
			  source);
		errs++;
		sfree(dirpart);
		sfree(wildcard);
		sfree(dupsource);







|







1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
	    /*
	     * Now we have separated our string into dupsource (the
	     * directory part) and wildcard. Both of these will
	     * need freeing at some point. Next step is to remove
	     * wildcard escapes from the directory part, throwing
	     * an error if it contains a real wildcard.
	     */
	    dirpart = snewn(1+strlen(dupsource), char);
	    if (!wc_unescape(dirpart, dupsource)) {
		tell_user(stderr, "%s: multiple-level wildcards unsupported",
			  source);
		errs++;
		sfree(dirpart);
		sfree(wildcard);
		sfree(dupsource);
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
		}
		if (names->nnames == 0) {
		    fxp_free_names(names);
		    break;
		}
		if (nnames + names->nnames >= namesize) {
		    namesize += names->nnames + 128;
		    ournames =
			srealloc(ournames, namesize * sizeof(*ournames));
		}
		for (i = 0; i < names->nnames; i++)
		    ournames[nnames++] = names->names[i];
		names->nnames = 0;	       /* prevent free_names */
		fxp_free_names(names);
	    }
	    fxp_close(dirhandle);

	    newitem = smalloc(sizeof(struct scp_sftp_dirstack));
	    newitem->next = scp_sftp_dirstack_head;
	    newitem->names = ournames;
	    newitem->namepos = 0;
	    newitem->namelen = nnames;
	    if (must_free_fname)
		newitem->dirpath = fname;
	    else







|
<








|







1300
1301
1302
1303
1304
1305
1306
1307

1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
		}
		if (names->nnames == 0) {
		    fxp_free_names(names);
		    break;
		}
		if (nnames + names->nnames >= namesize) {
		    namesize += names->nnames + 128;
		    ournames = sresize(ournames, namesize, struct fxp_name);

		}
		for (i = 0; i < names->nnames; i++)
		    ournames[nnames++] = names->names[i];
		names->nnames = 0;	       /* prevent free_names */
		fxp_free_names(names);
	    }
	    fxp_close(dirhandle);

	    newitem = snew(struct scp_sftp_dirstack);
	    newitem->next = scp_sftp_dirstack_head;
	    newitem->names = ournames;
	    newitem->namepos = 0;
	    newitem->namelen = nnames;
	    if (must_free_fname)
		newitem->dirpath = fname;
	    else
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
	    i = 0;
	    action = ch;
	    do {
		if (ssh_scp_recv(&ch, 1) <= 0)
		    bump("Lost connection");
		if (i >= bufsize) {
		    bufsize = i + 128;
		    act->buf = srealloc(act->buf, bufsize);
		}
		act->buf[i++] = ch;
	    } while (ch != '\n');
	    act->buf[i - 1] = '\0';
	    switch (action) {
	      case '\01':		       /* error */
		tell_user(stderr, "%s\n", act->buf);







|







1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
	    i = 0;
	    action = ch;
	    do {
		if (ssh_scp_recv(&ch, 1) <= 0)
		    bump("Lost connection");
		if (i >= bufsize) {
		    bufsize = i + 128;
		    act->buf = sresize(act->buf, bufsize, char);
		}
		act->buf[i++] = ch;
	    } while (ch != '\n');
	    act->buf[i - 1] = '\0';
	    switch (action) {
	      case '\01':		       /* error */
		tell_user(stderr, "%s\n", act->buf);
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
	user = NULL;
    } else {
	*host++ = '\0';
	if (*user == '\0')
	    user = NULL;
    }

    cmd = smalloc(4 * strlen(src) + 100);
    strcpy(cmd, "ls -la '");
    p = cmd + strlen(cmd);
    for (q = src; *q; q++) {
	if (*q == '\'') {
	    *p++ = '\'';
	    *p++ = '\\';
	    *p++ = '\'';







|







2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
	user = NULL;
    } else {
	*host++ = '\0';
	if (*user == '\0')
	    user = NULL;
    }

    cmd = snewn(4 * strlen(src) + 100, char);
    strcpy(cmd, "ls -la '");
    p = cmd + strlen(cmd);
    for (q = src; *q; q++) {
	if (*q == '\'') {
	    *p++ = '\'';
	    *p++ = '\\';
	    *p++ = '\'';
Changes to settings.c.
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
	if ((handle = enum_settings_start()) != NULL) {
	    do {
		ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf));
		if (ret) {
		    int len = strlen(otherbuf) + 1;
		    if (bufsize < buflen + len) {
			bufsize = buflen + len + 2048;
			list->buffer = srealloc(list->buffer, bufsize);
		    }
		    strcpy(list->buffer + buflen, otherbuf);
		    buflen += strlen(list->buffer + buflen) + 1;
		}
	    } while (ret);
	    enum_settings_finish(handle);
	}
	list->buffer = srealloc(list->buffer, buflen + 1);
	list->buffer[buflen] = '\0';

	/*
	 * Now set up the list of sessions. Note that "Default
	 * Settings" must always be claimed to exist, even if it
	 * doesn't really.
	 */

	p = list->buffer;
	list->nsessions = 1;	       /* "Default Settings" counts as one */
	while (*p) {
	    if (strcmp(p, "Default Settings"))
		list->nsessions++;
	    while (*p)
		p++;
	    p++;
	}

	list->sessions = smalloc((list->nsessions + 1) * sizeof(char *));
	list->sessions[0] = "Default Settings";
	p = list->buffer;
	i = 1;
	while (*p) {
	    if (strcmp(p, "Default Settings"))
		list->sessions[i++] = p;
	    while (*p)







|







|


















|







668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
	if ((handle = enum_settings_start()) != NULL) {
	    do {
		ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf));
		if (ret) {
		    int len = strlen(otherbuf) + 1;
		    if (bufsize < buflen + len) {
			bufsize = buflen + len + 2048;
			list->buffer = sresize(list->buffer, bufsize, char);
		    }
		    strcpy(list->buffer + buflen, otherbuf);
		    buflen += strlen(list->buffer + buflen) + 1;
		}
	    } while (ret);
	    enum_settings_finish(handle);
	}
	list->buffer = sresize(list->buffer, buflen + 1, char);
	list->buffer[buflen] = '\0';

	/*
	 * Now set up the list of sessions. Note that "Default
	 * Settings" must always be claimed to exist, even if it
	 * doesn't really.
	 */

	p = list->buffer;
	list->nsessions = 1;	       /* "Default Settings" counts as one */
	while (*p) {
	    if (strcmp(p, "Default Settings"))
		list->nsessions++;
	    while (*p)
		p++;
	    p++;
	}

	list->sessions = snewn(list->nsessions + 1, char *);
	list->sessions[0] = "Default Settings";
	p = list->buffer;
	i = 1;
	while (*p) {
	    if (strcmp(p, "Default Settings"))
		list->sessions[i++] = p;
	    while (*p)
Changes to sftp.c.
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* ----------------------------------------------------------------------
 * SFTP packet construction functions.
 */
static void sftp_pkt_ensure(struct sftp_packet *pkt, int length)
{
    if (pkt->maxlen < length) {
	pkt->maxlen = length + 256;
	pkt->data = srealloc(pkt->data, pkt->maxlen);
    }
}
static void sftp_pkt_adddata(struct sftp_packet *pkt, void *data, int len)
{
    pkt->length += len;
    sftp_pkt_ensure(pkt, pkt->length);
    memcpy(pkt->data + pkt->length - len, data, len);
}
static void sftp_pkt_addbyte(struct sftp_packet *pkt, unsigned char byte)
{
    sftp_pkt_adddata(pkt, &byte, 1);
}
static struct sftp_packet *sftp_pkt_init(int pkt_type)
{
    struct sftp_packet *pkt;
    pkt = smalloc(sizeof(struct sftp_packet));
    pkt->data = NULL;
    pkt->savedpos = -1;
    pkt->length = 0;
    pkt->maxlen = 0;
    sftp_pkt_addbyte(pkt, (unsigned char) pkt_type);
    return pkt;
}







|















|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* ----------------------------------------------------------------------
 * SFTP packet construction functions.
 */
static void sftp_pkt_ensure(struct sftp_packet *pkt, int length)
{
    if (pkt->maxlen < length) {
	pkt->maxlen = length + 256;
	pkt->data = sresize(pkt->data, pkt->maxlen, char);
    }
}
static void sftp_pkt_adddata(struct sftp_packet *pkt, void *data, int len)
{
    pkt->length += len;
    sftp_pkt_ensure(pkt, pkt->length);
    memcpy(pkt->data + pkt->length - len, data, len);
}
static void sftp_pkt_addbyte(struct sftp_packet *pkt, unsigned char byte)
{
    sftp_pkt_adddata(pkt, &byte, 1);
}
static struct sftp_packet *sftp_pkt_init(int pkt_type)
{
    struct sftp_packet *pkt;
    pkt = snew(struct sftp_packet);
    pkt->data = NULL;
    pkt->savedpos = -1;
    pkt->length = 0;
    pkt->maxlen = 0;
    sftp_pkt_addbyte(pkt, (unsigned char) pkt_type);
    return pkt;
}
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
{
    struct sftp_packet *pkt;
    char x[4];

    if (!sftp_recvdata(x, 4))
	return NULL;

    pkt = smalloc(sizeof(struct sftp_packet));
    pkt->savedpos = 0;
    pkt->length = pkt->maxlen = GET_32BIT(x);
    pkt->data = smalloc(pkt->length);

    if (!sftp_recvdata(pkt->data, pkt->length)) {
	sftp_pkt_free(pkt);
	return NULL;
    }

    pkt->type = sftp_pkt_getbyte(pkt);

    return pkt;
}

/* ----------------------------------------------------------------------
 * String handling routines.
 */

static char *mkstr(char *s, int len)
{
    char *p = smalloc(len + 1);
    memcpy(p, s, len);
    p[len] = '\0';
    return p;
}

/* ----------------------------------------------------------------------
 * SFTP primitives.







|


|

















|







224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
{
    struct sftp_packet *pkt;
    char x[4];

    if (!sftp_recvdata(x, 4))
	return NULL;

    pkt = snew(struct sftp_packet);
    pkt->savedpos = 0;
    pkt->length = pkt->maxlen = GET_32BIT(x);
    pkt->data = snewn(pkt->length, char);

    if (!sftp_recvdata(pkt->data, pkt->length)) {
	sftp_pkt_free(pkt);
	return NULL;
    }

    pkt->type = sftp_pkt_getbyte(pkt);

    return pkt;
}

/* ----------------------------------------------------------------------
 * String handling routines.
 */

static char *mkstr(char *s, int len)
{
    char *p = snewn(len + 1, char);
    memcpy(p, s, len);
    p[len] = '\0';
    return p;
}

/* ----------------------------------------------------------------------
 * SFTP primitives.
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

	sftp_pkt_getstring(pktin, &hstring, &len);
	if (!hstring) {
	    fxp_internal_error("OPEN returned malformed FXP_HANDLE\n");
            sftp_pkt_free(pktin);
	    return NULL;
	}
	handle = smalloc(sizeof(struct fxp_handle));
	handle->hstring = mkstr(hstring, len);
	handle->hlen = len;
	sftp_pkt_free(pktin);
	return handle;
    } else {
	fxp_got_status(pktin);
        sftp_pkt_free(pktin);







|







440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

	sftp_pkt_getstring(pktin, &hstring, &len);
	if (!hstring) {
	    fxp_internal_error("OPEN returned malformed FXP_HANDLE\n");
            sftp_pkt_free(pktin);
	    return NULL;
	}
	handle = snew(struct fxp_handle);
	handle->hstring = mkstr(hstring, len);
	handle->hlen = len;
	sftp_pkt_free(pktin);
	return handle;
    } else {
	fxp_got_status(pktin);
        sftp_pkt_free(pktin);
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500

	sftp_pkt_getstring(pktin, &hstring, &len);
	if (!hstring) {
	    fxp_internal_error("OPENDIR returned malformed FXP_HANDLE\n");
            sftp_pkt_free(pktin);
	    return NULL;
	}
	handle = smalloc(sizeof(struct fxp_handle));
	handle->hstring = mkstr(hstring, len);
	handle->hlen = len;
	sftp_pkt_free(pktin);
	return handle;
    } else {
	fxp_got_status(pktin);
        sftp_pkt_free(pktin);







|







486
487
488
489
490
491
492
493
494
495
496
497
498
499
500

	sftp_pkt_getstring(pktin, &hstring, &len);
	if (!hstring) {
	    fxp_internal_error("OPENDIR returned malformed FXP_HANDLE\n");
            sftp_pkt_free(pktin);
	    return NULL;
	}
	handle = snew(struct fxp_handle);
	handle->hstring = mkstr(hstring, len);
	handle->hlen = len;
	sftp_pkt_free(pktin);
	return handle;
    } else {
	fxp_got_status(pktin);
        sftp_pkt_free(pktin);
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
	fxp_internal_error("request ID mismatch\n");
        sftp_pkt_free(pktin);
	return NULL;
    }
    if (pktin->type == SSH_FXP_NAME) {
	struct fxp_names *ret;
	int i;
	ret = smalloc(sizeof(struct fxp_names));
	ret->nnames = sftp_pkt_getuint32(pktin);
	ret->names = smalloc(ret->nnames * sizeof(struct fxp_name));
	for (i = 0; i < ret->nnames; i++) {
	    char *str;
	    int len;
	    sftp_pkt_getstring(pktin, &str, &len);
	    ret->names[i].filename = mkstr(str, len);
	    sftp_pkt_getstring(pktin, &str, &len);
	    ret->names[i].longname = mkstr(str, len);







|

|







851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
	fxp_internal_error("request ID mismatch\n");
        sftp_pkt_free(pktin);
	return NULL;
    }
    if (pktin->type == SSH_FXP_NAME) {
	struct fxp_names *ret;
	int i;
	ret = snew(struct fxp_names);
	ret->nnames = sftp_pkt_getuint32(pktin);
	ret->names = snewn(ret->nnames, struct fxp_name);
	for (i = 0; i < ret->nnames; i++) {
	    char *str;
	    int len;
	    sftp_pkt_getstring(pktin, &str, &len);
	    ret->names[i].filename = mkstr(str, len);
	    sftp_pkt_getstring(pktin, &str, &len);
	    ret->names[i].longname = mkstr(str, len);
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940

/*
 * Duplicate an fxp_name structure.
 */
struct fxp_name *fxp_dup_name(struct fxp_name *name)
{
    struct fxp_name *ret;
    ret = smalloc(sizeof(struct fxp_name));
    ret->filename = dupstr(name->filename);
    ret->longname = dupstr(name->longname);
    ret->attrs = name->attrs;	       /* structure copy */
    return ret;
}

/*







|







926
927
928
929
930
931
932
933
934
935
936
937
938
939
940

/*
 * Duplicate an fxp_name structure.
 */
struct fxp_name *fxp_dup_name(struct fxp_name *name)
{
    struct fxp_name *ret;
    ret = snew(struct fxp_name);
    ret->filename = dupstr(name->filename);
    ret->longname = dupstr(name->longname);
    ret->attrs = name->attrs;	       /* structure copy */
    return ret;
}

/*
Changes to sizetip.c.
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
	    hbr = CreateSolidBrush(tip_bg);
	    holdbr = SelectObject(hdc, hbr);

	    GetClientRect(hWnd, &cr);
	    Rectangle(hdc, cr.left, cr.top, cr.right, cr.bottom);

	    wtlen = GetWindowTextLength(hWnd);
	    wt = (LPTSTR) smalloc((wtlen + 1) * sizeof(TCHAR));
	    GetWindowText(hWnd, wt, wtlen + 1);

	    SetTextColor(hdc, tip_text);
	    SetBkColor(hdc, tip_bg);

	    TextOut(hdc, cr.left + 3, cr.top + 3, wt, wtlen);








|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
	    hbr = CreateSolidBrush(tip_bg);
	    holdbr = SelectObject(hdc, hbr);

	    GetClientRect(hWnd, &cr);
	    Rectangle(hdc, cr.left, cr.top, cr.right, cr.bottom);

	    wtlen = GetWindowTextLength(hWnd);
	    wt = (LPTSTR) snewn(wtlen + 1, TCHAR);
	    GetWindowText(hWnd, wt, wtlen + 1);

	    SetTextColor(hdc, tip_text);
	    SetBkColor(hdc, tip_bg);

	    TextOut(hdc, cr.left + 3, cr.top + 3, wt, wtlen);

Changes to ssh.c.
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
 *  - select the C/C++ tab and the General category
 *  - under `Debug info:', select anything _other_ than `Program
 *    Database for Edit and Continue'.
 */
#define crBegin(v)	{ int *crLine = &v; switch(v) { case 0:;
#define crState(t) \
    struct t *s; \
    if (!ssh->t) ssh->t = smalloc(sizeof(struct t)); \
    s = ssh->t;
#define crFinish(z)	} *crLine = 0; return (z); }
#define crFinishV	} *crLine = 0; return; }
#define crReturn(z)	\
	do {\
	    *crLine =__LINE__; return (z); case __LINE__:;\
	} while (0)







|







288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
 *  - select the C/C++ tab and the General category
 *  - under `Debug info:', select anything _other_ than `Program
 *    Database for Edit and Continue'.
 */
#define crBegin(v)	{ int *crLine = &v; switch(v) { case 0:;
#define crState(t) \
    struct t *s; \
    if (!ssh->t) ssh->t = snew(struct t); \
    s = ssh->t;
#define crFinish(z)	} *crLine = 0; return (z); }
#define crFinishV	} *crLine = 0; return; }
#define crReturn(z)	\
	do {\
	    *crLine =__LINE__; return (z); case __LINE__:;\
	} while (0)
810
811
812
813
814
815
816
817

818
819
820
821
822
823
824

    st->pad = 8 - (st->len % 8);
    st->biglen = st->len + st->pad;
    ssh->pktin.length = st->len - 5;

    if (ssh->pktin.maxlen < st->biglen) {
	ssh->pktin.maxlen = st->biglen;
	ssh->pktin.data = srealloc(ssh->pktin.data, st->biglen + APIEXTRA);

    }

    st->to_read = st->biglen;
    st->p = ssh->pktin.data;
    while (st->to_read > 0) {
	st->chunk = st->to_read;
	while ((*datalen) == 0)







|
>







810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825

    st->pad = 8 - (st->len % 8);
    st->biglen = st->len + st->pad;
    ssh->pktin.length = st->len - 5;

    if (ssh->pktin.maxlen < st->biglen) {
	ssh->pktin.maxlen = st->biglen;
	ssh->pktin.data = sresize(ssh->pktin.data, st->biglen + APIEXTRA,
				  unsigned char);
    }

    st->to_read = st->biglen;
    st->p = ssh->pktin.data;
    while (st->to_read > 0) {
	st->chunk = st->to_read;
	while ((*datalen) == 0)
855
856
857
858
859
860
861
862
863

864
865
866
867
868
869
870
	int decomplen;
	zlib_decompress_block(ssh->sc_comp_ctx,
			      ssh->pktin.body - 1, ssh->pktin.length + 1,
			      &decompblk, &decomplen);

	if (ssh->pktin.maxlen < st->pad + decomplen) {
	    ssh->pktin.maxlen = st->pad + decomplen;
	    ssh->pktin.data = srealloc(ssh->pktin.data,
				       ssh->pktin.maxlen + APIEXTRA);

	    ssh->pktin.body = ssh->pktin.data + st->pad + 1;
	}

	memcpy(ssh->pktin.body - 1, decompblk, decomplen);
	sfree(decompblk);
	ssh->pktin.length = decomplen - 1;
    }







|
|
>







856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
	int decomplen;
	zlib_decompress_block(ssh->sc_comp_ctx,
			      ssh->pktin.body - 1, ssh->pktin.length + 1,
			      &decompblk, &decomplen);

	if (ssh->pktin.maxlen < st->pad + decomplen) {
	    ssh->pktin.maxlen = st->pad + decomplen;
	    ssh->pktin.data = sresize(ssh->pktin.data,
				      ssh->pktin.maxlen + APIEXTRA,
				      unsigned char);
	    ssh->pktin.body = ssh->pktin.data + st->pad + 1;
	}

	memcpy(ssh->pktin.body - 1, decompblk, decomplen);
	sfree(decompblk);
	ssh->pktin.length = decomplen - 1;
    }
938
939
940
941
942
943
944
945

946
947
948
949
950
951
952
    else
	st->cipherblk = 8;
    if (st->cipherblk < 8)
	st->cipherblk = 8;

    if (ssh->pktin.maxlen < st->cipherblk) {
	ssh->pktin.maxlen = st->cipherblk;
	ssh->pktin.data = srealloc(ssh->pktin.data, st->cipherblk + APIEXTRA);

    }

    /*
     * Acquire and decrypt the first block of the packet. This will
     * contain the length and padding details.
     */
    for (st->i = st->len = 0; st->i < st->cipherblk; st->i++) {







|
>







940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
    else
	st->cipherblk = 8;
    if (st->cipherblk < 8)
	st->cipherblk = 8;

    if (ssh->pktin.maxlen < st->cipherblk) {
	ssh->pktin.maxlen = st->cipherblk;
	ssh->pktin.data = sresize(ssh->pktin.data, st->cipherblk + APIEXTRA,
				  unsigned char);
    }

    /*
     * Acquire and decrypt the first block of the packet. This will
     * contain the length and padding details.
     */
    for (st->i = st->len = 0; st->i < st->cipherblk; st->i++) {
989
990
991
992
993
994
995
996
997

998
999
1000
1001
1002
1003
1004
    st->maclen = ssh->scmac ? ssh->scmac->len : 0;

    /*
     * Adjust memory allocation if packet is too big.
     */
    if (ssh->pktin.maxlen < st->packetlen + st->maclen) {
	ssh->pktin.maxlen = st->packetlen + st->maclen;
	ssh->pktin.data = srealloc(ssh->pktin.data,
				   ssh->pktin.maxlen + APIEXTRA);

    }

    /*
     * Read and decrypt the remainder of the packet.
     */
    for (st->i = st->cipherblk; st->i < st->packetlen + st->maclen;
	 st->i++) {







|
|
>







992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
    st->maclen = ssh->scmac ? ssh->scmac->len : 0;

    /*
     * Adjust memory allocation if packet is too big.
     */
    if (ssh->pktin.maxlen < st->packetlen + st->maclen) {
	ssh->pktin.maxlen = st->packetlen + st->maclen;
	ssh->pktin.data = sresize(ssh->pktin.data,
				  ssh->pktin.maxlen + APIEXTRA,
				  unsigned char);
    }

    /*
     * Read and decrypt the remainder of the packet.
     */
    for (st->i = st->cipherblk; st->i < st->packetlen + st->maclen;
	 st->i++) {
1032
1033
1034
1035
1036
1037
1038
1039
1040

1041
1042
1043
1044
1045
1046
1047
	int newlen;
	if (ssh->sccomp &&
	    ssh->sccomp->decompress(ssh->sc_comp_ctx,
				    ssh->pktin.data + 5, ssh->pktin.length - 5,
				    &newpayload, &newlen)) {
	    if (ssh->pktin.maxlen < newlen + 5) {
		ssh->pktin.maxlen = newlen + 5;
		ssh->pktin.data = srealloc(ssh->pktin.data,
					   ssh->pktin.maxlen + APIEXTRA);

	    }
	    ssh->pktin.length = 5 + newlen;
	    memcpy(ssh->pktin.data + 5, newpayload, newlen);
	    sfree(newpayload);
	}
    }








|
|
>







1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
	int newlen;
	if (ssh->sccomp &&
	    ssh->sccomp->decompress(ssh->sc_comp_ctx,
				    ssh->pktin.data + 5, ssh->pktin.length - 5,
				    &newpayload, &newlen)) {
	    if (ssh->pktin.maxlen < newlen + 5) {
		ssh->pktin.maxlen = newlen + 5;
		ssh->pktin.data = sresize(ssh->pktin.data,
					  ssh->pktin.maxlen + APIEXTRA,
					  unsigned char);
	    }
	    ssh->pktin.length = 5 + newlen;
	    memcpy(ssh->pktin.data + 5, newpayload, newlen);
	    sfree(newpayload);
	}
    }

1166
1167
1168
1169
1170
1171
1172
1173

1174
1175

1176
1177
1178
1179
1180
1181
1182

    ssh->pktout.length = len - 5;
    if (ssh->pktout.maxlen < biglen) {
	ssh->pktout.maxlen = biglen;
#ifdef MSCRYPTOAPI
	/* Allocate enough buffer space for extra block
	 * for MS CryptEncrypt() */
	ssh->pktout.data = srealloc(ssh->pktout.data, biglen + 12);

#else
	ssh->pktout.data = srealloc(ssh->pktout.data, biglen + 4);

#endif
    }
    ssh->pktout.body = ssh->pktout.data + 4 + pad + 1;
}

static void s_wrpkt_start(Ssh ssh, int type, int len)
{







|
>

|
>







1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189

    ssh->pktout.length = len - 5;
    if (ssh->pktout.maxlen < biglen) {
	ssh->pktout.maxlen = biglen;
#ifdef MSCRYPTOAPI
	/* Allocate enough buffer space for extra block
	 * for MS CryptEncrypt() */
	ssh->pktout.data = sresize(ssh->pktout.data, biglen + 12,
				   unsigned char);
#else
	ssh->pktout.data = sresize(ssh->pktout.data, biglen + 4,
				   unsigned char);
#endif
    }
    ssh->pktout.body = ssh->pktout.data + 4 + pad + 1;
}

static void s_wrpkt_start(Ssh ssh, int type, int len)
{
1244
1245
1246
1247
1248
1249
1250
1251
1252

1253
1254
1255
1256
1257
1258
1259

static void s_wrpkt_defer(Ssh ssh)
{
    int len;
    len = s_wrpkt_prepare(ssh);
    if (ssh->deferred_len + len > ssh->deferred_size) {
	ssh->deferred_size = ssh->deferred_len + len + 128;
	ssh->deferred_send_data = srealloc(ssh->deferred_send_data,
					   ssh->deferred_size);

    }
    memcpy(ssh->deferred_send_data + ssh->deferred_len, ssh->pktout.data, len);
    ssh->deferred_len += len;
}

/*
 * Construct a packet with the specified contents.







|
|
>







1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267

static void s_wrpkt_defer(Ssh ssh)
{
    int len;
    len = s_wrpkt_prepare(ssh);
    if (ssh->deferred_len + len > ssh->deferred_size) {
	ssh->deferred_size = ssh->deferred_len + len + 128;
	ssh->deferred_send_data = sresize(ssh->deferred_send_data,
					  ssh->deferred_size,
					  unsigned char);
    }
    memcpy(ssh->deferred_send_data + ssh->deferred_len, ssh->pktout.data, len);
    ssh->deferred_len += len;
}

/*
 * Construct a packet with the specified contents.
1392
1393
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
/*
 * SSH2 packet construction functions.
 */
static void ssh2_pkt_ensure(Ssh ssh, int length)
{
    if (ssh->pktout.maxlen < length) {
	ssh->pktout.maxlen = length + 256;
	ssh->pktout.data = srealloc(ssh->pktout.data,
				    ssh->pktout.maxlen + APIEXTRA);

	if (!ssh->pktout.data)
	    fatalbox("Out of memory");
    }
}
static void ssh2_pkt_adddata(Ssh ssh, void *data, int len)
{
    ssh->pktout.length += len;







|
|
>







1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
/*
 * SSH2 packet construction functions.
 */
static void ssh2_pkt_ensure(Ssh ssh, int length)
{
    if (ssh->pktout.maxlen < length) {
	ssh->pktout.maxlen = length + 256;
	ssh->pktout.data = sresize(ssh->pktout.data,
				   ssh->pktout.maxlen + APIEXTRA,
				   unsigned char);
	if (!ssh->pktout.data)
	    fatalbox("Out of memory");
    }
}
static void ssh2_pkt_adddata(Ssh ssh, void *data, int len)
{
    ssh->pktout.length += len;
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
    ssh2_pkt_addstring_start(ssh);
    ssh2_pkt_addstring_str(ssh, data);
}
static unsigned char *ssh2_mpint_fmt(Bignum b, int *len)
{
    unsigned char *p;
    int i, n = (bignum_bitcount(b) + 7) / 8;
    p = smalloc(n + 1);
    if (!p)
	fatalbox("out of memory");
    p[0] = 0;
    for (i = 1; i <= n; i++)
	p[i] = bignum_byte(b, n - i);
    i = 0;
    while (i <= n && p[i] == 0 && (p[i + 1] & 0x80) == 0)







|







1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
    ssh2_pkt_addstring_start(ssh);
    ssh2_pkt_addstring_str(ssh, data);
}
static unsigned char *ssh2_mpint_fmt(Bignum b, int *len)
{
    unsigned char *p;
    int i, n = (bignum_bitcount(b) + 7) / 8;
    p = snewn(n + 1, unsigned char);
    if (!p)
	fatalbox("out of memory");
    p[0] = 0;
    for (i = 1; i <= n; i++)
	p[i] = bignum_byte(b, n - i);
    i = 0;
    while (i <= n && p[i] == 0 && (p[i + 1] & 0x80) == 0)
1560
1561
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571
1572
1573
1574
1575
 * constructed in one order and sent in another.
 */
static void ssh2_pkt_defer(Ssh ssh)
{
    int len = ssh2_pkt_construct(ssh);
    if (ssh->deferred_len + len > ssh->deferred_size) {
	ssh->deferred_size = ssh->deferred_len + len + 128;
	ssh->deferred_send_data = srealloc(ssh->deferred_send_data,
					   ssh->deferred_size);

    }
    memcpy(ssh->deferred_send_data + ssh->deferred_len, ssh->pktout.data, len);
    ssh->deferred_len += len;
}

/*
 * Send the whole deferred data block constructed by







|
|
>







1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
 * constructed in one order and sent in another.
 */
static void ssh2_pkt_defer(Ssh ssh)
{
    int len = ssh2_pkt_construct(ssh);
    if (ssh->deferred_len + len > ssh->deferred_size) {
	ssh->deferred_size = ssh->deferred_len + len + 128;
	ssh->deferred_send_data = sresize(ssh->deferred_send_data,
					  ssh->deferred_size,
					  unsigned char);
    }
    memcpy(ssh->deferred_send_data + ssh->deferred_len, ssh->pktout.data, len);
    ssh->deferred_len += len;
}

/*
 * Send the whole deferred data block constructed by
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
	    s->i = 0;
	if (s->i < 0)
	    break;
	crReturn(1);		       /* get another character */
    }

    s->vstrsize = 16;
    s->vstring = smalloc(s->vstrsize);
    strcpy(s->vstring, "SSH-");
    s->vslen = 4;
    s->i = 0;
    while (1) {
	crReturn(1);		       /* get another char */
	if (s->vslen >= s->vstrsize - 1) {
	    s->vstrsize += 16;
	    s->vstring = srealloc(s->vstring, s->vstrsize);
	}
	s->vstring[s->vslen++] = c;
	if (s->i >= 0) {
	    if (c == '-') {
		s->version[s->i] = '\0';
		s->i = -1;
	    } else if (s->i < sizeof(s->version) - 1)
		s->version[s->i++] = c;
	} else if (c == '\012')
	    break;
    }

    ssh->agentfwd_enabled = FALSE;
    ssh->rdpkt2_state.incoming_sequence = 0;

    s->vstring[s->vslen] = 0;
    s->vstring[strcspn(s->vstring, "\r\n")] = '\0';/* remove EOL chars */
    {
	char *vlog;
	vlog = smalloc(20 + s->vslen);
	sprintf(vlog, "Server version: %s", s->vstring);
	logevent(vlog);
	sfree(vlog);
    }
    ssh_detect_bugs(ssh, s->vstring);

    /*







|







|



















|







1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
	    s->i = 0;
	if (s->i < 0)
	    break;
	crReturn(1);		       /* get another character */
    }

    s->vstrsize = 16;
    s->vstring = snewn(s->vstrsize, char);
    strcpy(s->vstring, "SSH-");
    s->vslen = 4;
    s->i = 0;
    while (1) {
	crReturn(1);		       /* get another char */
	if (s->vslen >= s->vstrsize - 1) {
	    s->vstrsize += 16;
	    s->vstring = sresize(s->vstring, s->vstrsize, char);
	}
	s->vstring[s->vslen++] = c;
	if (s->i >= 0) {
	    if (c == '-') {
		s->version[s->i] = '\0';
		s->i = -1;
	    } else if (s->i < sizeof(s->version) - 1)
		s->version[s->i++] = c;
	} else if (c == '\012')
	    break;
    }

    ssh->agentfwd_enabled = FALSE;
    ssh->rdpkt2_state.incoming_sequence = 0;

    s->vstring[s->vslen] = 0;
    s->vstring[strcspn(s->vstring, "\r\n")] = '\0';/* remove EOL chars */
    {
	char *vlog;
	vlog = snewn(20 + s->vslen, char);
	sprintf(vlog, "Server version: %s", s->vstring);
	logevent(vlog);
	sfree(vlog);
    }
    ssh_detect_bugs(ssh, s->vstring);

    /*
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
	ssh_sent,
	NULL
    };

    SockAddr addr;
    char *err;

    ssh->savedhost = smalloc(1 + strlen(host));
    if (!ssh->savedhost)
	fatalbox("Out of memory");
    strcpy(ssh->savedhost, host);

    if (port < 0)
	port = 22;		       /* default ssh port */
    ssh->savedport = port;







|







2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
	ssh_sent,
	NULL
    };

    SockAddr addr;
    char *err;

    ssh->savedhost = snewn(1 + strlen(host), char);
    if (!ssh->savedhost)
	fatalbox("Out of memory");
    strcpy(ssh->savedhost, host);

    if (port < 0)
	port = 22;		       /* default ssh port */
    ssh->savedport = port;
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
    MD5Final(s->session_id, &md5c);

    for (i = 0; i < 32; i++)
	ssh->session_key[i] = random_byte();

    s->len = (hostkey.bytes > servkey.bytes ? hostkey.bytes : servkey.bytes);

    s->rsabuf = smalloc(s->len);
    if (!s->rsabuf)
	fatalbox("Out of memory");

    /*
     * Verify the host key.
     */
    {
	/*
	 * First format the key into a string.
	 */
	int len = rsastr_len(&hostkey);
	char fingerprint[100];
	char *keystr = smalloc(len);
	if (!keystr)
	    fatalbox("Out of memory");
	rsastr_fmt(keystr, &hostkey);
	rsa_fingerprint(fingerprint, sizeof(fingerprint), &hostkey);
	verify_ssh_host_key(ssh->frontend,
			    ssh->savedhost, ssh->savedport, "rsa", keystr,
			    fingerprint);







|












|







2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
    MD5Final(s->session_id, &md5c);

    for (i = 0; i < 32; i++)
	ssh->session_key[i] = random_byte();

    s->len = (hostkey.bytes > servkey.bytes ? hostkey.bytes : servkey.bytes);

    s->rsabuf = snewn(s->len, unsigned char);
    if (!s->rsabuf)
	fatalbox("Out of memory");

    /*
     * Verify the host key.
     */
    {
	/*
	 * First format the key into a string.
	 */
	int len = rsastr_len(&hostkey);
	char fingerprint[100];
	char *keystr = snewn(len, char);
	if (!keystr)
	    fatalbox("Out of memory");
	rsastr_fmt(keystr, &hostkey);
	rsa_fingerprint(fingerprint, sizeof(fingerprint), &hostkey);
	verify_ssh_host_key(ssh->frontend,
			    ssh->savedhost, ssh->savedport, "rsa", keystr,
			    fingerprint);
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
			int len, retlen;
			len = 1 + 4;   /* message type, bit count */
			len += ssh1_bignum_length(s->key.exponent);
			len += ssh1_bignum_length(s->key.modulus);
			len += ssh1_bignum_length(s->challenge);
			len += 16;     /* session id */
			len += 4;      /* response format */
			agentreq = smalloc(4 + len);
			PUT_32BIT(agentreq, len);
			q = agentreq + 4;
			*q++ = SSH1_AGENTC_RSA_CHALLENGE;
			PUT_32BIT(q, bignum_bitcount(s->key.modulus));
			q += 4;
			q += ssh1_write_bignum(q, s->key.exponent);
			q += ssh1_write_bignum(q, s->key.modulus);







|







2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
			int len, retlen;
			len = 1 + 4;   /* message type, bit count */
			len += ssh1_bignum_length(s->key.exponent);
			len += ssh1_bignum_length(s->key.modulus);
			len += ssh1_bignum_length(s->challenge);
			len += 16;     /* session id */
			len += 4;      /* response format */
			agentreq = snewn(4 + len, char);
			PUT_32BIT(agentreq, len);
			q = agentreq + 4;
			*q++ = SSH1_AGENTC_RSA_CHALLENGE;
			PUT_32BIT(q, bignum_bitcount(s->key.modulus));
			q += 4;
			q += ssh1_write_bignum(q, s->key.exponent);
			q += ssh1_write_bignum(q, s->key.modulus);
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
		    } else {
			bottom = pwlen & ~7;
			top = bottom + 7;
		    }

		    assert(pwlen >= bottom && pwlen <= top);

		    randomstr = smalloc(top + 1);

		    for (i = bottom; i <= top; i++) {
			if (i == pwlen)
			    defer_packet(ssh, s->pwpkt_type,
					 PKT_STR, s->password, PKT_END);
			else {
			    for (j = 0; j < i; j++) {







|







2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
		    } else {
			bottom = pwlen & ~7;
			top = bottom + 7;
		    }

		    assert(pwlen >= bottom && pwlen <= top);

		    randomstr = snewn(top + 1, char);

		    for (i = bottom; i <= top; i++) {
			if (i == pwlen)
			    defer_packet(ssh, s->pwpkt_type,
					 PKT_STR, s->password, PKT_END);
			else {
			    for (j = 0; j < i; j++) {
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
			      (int)(sserv ? strlen(sports) : 0), sports,
			      sserv, "(", sport, sserv, ")",
			      host,
			      (int)(dserv ? strlen(dports) : 0), dports,
			      dserv, "(", dport, dserv, ")");
		} else {
		    struct ssh_rportfwd *pf;
		    pf = smalloc(sizeof(*pf));
		    strcpy(pf->dhost, host);
		    pf->dport = dport;
		    if (saddr) {
			logeventf(ssh,
				  "SSH1 cannot handle source address spec \"%s:%d\"; ignoring",
				  saddr, sport);
		    }







|







3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
			      (int)(sserv ? strlen(sports) : 0), sports,
			      sserv, "(", sport, sserv, ")",
			      host,
			      (int)(dserv ? strlen(dports) : 0), dports,
			      dserv, "(", dport, dserv, ")");
		} else {
		    struct ssh_rportfwd *pf;
		    pf = snew(struct ssh_rportfwd);
		    strcpy(pf->dhost, host);
		    pf->dport = dport;
		    if (saddr) {
			logeventf(ssh,
				  "SSH1 cannot handle source address spec \"%s:%d\"; ignoring",
				  saddr, sport);
		    }
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
		logevent("Received X11 connect request");
		/* Refuse if X11 forwarding is disabled. */
		if (!ssh->X11_fwd_enabled) {
		    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
				PKT_INT, GET_32BIT(ssh->pktin.body), PKT_END);
		    logevent("Rejected X11 connect request");
		} else {
		    c = smalloc(sizeof(struct ssh_channel));
		    c->ssh = ssh;

		    if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c,
				 ssh->x11auth, NULL, -1, &ssh->cfg) != NULL) {
			logevent("opening X11 forward connection failed");
			sfree(c);
			send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,







|







3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
		logevent("Received X11 connect request");
		/* Refuse if X11 forwarding is disabled. */
		if (!ssh->X11_fwd_enabled) {
		    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
				PKT_INT, GET_32BIT(ssh->pktin.body), PKT_END);
		    logevent("Rejected X11 connect request");
		} else {
		    c = snew(struct ssh_channel);
		    c->ssh = ssh;

		    if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c,
				 ssh->x11auth, NULL, -1, &ssh->cfg) != NULL) {
			logevent("opening X11 forward connection failed");
			sfree(c);
			send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
		struct ssh_channel *c;

		/* Refuse if agent forwarding is disabled. */
		if (!ssh->agentfwd_enabled) {
		    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
				PKT_INT, GET_32BIT(ssh->pktin.body), PKT_END);
		} else {
		    c = smalloc(sizeof(struct ssh_channel));
		    c->ssh = ssh;
		    c->remoteid = GET_32BIT(ssh->pktin.body);
		    c->localid = alloc_channel_id(ssh);
		    c->closes = 0;
		    c->v.v1.throttling = 0;
		    c->type = CHAN_AGENT;	/* identify channel type */
		    c->u.a.lensofar = 0;
		    add234(ssh->channels, c);
		    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
				PKT_INT, c->remoteid, PKT_INT, c->localid,
				PKT_END);
		}
	    } else if (ssh->pktin.type == SSH1_MSG_PORT_OPEN) {
   		/* Remote side is trying to open a channel to talk to a
		 * forwarded port. Give them back a local channel number. */
		struct ssh_channel *c;
		struct ssh_rportfwd pf;
		int hostsize, port;
		char host[256], buf[1024];
		char *p, *h, *e;
		c = smalloc(sizeof(struct ssh_channel));
		c->ssh = ssh;

		hostsize = GET_32BIT(ssh->pktin.body+4);
		for (h = host, p = (char *)(ssh->pktin.body+8);
		     hostsize != 0; hostsize--) {
		    if (h+1 < host+sizeof(host))
			*h++ = *p;







|




















|







3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
		struct ssh_channel *c;

		/* Refuse if agent forwarding is disabled. */
		if (!ssh->agentfwd_enabled) {
		    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
				PKT_INT, GET_32BIT(ssh->pktin.body), PKT_END);
		} else {
		    c = snew(struct ssh_channel);
		    c->ssh = ssh;
		    c->remoteid = GET_32BIT(ssh->pktin.body);
		    c->localid = alloc_channel_id(ssh);
		    c->closes = 0;
		    c->v.v1.throttling = 0;
		    c->type = CHAN_AGENT;	/* identify channel type */
		    c->u.a.lensofar = 0;
		    add234(ssh->channels, c);
		    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
				PKT_INT, c->remoteid, PKT_INT, c->localid,
				PKT_END);
		}
	    } else if (ssh->pktin.type == SSH1_MSG_PORT_OPEN) {
   		/* Remote side is trying to open a channel to talk to a
		 * forwarded port. Give them back a local channel number. */
		struct ssh_channel *c;
		struct ssh_rportfwd pf;
		int hostsize, port;
		char host[256], buf[1024];
		char *p, *h, *e;
		c = snew(struct ssh_channel);
		c->ssh = ssh;

		hostsize = GET_32BIT(ssh->pktin.body+4);
		for (h = host, p = (char *)(ssh->pktin.body+8);
		     hostsize != 0; hostsize--) {
		    if (h+1 < host+sizeof(host))
			*h++ = *p;
3538
3539
3540
3541
3542
3543
3544
3545

3546
3547
3548
3549
3550
3551
3552
				p += l;
				len -= l;
				c->u.a.lensofar += l;
			    }
			    if (c->u.a.lensofar == 4) {
				c->u.a.totallen =
				    4 + GET_32BIT(c->u.a.msglen);
				c->u.a.message = smalloc(c->u.a.totallen);

				memcpy(c->u.a.message, c->u.a.msglen, 4);
			    }
			    if (c->u.a.lensofar >= 4 && len > 0) {
				int l =
				    min(c->u.a.totallen - c->u.a.lensofar,
					len);
				memcpy(c->u.a.message + c->u.a.lensofar, p,







|
>







3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
				p += l;
				len -= l;
				c->u.a.lensofar += l;
			    }
			    if (c->u.a.lensofar == 4) {
				c->u.a.totallen =
				    4 + GET_32BIT(c->u.a.msglen);
				c->u.a.message = snewn(c->u.a.totallen,
						       unsigned char);
				memcpy(c->u.a.message, c->u.a.msglen, 4);
			    }
			    if (c->u.a.lensofar >= 4 && len > 0) {
				int l =
				    min(c->u.a.totallen - c->u.a.lensofar,
					len);
				memcpy(c->u.a.message + c->u.a.lensofar, p,
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
			s->siglen = ssh->pktout.length - 5 + 4 + 20;
                        if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
                            s->siglen -= 4;
			s->len = 1;       /* message type */
			s->len += 4 + s->pklen;	/* key blob */
			s->len += 4 + s->siglen;	/* data to sign */
			s->len += 4;      /* flags */
			s->agentreq = smalloc(4 + s->len);
			PUT_32BIT(s->agentreq, s->len);
			s->q = s->agentreq + 4;
			*s->q++ = SSH2_AGENTC_SIGN_REQUEST;
			PUT_32BIT(s->q, s->pklen);
			s->q += 4;
			memcpy(s->q, s->pkblob, s->pklen);
			s->q += s->pklen;







|







4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
			s->siglen = ssh->pktout.length - 5 + 4 + 20;
                        if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
                            s->siglen -= 4;
			s->len = 1;       /* message type */
			s->len += 4 + s->pklen;	/* key blob */
			s->len += 4 + s->siglen;	/* data to sign */
			s->len += 4;      /* flags */
			s->agentreq = snewn(4 + s->len, char);
			PUT_32BIT(s->agentreq, s->len);
			s->q = s->agentreq + 4;
			*s->q++ = SSH2_AGENTC_SIGN_REQUEST;
			PUT_32BIT(s->q, s->pklen);
			s->q += 4;
			memcpy(s->q, s->pkblob, s->pklen);
			s->q += s->pklen;
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
		     *
		     * followed by everything so far placed in the
		     * outgoing packet.
		     */
		    sigdata_len = ssh->pktout.length - 5 + 4 + 20;
                    if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
                        sigdata_len -= 4;
		    sigdata = smalloc(sigdata_len);
                    p = 0;
                    if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) {
                        PUT_32BIT(sigdata+p, 20);
                        p += 4;
                    }
		    memcpy(sigdata+p, ssh->v2_session_id, 20); p += 20;
		    memcpy(sigdata+p, ssh->pktout.data + 5,







|







4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
		     *
		     * followed by everything so far placed in the
		     * outgoing packet.
		     */
		    sigdata_len = ssh->pktout.length - 5 + 4 + 20;
                    if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
                        sigdata_len -= 4;
		    sigdata = snewn(sigdata_len, char);
                    p = 0;
                    if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) {
                        PUT_32BIT(sigdata+p, 20);
                        p += 4;
                    }
		    memcpy(sigdata+p, ssh->v2_session_id, 20); p += 20;
		    memcpy(sigdata+p, ssh->pktout.data + 5,
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
     * point; there's no need to send SERVICE_REQUEST.
     */

    /*
     * So now create a channel with a session in it.
     */
    ssh->channels = newtree234(ssh_channelcmp);
    ssh->mainchan = smalloc(sizeof(struct ssh_channel));
    ssh->mainchan->ssh = ssh;
    ssh->mainchan->localid = alloc_channel_id(ssh);
    ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_OPEN);
    ssh2_pkt_addstring(ssh, "session");
    ssh2_pkt_adduint32(ssh, ssh->mainchan->localid);
    ssh->mainchan->v.v2.locwindow = OUR_V2_WINSIZE;
    ssh2_pkt_adduint32(ssh, ssh->mainchan->v.v2.locwindow);/* our window size */







|







5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
     * point; there's no need to send SERVICE_REQUEST.
     */

    /*
     * So now create a channel with a session in it.
     */
    ssh->channels = newtree234(ssh_channelcmp);
    ssh->mainchan = snew(struct ssh_channel);
    ssh->mainchan->ssh = ssh;
    ssh->mainchan->localid = alloc_channel_id(ssh);
    ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_OPEN);
    ssh2_pkt_addstring(ssh, "session");
    ssh2_pkt_adduint32(ssh, ssh->mainchan->localid);
    ssh->mainchan->v.v2.locwindow = OUR_V2_WINSIZE;
    ssh2_pkt_adduint32(ssh, ssh->mainchan->v.v2.locwindow);/* our window size */
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
			      (int)(sserv ? strlen(sports) : 0), sports,
			      sserv, "(", sport, sserv, ")",
			      host,
			      (int)(dserv ? strlen(dports) : 0), dports,
			      dserv, "(", dport, dserv, ")");
		} else {
		    struct ssh_rportfwd *pf;
		    pf = smalloc(sizeof(*pf));
		    strcpy(pf->dhost, host);
		    pf->dport = dport;
		    pf->sport = sport;
		    if (add234(ssh->rportfwds, pf) != pf) {
			logeventf(ssh, "Duplicate remote port forwarding"
				  " to %s:%d", host, dport);
			sfree(pf);







|







5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
			      (int)(sserv ? strlen(sports) : 0), sports,
			      sserv, "(", sport, sserv, ")",
			      host,
			      (int)(dserv ? strlen(dports) : 0), dports,
			      dserv, "(", dport, dserv, ")");
		} else {
		    struct ssh_rportfwd *pf;
		    pf = snew(struct ssh_rportfwd);
		    strcpy(pf->dhost, host);
		    pf->dport = dport;
		    pf->sport = sport;
		    if (add234(ssh->rportfwds, pf) != pf) {
			logeventf(ssh, "Duplicate remote port forwarding"
				  " to %s:%d", host, dport);
			sfree(pf);
5526
5527
5528
5529
5530
5531
5532
5533

5534
5535
5536
5537
5538
5539
5540
				data += l;
				length -= l;
				c->u.a.lensofar += l;
			    }
			    if (c->u.a.lensofar == 4) {
				c->u.a.totallen =
				    4 + GET_32BIT(c->u.a.msglen);
				c->u.a.message = smalloc(c->u.a.totallen);

				memcpy(c->u.a.message, c->u.a.msglen, 4);
			    }
			    if (c->u.a.lensofar >= 4 && length > 0) {
				int l =
				    min(c->u.a.totallen - c->u.a.lensofar,
					length);
				memcpy(c->u.a.message + c->u.a.lensofar,







|
>







5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
				data += l;
				length -= l;
				c->u.a.lensofar += l;
			    }
			    if (c->u.a.lensofar == 4) {
				c->u.a.totallen =
				    4 + GET_32BIT(c->u.a.msglen);
				c->u.a.message = snewn(c->u.a.totallen,
						       unsigned char);
				memcpy(c->u.a.message, c->u.a.msglen, 4);
			    }
			    if (c->u.a.lensofar >= 4 && length > 0) {
				int l =
				    min(c->u.a.totallen - c->u.a.lensofar,
					length);
				memcpy(c->u.a.message + c->u.a.lensofar,
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
		char *peeraddr;
		int peeraddrlen;
		int port;
		char *error = NULL;
		struct ssh_channel *c;
		unsigned remid, winsize, pktsize;
		ssh2_pkt_getstring(ssh, &type, &typelen);
		c = smalloc(sizeof(struct ssh_channel));
		c->ssh = ssh;

		remid = ssh2_pkt_getuint32(ssh);
		winsize = ssh2_pkt_getuint32(ssh);
		pktsize = ssh2_pkt_getuint32(ssh);
		ssh2_pkt_getstring(ssh, &peeraddr, &peeraddrlen);
		port = ssh2_pkt_getuint32(ssh);

		if (typelen == 3 && !memcmp(type, "x11", 3)) {
		    char *addrstr = smalloc(peeraddrlen+1);
		    memcpy(addrstr, peeraddr, peeraddrlen);
		    peeraddr[peeraddrlen] = '\0';

		    if (!ssh->X11_fwd_enabled)
			error = "X11 forwarding is not enabled";
		    else if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c,
				      ssh->x11auth, addrstr, port,







|









|







5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
		char *peeraddr;
		int peeraddrlen;
		int port;
		char *error = NULL;
		struct ssh_channel *c;
		unsigned remid, winsize, pktsize;
		ssh2_pkt_getstring(ssh, &type, &typelen);
		c = snew(struct ssh_channel);
		c->ssh = ssh;

		remid = ssh2_pkt_getuint32(ssh);
		winsize = ssh2_pkt_getuint32(ssh);
		pktsize = ssh2_pkt_getuint32(ssh);
		ssh2_pkt_getstring(ssh, &peeraddr, &peeraddrlen);
		port = ssh2_pkt_getuint32(ssh);

		if (typelen == 3 && !memcmp(type, "x11", 3)) {
		    char *addrstr = snewn(peeraddrlen+1, char);
		    memcpy(addrstr, peeraddr, peeraddrlen);
		    peeraddr[peeraddrlen] = '\0';

		    if (!ssh->X11_fwd_enabled)
			error = "X11 forwarding is not enabled";
		    else if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c,
				      ssh->x11auth, addrstr, port,
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
static char *ssh_init(void *frontend_handle, void **backend_handle,
		      Config *cfg,
		      char *host, int port, char **realhost, int nodelay)
{
    char *p;
    Ssh ssh;

    ssh = smalloc(sizeof(*ssh));
    ssh->cfg = *cfg;		       /* STRUCTURE COPY */
    ssh->s = NULL;
    ssh->cipher = NULL;
    ssh->v1_cipher_ctx = NULL;
    ssh->crcda_ctx = NULL;
    ssh->cscipher = NULL;
    ssh->cs_cipher_ctx = NULL;







|







5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
static char *ssh_init(void *frontend_handle, void **backend_handle,
		      Config *cfg,
		      char *host, int port, char **realhost, int nodelay)
{
    char *p;
    Ssh ssh;

    ssh = snew(struct ssh_tag);
    ssh->cfg = *cfg;		       /* STRUCTURE COPY */
    ssh->s = NULL;
    ssh->cipher = NULL;
    ssh->v1_cipher_ctx = NULL;
    ssh->crcda_ctx = NULL;
    ssh->cscipher = NULL;
    ssh->cs_cipher_ctx = NULL;
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
    }
}

void *new_sock_channel(void *handle, Socket s)
{
    Ssh ssh = (Ssh) handle;
    struct ssh_channel *c;
    c = smalloc(sizeof(struct ssh_channel));
    c->ssh = ssh;

    if (c) {
	c->remoteid = -1;	       /* to be set when open confirmed */
	c->localid = alloc_channel_id(ssh);
	c->closes = 0;
	c->type = CHAN_SOCKDATA_DORMANT;/* identify channel type */







|







6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
    }
}

void *new_sock_channel(void *handle, Socket s)
{
    Ssh ssh = (Ssh) handle;
    struct ssh_channel *c;
    c = snew(struct ssh_channel);
    c->ssh = ssh;

    if (c) {
	c->remoteid = -1;	       /* to be set when open confirmed */
	c->localid = alloc_channel_id(ssh);
	c->closes = 0;
	c->type = CHAN_SOCKDATA_DORMANT;/* identify channel type */
Changes to sshaes.c.
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
    }

    memcpy(ctx->iv, iv, sizeof(iv));
}

static void *aes_make_context(void)
{
    return smalloc(sizeof(AESContext));
}

static void aes_free_context(void *handle)
{
    sfree(handle);
}








|







1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
    }

    memcpy(ctx->iv, iv, sizeof(iv));
}

static void *aes_make_context(void)
{
    return snew(AESContext);
}

static void aes_free_context(void *handle)
{
    sfree(handle);
}

Changes to sshblowf.c.
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

/* -- Interface with PuTTY -- */

#define SSH_SESSION_KEY_LENGTH	32

static void *blowfish_make_context(void)
{
    return smalloc(sizeof(BlowfishContext));
}

static void *blowfish_ssh1_make_context(void)
{
    /* In SSH1, need one key for each direction */
    return smalloc(2*sizeof(BlowfishContext));
}

static void blowfish_free_context(void *handle)
{
    sfree(handle);
}








|





|







474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

/* -- Interface with PuTTY -- */

#define SSH_SESSION_KEY_LENGTH	32

static void *blowfish_make_context(void)
{
    return snew(BlowfishContext);
}

static void *blowfish_ssh1_make_context(void)
{
    /* In SSH1, need one key for each direction */
    return snewn(2, BlowfishContext);
}

static void blowfish_free_context(void *handle)
{
    sfree(handle);
}

Changes to sshbn.c.
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 * nonzero.
 */

Bignum Zero = bnZero, One = bnOne;

static Bignum newbn(int length)
{
    Bignum b = smalloc((length + 1) * sizeof(unsigned short));
    if (!b)
	abort();		       /* FIXME */
    memset(b, 0, (length + 1) * sizeof(*b));
    b[0] = length;
    return b;
}

void bn_restore_invariant(Bignum b)
{
    while (b[0] > 1 && b[b[0]] == 0)
	b[0]--;
}

Bignum copybn(Bignum orig)
{
    Bignum b = smalloc((orig[0] + 1) * sizeof(unsigned short));
    if (!b)
	abort();		       /* FIXME */
    memcpy(b, orig, (orig[0] + 1) * sizeof(*b));
    return b;
}

void freebn(Bignum b)







|















|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 * nonzero.
 */

Bignum Zero = bnZero, One = bnOne;

static Bignum newbn(int length)
{
    Bignum b = snewn(length + 1, unsigned short);
    if (!b)
	abort();		       /* FIXME */
    memset(b, 0, (length + 1) * sizeof(*b));
    b[0] = length;
    return b;
}

void bn_restore_invariant(Bignum b)
{
    while (b[0] > 1 && b[b[0]] == 0)
	b[0]--;
}

Bignum copybn(Bignum orig)
{
    Bignum b = snewn(orig[0] + 1, unsigned short);
    if (!b)
	abort();		       /* FIXME */
    memcpy(b, orig, (orig[0] + 1) * sizeof(*b));
    return b;
}

void freebn(Bignum b)
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
    int mshift;
    int mlen, i, j;
    Bignum result;

    /* Allocate m of size mlen, copy mod to m */
    /* We use big endian internally */
    mlen = mod[0];
    m = smalloc(mlen * sizeof(unsigned short));
    for (j = 0; j < mlen; j++)
	m[j] = mod[mod[0] - j];

    /* Shift m left to make msb bit set */
    for (mshift = 0; mshift < 15; mshift++)
	if ((m[0] << mshift) & 0x8000)
	    break;
    if (mshift) {
	for (i = 0; i < mlen - 1; i++)
	    m[i] = (m[i] << mshift) | (m[i + 1] >> (16 - mshift));
	m[mlen - 1] = m[mlen - 1] << mshift;
    }

    /* Allocate n of size mlen, copy base to n */
    n = smalloc(mlen * sizeof(unsigned short));
    i = mlen - base[0];
    for (j = 0; j < i; j++)
	n[j] = 0;
    for (j = 0; j < base[0]; j++)
	n[i + j] = base[base[0] - j];

    /* Allocate a and b of size 2*mlen. Set a = 1 */
    a = smalloc(2 * mlen * sizeof(unsigned short));
    b = smalloc(2 * mlen * sizeof(unsigned short));
    for (i = 0; i < 2 * mlen; i++)
	a[i] = 0;
    a[2 * mlen - 1] = 1;

    /* Skip leading zero bits of exp. */
    i = 0;
    j = 15;







|














|







|
|







212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
    int mshift;
    int mlen, i, j;
    Bignum result;

    /* Allocate m of size mlen, copy mod to m */
    /* We use big endian internally */
    mlen = mod[0];
    m = snewn(mlen, unsigned short);
    for (j = 0; j < mlen; j++)
	m[j] = mod[mod[0] - j];

    /* Shift m left to make msb bit set */
    for (mshift = 0; mshift < 15; mshift++)
	if ((m[0] << mshift) & 0x8000)
	    break;
    if (mshift) {
	for (i = 0; i < mlen - 1; i++)
	    m[i] = (m[i] << mshift) | (m[i + 1] >> (16 - mshift));
	m[mlen - 1] = m[mlen - 1] << mshift;
    }

    /* Allocate n of size mlen, copy base to n */
    n = snewn(mlen, unsigned short);
    i = mlen - base[0];
    for (j = 0; j < i; j++)
	n[j] = 0;
    for (j = 0; j < base[0]; j++)
	n[i + j] = base[base[0] - j];

    /* Allocate a and b of size 2*mlen. Set a = 1 */
    a = snewn(2 * mlen, unsigned short);
    b = snewn(2 * mlen, unsigned short);
    for (i = 0; i < 2 * mlen; i++)
	a[i] = 0;
    a[2 * mlen - 1] = 1;

    /* Skip leading zero bits of exp. */
    i = 0;
    j = 15;
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
    int mshift;
    int pqlen, mlen, rlen, i, j;
    Bignum result;

    /* Allocate m of size mlen, copy mod to m */
    /* We use big endian internally */
    mlen = mod[0];
    m = smalloc(mlen * sizeof(unsigned short));
    for (j = 0; j < mlen; j++)
	m[j] = mod[mod[0] - j];

    /* Shift m left to make msb bit set */
    for (mshift = 0; mshift < 15; mshift++)
	if ((m[0] << mshift) & 0x8000)
	    break;
    if (mshift) {
	for (i = 0; i < mlen - 1; i++)
	    m[i] = (m[i] << mshift) | (m[i + 1] >> (16 - mshift));
	m[mlen - 1] = m[mlen - 1] << mshift;
    }

    pqlen = (p[0] > q[0] ? p[0] : q[0]);

    /* Allocate n of size pqlen, copy p to n */
    n = smalloc(pqlen * sizeof(unsigned short));
    i = pqlen - p[0];
    for (j = 0; j < i; j++)
	n[j] = 0;
    for (j = 0; j < p[0]; j++)
	n[i + j] = p[p[0] - j];

    /* Allocate o of size pqlen, copy q to o */
    o = smalloc(pqlen * sizeof(unsigned short));
    i = pqlen - q[0];
    for (j = 0; j < i; j++)
	o[j] = 0;
    for (j = 0; j < q[0]; j++)
	o[i + j] = q[q[0] - j];

    /* Allocate a of size 2*pqlen for result */
    a = smalloc(2 * pqlen * sizeof(unsigned short));

    /* Main computation */
    internal_mul(n, o, a, pqlen);
    internal_mod(a, pqlen * 2, m, mlen, NULL, 0);

    /* Fixup result in case the modulus was shifted */
    if (mshift) {







|
















|







|







|







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
    int mshift;
    int pqlen, mlen, rlen, i, j;
    Bignum result;

    /* Allocate m of size mlen, copy mod to m */
    /* We use big endian internally */
    mlen = mod[0];
    m = snewn(mlen, unsigned short);
    for (j = 0; j < mlen; j++)
	m[j] = mod[mod[0] - j];

    /* Shift m left to make msb bit set */
    for (mshift = 0; mshift < 15; mshift++)
	if ((m[0] << mshift) & 0x8000)
	    break;
    if (mshift) {
	for (i = 0; i < mlen - 1; i++)
	    m[i] = (m[i] << mshift) | (m[i + 1] >> (16 - mshift));
	m[mlen - 1] = m[mlen - 1] << mshift;
    }

    pqlen = (p[0] > q[0] ? p[0] : q[0]);

    /* Allocate n of size pqlen, copy p to n */
    n = snewn(pqlen, unsigned short);
    i = pqlen - p[0];
    for (j = 0; j < i; j++)
	n[j] = 0;
    for (j = 0; j < p[0]; j++)
	n[i + j] = p[p[0] - j];

    /* Allocate o of size pqlen, copy q to o */
    o = snewn(pqlen, unsigned short);
    i = pqlen - q[0];
    for (j = 0; j < i; j++)
	o[j] = 0;
    for (j = 0; j < q[0]; j++)
	o[i + j] = q[q[0] - j];

    /* Allocate a of size 2*pqlen for result */
    a = snewn(2 * pqlen, unsigned short);

    /* Main computation */
    internal_mul(n, o, a, pqlen);
    internal_mod(a, pqlen * 2, m, mlen, NULL, 0);

    /* Fixup result in case the modulus was shifted */
    if (mshift) {
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
    unsigned short *n, *m;
    int mshift;
    int plen, mlen, i, j;

    /* Allocate m of size mlen, copy mod to m */
    /* We use big endian internally */
    mlen = mod[0];
    m = smalloc(mlen * sizeof(unsigned short));
    for (j = 0; j < mlen; j++)
	m[j] = mod[mod[0] - j];

    /* Shift m left to make msb bit set */
    for (mshift = 0; mshift < 15; mshift++)
	if ((m[0] << mshift) & 0x8000)
	    break;
    if (mshift) {
	for (i = 0; i < mlen - 1; i++)
	    m[i] = (m[i] << mshift) | (m[i + 1] >> (16 - mshift));
	m[mlen - 1] = m[mlen - 1] << mshift;
    }

    plen = p[0];
    /* Ensure plen > mlen */
    if (plen <= mlen)
	plen = mlen + 1;

    /* Allocate n of size plen, copy p to n */
    n = smalloc(plen * sizeof(unsigned short));
    for (j = 0; j < plen; j++)
	n[j] = 0;
    for (j = 1; j <= p[0]; j++)
	n[plen - j] = p[j];

    /* Main computation */
    internal_mod(n, plen, m, mlen, quotient, mshift);







|



















|







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
    unsigned short *n, *m;
    int mshift;
    int plen, mlen, i, j;

    /* Allocate m of size mlen, copy mod to m */
    /* We use big endian internally */
    mlen = mod[0];
    m = snewn(mlen, unsigned short);
    for (j = 0; j < mlen; j++)
	m[j] = mod[mod[0] - j];

    /* Shift m left to make msb bit set */
    for (mshift = 0; mshift < 15; mshift++)
	if ((m[0] << mshift) & 0x8000)
	    break;
    if (mshift) {
	for (i = 0; i < mlen - 1; i++)
	    m[i] = (m[i] << mshift) | (m[i + 1] >> (16 - mshift));
	m[mlen - 1] = m[mlen - 1] << mshift;
    }

    plen = p[0];
    /* Ensure plen > mlen */
    if (plen <= mlen)
	plen = mlen + 1;

    /* Allocate n of size plen, copy p to n */
    n = snewn(plen, unsigned short);
    for (j = 0; j < plen; j++)
	n[j] = 0;
    for (j = 1; j <= p[0]; j++)
	n[plen - j] = p[j];

    /* Main computation */
    internal_mod(n, plen, m, mlen, quotient, mshift);
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
    int alen = a[0], blen = b[0];
    int mlen = (alen > blen ? alen : blen);
    int rlen, i, maxspot;
    unsigned short *workspace;
    Bignum ret;

    /* mlen space for a, mlen space for b, 2*mlen for result */
    workspace = smalloc(mlen * 4 * sizeof(unsigned short));
    for (i = 0; i < mlen; i++) {
	workspace[0 * mlen + i] = (mlen - i <= a[0] ? a[mlen - i] : 0);
	workspace[1 * mlen + i] = (mlen - i <= b[0] ? b[mlen - i] : 0);
    }

    internal_mul(workspace + 0 * mlen, workspace + 1 * mlen,
		 workspace + 2 * mlen, mlen);







|







669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
    int alen = a[0], blen = b[0];
    int mlen = (alen > blen ? alen : blen);
    int rlen, i, maxspot;
    unsigned short *workspace;
    Bignum ret;

    /* mlen space for a, mlen space for b, 2*mlen for result */
    workspace = snewn(mlen * 4, unsigned short);
    for (i = 0; i < mlen; i++) {
	workspace[0 * mlen + i] = (mlen - i <= a[0] ? a[mlen - i] : 0);
	workspace[1 * mlen + i] = (mlen - i <= b[0] ? b[mlen - i] : 0);
    }

    internal_mul(workspace + 0 * mlen, workspace + 1 * mlen,
		 workspace + 2 * mlen, mlen);
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
     * round up (rounding down might make it less than x again).
     * Therefore if we multiply the bit count by 28/93, rounding
     * up, we will have enough digits.
     */
    i = bignum_bitcount(x);
    ndigits = (28 * i + 92) / 93;      /* multiply by 28/93 and round up */
    ndigits++;			       /* allow for trailing \0 */
    ret = smalloc(ndigits);

    /*
     * Now allocate some workspace to hold the binary form as we
     * repeatedly divide it by ten. Initialise this to the
     * big-endian form of the number.
     */
    workspace = smalloc(sizeof(unsigned short) * x[0]);
    for (i = 0; i < x[0]; i++)
	workspace[i] = x[x[0] - i];

    /*
     * Next, write the decimal number starting with the last digit.
     * We use ordinary short division, dividing 10 into the
     * workspace.







|






|







945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
     * round up (rounding down might make it less than x again).
     * Therefore if we multiply the bit count by 28/93, rounding
     * up, we will have enough digits.
     */
    i = bignum_bitcount(x);
    ndigits = (28 * i + 92) / 93;      /* multiply by 28/93 and round up */
    ndigits++;			       /* allow for trailing \0 */
    ret = snewn(ndigits, char);

    /*
     * Now allocate some workspace to hold the binary form as we
     * repeatedly divide it by ten. Initialise this to the
     * big-endian form of the number.
     */
    workspace = snewn(x[0], unsigned short);
    for (i = 0; i < x[0]; i++)
	workspace[i] = x[x[0] - i];

    /*
     * Next, write the decimal number starting with the last digit.
     * We use ordinary short division, dividing 10 into the
     * workspace.
Changes to sshcrcda.c.
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
struct crcda_ctx {
    uint16 *h;
    uint32 n;
};

void *crcda_make_context(void)
{
    struct crcda_ctx *ret = smalloc(sizeof(struct crcda_ctx));
    ret->h = NULL;
    ret->n = HASH_MINSIZE / HASH_ENTRYSIZE;
    return ret;
}

void crcda_free_context(void *handle)
{







|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
struct crcda_ctx {
    uint16 *h;
    uint32 n;
};

void *crcda_make_context(void)
{
    struct crcda_ctx *ret = snew(struct crcda_ctx);
    ret->h = NULL;
    ret->n = HASH_MINSIZE / HASH_ENTRYSIZE;
    return ret;
}

void crcda_free_context(void *handle)
{
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    assert(!(len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
             len % SSH_BLOCKSIZE != 0));
    for (l = ctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
        ;

    if (ctx->h == NULL) {
        ctx->n = l;
        ctx->h = (uint16 *) smalloc(ctx->n * HASH_ENTRYSIZE);
    } else {
        if (l > ctx->n) {
            ctx->n = l;
            ctx->h = (uint16 *) srealloc(ctx->h, ctx->n * HASH_ENTRYSIZE);
        }
    }

    if (len <= HASH_MINBLOCKS) {
        for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
            if (IV && (!CMP(c, IV))) {
                if ((check_crc(c, buf, len, IV)))







|



|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    assert(!(len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
             len % SSH_BLOCKSIZE != 0));
    for (l = ctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
        ;

    if (ctx->h == NULL) {
        ctx->n = l;
        ctx->h = snewn(ctx->n, uint16);
    } else {
        if (l > ctx->n) {
            ctx->n = l;
            ctx->h = sresize(ctx->h, ctx->n, uint16);
        }
    }

    if (len <= HASH_MINBLOCKS) {
        for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
            if (IV && (!CMP(c, IV))) {
                if ((check_crc(c, buf, len, IV)))
Changes to sshdes.c.
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
    }
    scheds->iv0 = iv0;
    scheds->iv1 = iv1;
}

static void *des3_make_context(void)
{
    return smalloc(3*sizeof(DESContext));
}

static void *des3_ssh1_make_context(void)
{
    /* Need 3 keys for each direction, in SSH1 */
    return smalloc(6*sizeof(DESContext));
}

static void *des_make_context(void)
{
    return smalloc(sizeof(DESContext));
}

static void *des_ssh1_make_context(void)
{
    /* Need one key for each direction, in SSH1 */
    return smalloc(2*sizeof(DESContext));
}

static void des3_free_context(void *handle)   /* used for both 3DES and DES */
{
    sfree(handle);
}








|





|




|





|







742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
    }
    scheds->iv0 = iv0;
    scheds->iv1 = iv1;
}

static void *des3_make_context(void)
{
    return snewn(3, DESContext);
}

static void *des3_ssh1_make_context(void)
{
    /* Need 3 keys for each direction, in SSH1 */
    return snewn(6, DESContext);
}

static void *des_make_context(void)
{
    return snew(DESContext);
}

static void *des_ssh1_make_context(void)
{
    /* Need one key for each direction, in SSH1 */
    return snewn(2, DESContext);
}

static void des3_free_context(void *handle)   /* used for both 3DES and DES */
{
    sfree(handle);
}

Changes to sshdh.c.
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
}

/*
 * Initialise DH for the standard group1.
 */
void *dh_setup_group1(void)
{
    struct dh_ctx *ctx = smalloc(sizeof(struct dh_ctx));
    ctx->p = bignum_from_bytes(P, sizeof(P));
    ctx->g = bignum_from_bytes(G, sizeof(G));
    dh_init(ctx);
    return ctx;
}

/*
 * Initialise DH for an alternative group.
 */
void *dh_setup_group(Bignum pval, Bignum gval)
{
    struct dh_ctx *ctx = smalloc(sizeof(struct dh_ctx));
    ctx->p = copybn(pval);
    ctx->g = copybn(gval);
    dh_init(ctx);
    return ctx;
}

/*







|











|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
}

/*
 * Initialise DH for the standard group1.
 */
void *dh_setup_group1(void)
{
    struct dh_ctx *ctx = snew(struct dh_ctx);
    ctx->p = bignum_from_bytes(P, sizeof(P));
    ctx->g = bignum_from_bytes(G, sizeof(G));
    dh_init(ctx);
    return ctx;
}

/*
 * Initialise DH for an alternative group.
 */
void *dh_setup_group(Bignum pval, Bignum gval)
{
    struct dh_ctx *ctx = snew(struct dh_ctx);
    ctx->p = copybn(pval);
    ctx->g = copybn(gval);
    dh_init(ctx);
    return ctx;
}

/*
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
    struct dh_ctx *ctx = (struct dh_ctx *)handle;
    int i;

    int nbytes;
    unsigned char *buf;

    nbytes = ssh1_bignum_length(ctx->qmask);
    buf = smalloc(nbytes);

    do {
	/*
	 * Create a potential x, by ANDing a string of random bytes
	 * with qmask.
	 */
	if (ctx->x)







|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
    struct dh_ctx *ctx = (struct dh_ctx *)handle;
    int i;

    int nbytes;
    unsigned char *buf;

    nbytes = ssh1_bignum_length(ctx->qmask);
    buf = snewn(nbytes, unsigned char);

    do {
	/*
	 * Create a potential x, by ANDing a string of random bytes
	 * with qmask.
	 */
	if (ctx->x)
Changes to sshdss.c.
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

static void *dss_newkey(char *data, int len)
{
    char *p;
    int slen;
    struct dss_key *dss;

    dss = smalloc(sizeof(struct dss_key));
    if (!dss)
	return NULL;
    getstring(&data, &len, &p, &slen);

#ifdef DEBUG_DSS
    {
	int i;







|







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

static void *dss_newkey(char *data, int len)
{
    char *p;
    int slen;
    struct dss_key *dss;

    dss = snew(struct dss_key);
    if (!dss)
	return NULL;
    getstring(&data, &len, &p, &slen);

#ifdef DEBUG_DSS
    {
	int i;
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
    if (!dss->p)
	return NULL;
    len = 8 + 4 + 1;		       /* 4 x "0x", punctuation, \0 */
    len += 4 * (bignum_bitcount(dss->p) + 15) / 16;
    len += 4 * (bignum_bitcount(dss->q) + 15) / 16;
    len += 4 * (bignum_bitcount(dss->g) + 15) / 16;
    len += 4 * (bignum_bitcount(dss->y) + 15) / 16;
    p = smalloc(len);
    if (!p)
	return NULL;

    pos = 0;
    pos += sprintf(p + pos, "0x");
    nibbles = (3 + bignum_bitcount(dss->p)) / 4;
    if (nibbles < 1)







|







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
    if (!dss->p)
	return NULL;
    len = 8 + 4 + 1;		       /* 4 x "0x", punctuation, \0 */
    len += 4 * (bignum_bitcount(dss->p) + 15) / 16;
    len += 4 * (bignum_bitcount(dss->q) + 15) / 16;
    len += 4 * (bignum_bitcount(dss->g) + 15) / 16;
    len += 4 * (bignum_bitcount(dss->y) + 15) / 16;
    p = snewn(len, char);
    if (!p)
	return NULL;

    pos = 0;
    pos += sprintf(p + pos, "0x");
    nibbles = (3 + bignum_bitcount(dss->p)) / 4;
    if (nibbles < 1)
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

    MD5Final(digest, &md5c);

    sprintf(buffer, "ssh-dss %d ", bignum_bitcount(dss->p));
    for (i = 0; i < 16; i++)
	sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
		digest[i]);
    ret = smalloc(strlen(buffer) + 1);
    if (ret)
	strcpy(ret, buffer);
    return ret;
}

static int dss_verifysig(void *key, char *sig, int siglen,
			 char *data, int datalen)







|







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

    MD5Final(digest, &md5c);

    sprintf(buffer, "ssh-dss %d ", bignum_bitcount(dss->p));
    for (i = 0; i < 16; i++)
	sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
		digest[i]);
    ret = snewn(strlen(buffer) + 1, char);
    if (ret)
	strcpy(ret, buffer);
    return ret;
}

static int dss_verifysig(void *key, char *sig, int siglen,
			 char *data, int datalen)
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
    ylen = (bignum_bitcount(dss->y) + 8) / 8;

    /*
     * string "ssh-dss", mpint p, mpint q, mpint g, mpint y. Total
     * 27 + sum of lengths. (five length fields, 20+7=27).
     */
    bloblen = 27 + plen + qlen + glen + ylen;
    blob = smalloc(bloblen);
    p = blob;
    PUT_32BIT(p, 7);
    p += 4;
    memcpy(p, "ssh-dss", 7);
    p += 7;
    PUT_32BIT(p, plen);
    p += 4;







|







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
    ylen = (bignum_bitcount(dss->y) + 8) / 8;

    /*
     * string "ssh-dss", mpint p, mpint q, mpint g, mpint y. Total
     * 27 + sum of lengths. (five length fields, 20+7=27).
     */
    bloblen = 27 + plen + qlen + glen + ylen;
    blob = snewn(bloblen, unsigned char);
    p = blob;
    PUT_32BIT(p, 7);
    p += 4;
    memcpy(p, "ssh-dss", 7);
    p += 7;
    PUT_32BIT(p, plen);
    p += 4;
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372

    xlen = (bignum_bitcount(dss->x) + 8) / 8;

    /*
     * mpint x, string[20] the SHA of p||q||g. Total 4 + xlen.
     */
    bloblen = 4 + xlen;
    blob = smalloc(bloblen);
    p = blob;
    PUT_32BIT(p, xlen);
    p += 4;
    for (i = xlen; i--;)
	*p++ = bignum_byte(dss->x, i);
    assert(p == blob + bloblen);
    *len = bloblen;







|







358
359
360
361
362
363
364
365
366
367
368
369
370
371
372

    xlen = (bignum_bitcount(dss->x) + 8) / 8;

    /*
     * mpint x, string[20] the SHA of p||q||g. Total 4 + xlen.
     */
    bloblen = 4 + xlen;
    blob = snewn(bloblen, unsigned char);
    p = blob;
    PUT_32BIT(p, xlen);
    p += 4;
    for (i = xlen; i--;)
	*p++ = bignum_byte(dss->x, i);
    assert(p == blob + bloblen);
    *len = bloblen;
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
}

static void *dss_openssh_createkey(unsigned char **blob, int *len)
{
    char **b = (char **) blob;
    struct dss_key *dss;

    dss = smalloc(sizeof(struct dss_key));
    if (!dss)
	return NULL;

    dss->p = getmp(b, len);
    dss->q = getmp(b, len);
    dss->g = getmp(b, len);
    dss->y = getmp(b, len);







|







418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
}

static void *dss_openssh_createkey(unsigned char **blob, int *len)
{
    char **b = (char **) blob;
    struct dss_key *dss;

    dss = snew(struct dss_key);
    if (!dss)
	return NULL;

    dss->p = getmp(b, len);
    dss->q = getmp(b, len);
    dss->g = getmp(b, len);
    dss->y = getmp(b, len);
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
     * 
     *   string  "ssh-dss"
     *   string  two 20-byte numbers r and s, end to end
     * 
     * i.e. 4+7 + 4+40 bytes.
     */
    nbytes = 4 + 7 + 4 + 40;
    bytes = smalloc(nbytes);
    PUT_32BIT(bytes, 7);
    memcpy(bytes + 4, "ssh-dss", 7);
    PUT_32BIT(bytes + 4 + 7, 40);
    for (i = 0; i < 20; i++) {
	bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i);
	bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i);
    }







|







602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
     * 
     *   string  "ssh-dss"
     *   string  two 20-byte numbers r and s, end to end
     * 
     * i.e. 4+7 + 4+40 bytes.
     */
    nbytes = 4 + 7 + 4 + 40;
    bytes = snewn(nbytes, unsigned char);
    PUT_32BIT(bytes, 7);
    memcpy(bytes + 4, "ssh-dss", 7);
    PUT_32BIT(bytes + 4 + 7, 40);
    for (i = 0; i < 20; i++) {
	bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i);
	bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i);
    }
Changes to sshmd5.c.
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/* ----------------------------------------------------------------------
 * The above is the MD5 algorithm itself. Now we implement the
 * HMAC wrapper on it.
 */

static void *md5_make_context(void)
{
    return smalloc(2*sizeof(struct MD5Context));
}

static void md5_free_context(void *handle)
{
    sfree(handle);
}








|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/* ----------------------------------------------------------------------
 * The above is the MD5 algorithm itself. Now we implement the
 * HMAC wrapper on it.
 */

static void *md5_make_context(void)
{
    return snewn(2, struct MD5Context);
}

static void md5_free_context(void *handle)
{
    sfree(handle);
}

Changes to sshpubk.c.
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
    }

    /* Next, the comment field. */
    j = GET_32BIT(buf + i);
    i += 4;
    if (len - i < j)
	goto end;
    comment = smalloc(j + 1);
    if (comment) {
	memcpy(comment, buf + i, j);
	comment[j] = '\0';
    }
    i += j;
    if (commentptr)
	*commentptr = comment;







|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
    }

    /* Next, the comment field. */
    j = GET_32BIT(buf + i);
    i += 4;
    if (len - i < j)
	goto end;
    comment = snewn(j + 1, char);
    if (comment) {
	memcpy(comment, buf + i, j);
	comment[j] = '\0';
    }
    i += j;
    if (commentptr)
	*commentptr = comment;
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
{
    char *text;
    int len;
    int size;
    int c;

    size = 128;
    text = smalloc(size);
    len = 0;
    text[len] = '\0';

    while (1) {
	c = fgetc(fp);
	if (c == '\r' || c == '\n') {
	    c = fgetc(fp);
	    if (c != '\r' && c != '\n' && c != EOF)
		ungetc(c, fp);
	    return text;
	}
	if (c == EOF) {
	    sfree(text);
	    return NULL;
	}
	if (len + 1 > size) {
	    size += 128;
	    text = srealloc(text, size);
	}
	text[len++] = c;
	text[len] = '\0';
    }
}

int base64_decode_atom(char *atom, unsigned char *out)







|

















|







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
{
    char *text;
    int len;
    int size;
    int c;

    size = 128;
    text = snewn(size, char);
    len = 0;
    text[len] = '\0';

    while (1) {
	c = fgetc(fp);
	if (c == '\r' || c == '\n') {
	    c = fgetc(fp);
	    if (c != '\r' && c != '\n' && c != EOF)
		ungetc(c, fp);
	    return text;
	}
	if (c == EOF) {
	    sfree(text);
	    return NULL;
	}
	if (len + 1 > size) {
	    size += 128;
	    text = sresize(text, size, char);
	}
	text[len++] = c;
	text[len] = '\0';
    }
}

int base64_decode_atom(char *atom, unsigned char *out)
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
{
    unsigned char *blob;
    char *line;
    int linelen, len;
    int i, j, k;

    /* We expect at most 64 base64 characters, ie 48 real bytes, per line. */
    blob = smalloc(48 * nlines);
    len = 0;
    for (i = 0; i < nlines; i++) {
	line = read_body(fp);
	if (!line) {
	    sfree(blob);
	    return NULL;
	}







|







534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
{
    unsigned char *blob;
    char *line;
    int linelen, len;
    int i, j, k;

    /* We expect at most 64 base64 characters, ie 48 real bytes, per line. */
    blob = snewn(48 * nlines, unsigned char);
    len = 0;
    for (i = 0; i < nlines; i++) {
	line = read_body(fp);
	if (!line) {
	    sfree(blob);
	    return NULL;
	}
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
	    int enclen = strlen(encryption);
	    int commlen = strlen(comment);
	    maclen = (4 + namelen +
		      4 + enclen +
		      4 + commlen +
		      4 + public_blob_len +
		      4 + private_blob_len);
	    macdata = smalloc(maclen);
	    p = macdata;
#define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)
	    DO_STR(alg->name, namelen);
	    DO_STR(encryption, enclen);
	    DO_STR(comment, commlen);
	    DO_STR(public_blob, public_blob_len);
	    DO_STR(private_blob, private_blob_len);







|







723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
	    int enclen = strlen(encryption);
	    int commlen = strlen(comment);
	    maclen = (4 + namelen +
		      4 + enclen +
		      4 + commlen +
		      4 + public_blob_len +
		      4 + private_blob_len);
	    macdata = snewn(maclen, unsigned char);
	    p = macdata;
#define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)
	    DO_STR(alg->name, namelen);
	    DO_STR(encryption, enclen);
	    DO_STR(comment, commlen);
	    DO_STR(public_blob, public_blob_len);
	    DO_STR(private_blob, private_blob_len);
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
	}
    }
    sfree(mac);

    /*
     * Create and return the key.
     */
    ret = smalloc(sizeof(struct ssh2_userkey));
    ret->alg = alg;
    ret->comment = comment;
    ret->data = alg->createkey(public_blob, public_blob_len,
			       private_blob, private_blob_len);
    if (!ret->data) {
	sfree(ret->comment);
	sfree(ret);







|







774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
	}
    }
    sfree(mac);

    /*
     * Create and return the key.
     */
    ret = snew(struct ssh2_userkey);
    ret->alg = alg;
    ret->comment = comment;
    ret->data = alg->createkey(public_blob, public_blob_len,
			       private_blob, private_blob_len);
    if (!ret->data) {
	sfree(ret->comment);
	sfree(ret);
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
	cipherblk = 16;
    } else {
	cipherstr = "none";
	cipherblk = 1;
    }
    priv_encrypted_len = priv_blob_len + cipherblk - 1;
    priv_encrypted_len -= priv_encrypted_len % cipherblk;
    priv_blob_encrypted = smalloc(priv_encrypted_len);
    memset(priv_blob_encrypted, 0, priv_encrypted_len);
    memcpy(priv_blob_encrypted, priv_blob, priv_blob_len);
    /* Create padding based on the SHA hash of the unpadded blob. This prevents
     * too easy a known-plaintext attack on the last block. */
    SHA_Simple(priv_blob, priv_blob_len, priv_mac);
    assert(priv_encrypted_len - priv_blob_len < 20);
    memcpy(priv_blob_encrypted + priv_blob_len, priv_mac,







|







1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
	cipherblk = 16;
    } else {
	cipherstr = "none";
	cipherblk = 1;
    }
    priv_encrypted_len = priv_blob_len + cipherblk - 1;
    priv_encrypted_len -= priv_encrypted_len % cipherblk;
    priv_blob_encrypted = snewn(priv_encrypted_len, unsigned char);
    memset(priv_blob_encrypted, 0, priv_encrypted_len);
    memcpy(priv_blob_encrypted, priv_blob, priv_blob_len);
    /* Create padding based on the SHA hash of the unpadded blob. This prevents
     * too easy a known-plaintext attack on the last block. */
    SHA_Simple(priv_blob, priv_blob_len, priv_mac);
    assert(priv_encrypted_len - priv_blob_len < 20);
    memcpy(priv_blob_encrypted + priv_blob_len, priv_mac,
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
	char header[] = "putty-private-key-file-mac-key";

	maclen = (4 + namelen +
		  4 + enclen +
		  4 + commlen +
		  4 + pub_blob_len +
		  4 + priv_encrypted_len);
	macdata = smalloc(maclen);
	p = macdata;
#define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)
	DO_STR(key->alg->name, namelen);
	DO_STR(cipherstr, enclen);
	DO_STR(key->comment, commlen);
	DO_STR(pub_blob, pub_blob_len);
	DO_STR(priv_blob_encrypted, priv_encrypted_len);







|







1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
	char header[] = "putty-private-key-file-mac-key";

	maclen = (4 + namelen +
		  4 + enclen +
		  4 + commlen +
		  4 + pub_blob_len +
		  4 + priv_encrypted_len);
	macdata = snewn(maclen, unsigned char);
	p = macdata;
#define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)
	DO_STR(key->alg->name, namelen);
	DO_STR(cipherstr, enclen);
	DO_STR(key->comment, commlen);
	DO_STR(pub_blob, pub_blob_len);
	DO_STR(priv_blob_encrypted, priv_encrypted_len);
Changes to sshrand.c.
198
199
200
201
202
203
204
205
206
207
208
209
210
211
	random_stir();

    return pool.pool[pool.poolpos++];
}

void random_get_savedata(void **data, int *len)
{
    void *buf = smalloc(POOLSIZE / 2);
    random_stir();
    memcpy(buf, pool.pool + pool.poolpos, POOLSIZE / 2);
    *len = POOLSIZE / 2;
    *data = buf;
    random_stir();
}







|






198
199
200
201
202
203
204
205
206
207
208
209
210
211
	random_stir();

    return pool.pool[pool.poolpos++];
}

void random_get_savedata(void **data, int *len)
{
    void *buf = snewn(POOLSIZE / 2, char);
    random_stir();
    memcpy(buf, pool.pool + pool.poolpos, POOLSIZE / 2);
    *len = POOLSIZE / 2;
    *data = buf;
    random_stir();
}
Changes to sshrsa.c.
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
unsigned char *rsa_public_blob(struct RSAKey *key, int *len)
{
    int length, pos;
    unsigned char *ret;

    length = (ssh1_bignum_length(key->modulus) +
	      ssh1_bignum_length(key->exponent) + 4);
    ret = smalloc(length);

    PUT_32BIT(ret, bignum_bitcount(key->modulus));
    pos = 4;
    pos += ssh1_write_bignum(ret + pos, key->exponent);
    pos += ssh1_write_bignum(ret + pos, key->modulus);

    *len = length;







|







312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
unsigned char *rsa_public_blob(struct RSAKey *key, int *len)
{
    int length, pos;
    unsigned char *ret;

    length = (ssh1_bignum_length(key->modulus) +
	      ssh1_bignum_length(key->exponent) + 4);
    ret = snewn(length, unsigned char);

    PUT_32BIT(ret, bignum_bitcount(key->modulus));
    pos = 4;
    pos += ssh1_write_bignum(ret + pos, key->exponent);
    pos += ssh1_write_bignum(ret + pos, key->modulus);

    *len = length;
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

static void *rsa2_newkey(char *data, int len)
{
    char *p;
    int slen;
    struct RSAKey *rsa;

    rsa = smalloc(sizeof(struct RSAKey));
    if (!rsa)
	return NULL;
    getstring(&data, &len, &p, &slen);

    if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
	sfree(rsa);
	return NULL;







|







384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

static void *rsa2_newkey(char *data, int len)
{
    char *p;
    int slen;
    struct RSAKey *rsa;

    rsa = snew(struct RSAKey);
    if (!rsa)
	return NULL;
    getstring(&data, &len, &p, &slen);

    if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
	sfree(rsa);
	return NULL;
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
static char *rsa2_fmtkey(void *key)
{
    struct RSAKey *rsa = (struct RSAKey *) key;
    char *p;
    int len;

    len = rsastr_len(rsa);
    p = smalloc(len);
    rsastr_fmt(p, rsa);
    return p;
}

static unsigned char *rsa2_public_blob(void *key, int *len)
{
    struct RSAKey *rsa = (struct RSAKey *) key;
    int elen, mlen, bloblen;
    int i;
    unsigned char *blob, *p;

    elen = (bignum_bitcount(rsa->exponent) + 8) / 8;
    mlen = (bignum_bitcount(rsa->modulus) + 8) / 8;

    /*
     * string "ssh-rsa", mpint exp, mpint mod. Total 19+elen+mlen.
     * (three length fields, 12+7=19).
     */
    bloblen = 19 + elen + mlen;
    blob = smalloc(bloblen);
    p = blob;
    PUT_32BIT(p, 7);
    p += 4;
    memcpy(p, "ssh-rsa", 7);
    p += 7;
    PUT_32BIT(p, elen);
    p += 4;







|



















|







415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
static char *rsa2_fmtkey(void *key)
{
    struct RSAKey *rsa = (struct RSAKey *) key;
    char *p;
    int len;

    len = rsastr_len(rsa);
    p = snewn(len, char);
    rsastr_fmt(p, rsa);
    return p;
}

static unsigned char *rsa2_public_blob(void *key, int *len)
{
    struct RSAKey *rsa = (struct RSAKey *) key;
    int elen, mlen, bloblen;
    int i;
    unsigned char *blob, *p;

    elen = (bignum_bitcount(rsa->exponent) + 8) / 8;
    mlen = (bignum_bitcount(rsa->modulus) + 8) / 8;

    /*
     * string "ssh-rsa", mpint exp, mpint mod. Total 19+elen+mlen.
     * (three length fields, 12+7=19).
     */
    bloblen = 19 + elen + mlen;
    blob = snewn(bloblen, unsigned char);
    p = blob;
    PUT_32BIT(p, 7);
    p += 4;
    memcpy(p, "ssh-rsa", 7);
    p += 7;
    PUT_32BIT(p, elen);
    p += 4;
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
    ulen = (bignum_bitcount(rsa->iqmp) + 8) / 8;

    /*
     * mpint private_exp, mpint p, mpint q, mpint iqmp. Total 16 +
     * sum of lengths.
     */
    bloblen = 16 + dlen + plen + qlen + ulen;
    blob = smalloc(bloblen);
    p = blob;
    PUT_32BIT(p, dlen);
    p += 4;
    for (i = dlen; i--;)
	*p++ = bignum_byte(rsa->private_exponent, i);
    PUT_32BIT(p, plen);
    p += 4;







|







471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
    ulen = (bignum_bitcount(rsa->iqmp) + 8) / 8;

    /*
     * mpint private_exp, mpint p, mpint q, mpint iqmp. Total 16 +
     * sum of lengths.
     */
    bloblen = 16 + dlen + plen + qlen + ulen;
    blob = snewn(bloblen, unsigned char);
    p = blob;
    PUT_32BIT(p, dlen);
    p += 4;
    for (i = dlen; i--;)
	*p++ = bignum_byte(rsa->private_exponent, i);
    PUT_32BIT(p, plen);
    p += 4;
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
}

static void *rsa2_openssh_createkey(unsigned char **blob, int *len)
{
    char **b = (char **) blob;
    struct RSAKey *rsa;

    rsa = smalloc(sizeof(struct RSAKey));
    if (!rsa)
	return NULL;
    rsa->comment = NULL;

    rsa->modulus = getmp(b, len);
    rsa->exponent = getmp(b, len);
    rsa->private_exponent = getmp(b, len);







|







519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
}

static void *rsa2_openssh_createkey(unsigned char **blob, int *len)
{
    char **b = (char **) blob;
    struct RSAKey *rsa;

    rsa = snew(struct RSAKey);
    if (!rsa)
	return NULL;
    rsa->comment = NULL;

    rsa->modulus = getmp(b, len);
    rsa->exponent = getmp(b, len);
    rsa->private_exponent = getmp(b, len);
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618

    MD5Final(digest, &md5c);

    sprintf(buffer, "ssh-rsa %d ", bignum_bitcount(rsa->modulus));
    for (i = 0; i < 16; i++)
	sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
		digest[i]);
    ret = smalloc(strlen(buffer) + 1);
    if (ret)
	strcpy(ret, buffer);
    return ret;
}

/*
 * This is the magic ASN.1/DER prefix that goes in the decoded







|







604
605
606
607
608
609
610
611
612
613
614
615
616
617
618

    MD5Final(digest, &md5c);

    sprintf(buffer, "ssh-rsa %d ", bignum_bitcount(rsa->modulus));
    for (i = 0; i < 16; i++)
	sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
		digest[i]);
    ret = snewn(strlen(buffer) + 1, char);
    if (ret)
	strcpy(ret, buffer);
    return ret;
}

/*
 * This is the magic ASN.1/DER prefix that goes in the decoded
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
    unsigned char hash[20];
    Bignum in, out;
    int i, j;

    SHA_Simple(data, datalen, hash);

    nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8;
    bytes = smalloc(nbytes);

    bytes[0] = 1;
    for (i = 1; i < nbytes - 20 - ASN1_LEN; i++)
	bytes[i] = 0xFF;
    for (i = nbytes - 20 - ASN1_LEN, j = 0; i < nbytes - 20; i++, j++)
	bytes[i] = asn1_weird_stuff[j];
    for (i = nbytes - 20, j = 0; i < nbytes; i++, j++)
	bytes[i] = hash[j];

    in = bignum_from_bytes(bytes, nbytes);
    sfree(bytes);

    out = rsa_privkey_op(in, rsa);
    freebn(in);

    nbytes = (bignum_bitcount(out) + 7) / 8;
    bytes = smalloc(4 + 7 + 4 + nbytes);
    PUT_32BIT(bytes, 7);
    memcpy(bytes + 4, "ssh-rsa", 7);
    PUT_32BIT(bytes + 4 + 7, nbytes);
    for (i = 0; i < nbytes; i++)
	bytes[4 + 7 + 4 + i] = bignum_byte(out, nbytes - 1 - i);
    freebn(out);








|
















|







701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
    unsigned char hash[20];
    Bignum in, out;
    int i, j;

    SHA_Simple(data, datalen, hash);

    nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8;
    bytes = snewn(nbytes, unsigned char);

    bytes[0] = 1;
    for (i = 1; i < nbytes - 20 - ASN1_LEN; i++)
	bytes[i] = 0xFF;
    for (i = nbytes - 20 - ASN1_LEN, j = 0; i < nbytes - 20; i++, j++)
	bytes[i] = asn1_weird_stuff[j];
    for (i = nbytes - 20, j = 0; i < nbytes; i++, j++)
	bytes[i] = hash[j];

    in = bignum_from_bytes(bytes, nbytes);
    sfree(bytes);

    out = rsa_privkey_op(in, rsa);
    freebn(in);

    nbytes = (bignum_bitcount(out) + 7) / 8;
    bytes = snewn(4 + 7 + 4 + nbytes, unsigned char);
    PUT_32BIT(bytes, 7);
    memcpy(bytes + 4, "ssh-rsa", 7);
    PUT_32BIT(bytes + 4 + 7, nbytes);
    for (i = 0; i < nbytes; i++)
	bytes[4 + 7 + 4 + i] = bignum_byte(out, nbytes - 1 - i);
    freebn(out);

Changes to sshsha.c.
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* ----------------------------------------------------------------------
 * The above is the SHA-1 algorithm itself. Now we implement the
 * HMAC wrapper on it.
 */

static void *sha1_make_context(void)
{
    return smalloc(2*sizeof(SHA_State));
}

static void sha1_free_context(void *handle)
{
    sfree(handle);
}








|







191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* ----------------------------------------------------------------------
 * The above is the SHA-1 algorithm itself. Now we implement the
 * HMAC wrapper on it.
 */

static void *sha1_make_context(void)
{
    return snewn(2, SHA_State);
}

static void sha1_free_context(void *handle)
{
    sfree(handle);
}

Changes to sshzlib.c.
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
}

static int lz77_init(struct LZ77Context *ctx)
{
    struct LZ77InternalContext *st;
    int i;

    st = (struct LZ77InternalContext *) smalloc(sizeof(*st));
    if (!st)
	return 0;

    ctx->ictx = st;

    for (i = 0; i < WINSIZE; i++)
	st->win[i].next = st->win[i].prev = st->win[i].hashval = INVALID;







|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
}

static int lz77_init(struct LZ77Context *ctx)
{
    struct LZ77InternalContext *st;
    int i;

    st = snew(struct LZ77InternalContext);
    if (!st)
	return 0;

    ctx->ictx = st;

    for (i = 0; i < WINSIZE; i++)
	st->win[i].next = st->win[i].prev = st->win[i].hashval = INVALID;
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
{
    assert(out->noutbits + nbits <= 32);
    out->outbits |= bits << out->noutbits;
    out->noutbits += nbits;
    while (out->noutbits >= 8) {
	if (out->outlen >= out->outsize) {
	    out->outsize = out->outlen + 64;
	    out->outbuf = srealloc(out->outbuf, out->outsize);
	}
	out->outbuf[out->outlen++] = (unsigned char) (out->outbits & 0xFF);
	out->outbits >>= 8;
	out->noutbits -= 8;
    }
}








|







350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
{
    assert(out->noutbits + nbits <= 32);
    out->outbits |= bits << out->noutbits;
    out->noutbits += nbits;
    while (out->noutbits >= 8) {
	if (out->outlen >= out->outsize) {
	    out->outsize = out->outlen + 64;
	    out->outbuf = sresize(out->outbuf, out->outsize, unsigned char);
	}
	out->outbuf[out->outlen++] = (unsigned char) (out->outbits & 0xFF);
	out->outbits >>= 8;
	out->noutbits -= 8;
    }
}

579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
	    outbits(out, distance - d->min, d->extrabits);
    }
}

void *zlib_compress_init(void)
{
    struct Outbuf *out;
    struct LZ77Context *ectx = smalloc(sizeof(struct LZ77Context));

    lz77_init(ectx);
    ectx->literal = zlib_literal;
    ectx->match = zlib_match;

    out = smalloc(sizeof(struct Outbuf));
    out->outbits = out->noutbits = 0;
    out->firstblock = 1;
    out->comp_disabled = FALSE;
    ectx->userdata = out;

    return ectx;
}







|





|







579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
	    outbits(out, distance - d->min, d->extrabits);
    }
}

void *zlib_compress_init(void)
{
    struct Outbuf *out;
    struct LZ77Context *ectx = snew(struct LZ77Context);

    lz77_init(ectx);
    ectx->literal = zlib_literal;
    ectx->match = zlib_match;

    out = snew(struct Outbuf);
    out->outbits = out->noutbits = 0;
    out->firstblock = 1;
    out->comp_disabled = FALSE;
    ectx->userdata = out;

    return ectx;
}
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
 * [minlength,maxlength) of the provided code/length tables, and
 * recurse to build subtables.
 */
static struct zlib_table *zlib_mkonetab(int *codes, unsigned char *lengths,
					int nsyms,
					int pfx, int pfxbits, int bits)
{
    struct zlib_table *tab = smalloc(sizeof(struct zlib_table));
    int pfxmask = (1 << pfxbits) - 1;
    int nbits, i, j, code;

    tab->table = smalloc((1 << bits) * sizeof(struct zlib_tableentry));
    tab->mask = (1 << bits) - 1;

    for (code = 0; code <= tab->mask; code++) {
	tab->table[code].code = -1;
	tab->table[code].nbits = 0;
	tab->table[code].nexttable = NULL;
    }







|



|







802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
 * [minlength,maxlength) of the provided code/length tables, and
 * recurse to build subtables.
 */
static struct zlib_table *zlib_mkonetab(int *codes, unsigned char *lengths,
					int nsyms,
					int pfx, int pfxbits, int bits)
{
    struct zlib_table *tab = snew(struct zlib_table);
    int pfxmask = (1 << pfxbits) - 1;
    int nbits, i, j, code;

    tab->table = snewn(1 << bits, struct zlib_tableentry);
    tab->mask = (1 << bits) - 1;

    for (code = 0; code <= tab->mask; code++) {
	tab->table[code].code = -1;
	tab->table[code].nbits = 0;
	tab->table[code].nexttable = NULL;
    }
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
    int winpos;
    unsigned char *outblk;
    int outlen, outsize;
};

void *zlib_decompress_init(void)
{
    struct zlib_decompress_ctx *dctx =
	smalloc(sizeof(struct zlib_decompress_ctx));
    unsigned char lengths[288];

    memset(lengths, 8, 144);
    memset(lengths + 144, 9, 256 - 144);
    memset(lengths + 256, 7, 280 - 256);
    memset(lengths + 280, 8, 288 - 280);
    dctx->staticlentable = zlib_mktable(lengths, 288);







|
<







937
938
939
940
941
942
943
944

945
946
947
948
949
950
951
    int winpos;
    unsigned char *outblk;
    int outlen, outsize;
};

void *zlib_decompress_init(void)
{
    struct zlib_decompress_ctx *dctx = snew(struct zlib_decompress_ctx);

    unsigned char lengths[288];

    memset(lengths, 8, 144);
    memset(lengths + 144, 9, 256 - 144);
    memset(lengths + 256, 7, 280 - 256);
    memset(lengths + 280, 8, 288 - 280);
    dctx->staticlentable = zlib_mktable(lengths, 288);
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012

static void zlib_emit_char(struct zlib_decompress_ctx *dctx, int c)
{
    dctx->window[dctx->winpos] = c;
    dctx->winpos = (dctx->winpos + 1) & (WINSIZE - 1);
    if (dctx->outlen >= dctx->outsize) {
	dctx->outsize = dctx->outlen + 512;
	dctx->outblk = srealloc(dctx->outblk, dctx->outsize);
    }
    dctx->outblk[dctx->outlen++] = c;
}

#define EATBITS(n) ( dctx->nbits -= (n), dctx->bits >>= (n) )

int zlib_decompress_block(void *handle, unsigned char *block, int len,







|







997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011

static void zlib_emit_char(struct zlib_decompress_ctx *dctx, int c)
{
    dctx->window[dctx->winpos] = c;
    dctx->winpos = (dctx->winpos + 1) & (WINSIZE - 1);
    if (dctx->outlen >= dctx->outsize) {
	dctx->outsize = dctx->outlen + 512;
	dctx->outblk = sresize(dctx->outblk, dctx->outsize, unsigned char);
    }
    dctx->outblk[dctx->outlen++] = c;
}

#define EATBITS(n) ( dctx->nbits -= (n), dctx->bits >>= (n) )

int zlib_decompress_block(void *handle, unsigned char *block, int len,
Changes to telnet.c.
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
	    break;
	  case SUBNEGOT:
	    if (c == IAC)
		telnet->state = SUBNEG_IAC;
	    else {
	      subneg_addchar:
		if (telnet->sb_len >= telnet->sb_size) {
		    unsigned char *newbuf;
		    telnet->sb_size += SB_DELTA;
		    newbuf = (telnet->sb_buf ?
			      srealloc(telnet->sb_buf, telnet->sb_size) :
			      smalloc(telnet->sb_size));
		    if (newbuf)
			telnet->sb_buf = newbuf;
		    else
			telnet->sb_size -= SB_DELTA;
		}
		if (telnet->sb_len < telnet->sb_size)
		    telnet->sb_buf[telnet->sb_len++] = c;
		telnet->state = SUBNEGOT;	/* in case we came here by goto */
	    }
	    break;
	  case SUBNEG_IAC:
	    if (c != SE)
		goto subneg_addchar;   /* yes, it's a hack, I know, but... */
	    else {







<

<
|
<
|
<
<
<

<
|







607
608
609
610
611
612
613

614

615

616



617

618
619
620
621
622
623
624
625
	    break;
	  case SUBNEGOT:
	    if (c == IAC)
		telnet->state = SUBNEG_IAC;
	    else {
	      subneg_addchar:
		if (telnet->sb_len >= telnet->sb_size) {

		    telnet->sb_size += SB_DELTA;

		    telnet->sb_buf = sresize(telnet->sb_buf, telnet->sb_size,

					     unsigned char);



		}

		telnet->sb_buf[telnet->sb_len++] = c;
		telnet->state = SUBNEGOT;	/* in case we came here by goto */
	    }
	    break;
	  case SUBNEG_IAC:
	    if (c != SE)
		goto subneg_addchar;   /* yes, it's a hack, I know, but... */
	    else {
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
	telnet_receive,
	telnet_sent
    };
    SockAddr addr;
    char *err;
    Telnet telnet;

    telnet = smalloc(sizeof(*telnet));
    telnet->fn = &fn_table;
    telnet->cfg = *cfg;		       /* STRUCTURE COPY */
    telnet->s = NULL;
    telnet->echoing = TRUE;
    telnet->editing = TRUE;
    telnet->activated = FALSE;
    telnet->sb_buf = NULL;







|







680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
	telnet_receive,
	telnet_sent
    };
    SockAddr addr;
    char *err;
    Telnet telnet;

    telnet = snew(struct telnet_tag);
    telnet->fn = &fn_table;
    telnet->cfg = *cfg;		       /* STRUCTURE COPY */
    telnet->s = NULL;
    telnet->echoing = TRUE;
    telnet->editing = TRUE;
    telnet->activated = FALSE;
    telnet->sb_buf = NULL;
Changes to terminal.c.
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    if (line[0] != (unsigned long)cols) {
	/*
	 * This line is the wrong length, which probably means it
	 * hasn't been accessed since a resize. Resize it now.
	 */
	oldlen = line[0];
	lineattrs = line[oldlen + 1];
	line = srealloc(line, TSIZE * (2 + cols));
	line[0] = cols;
	for (i = oldlen; i < cols; i++)
	    line[i + 1] = ERASE_CHAR;
	line[cols + 1] = lineattrs & LATTR_MODE;
    }

    return line;







|







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    if (line[0] != (unsigned long)cols) {
	/*
	 * This line is the wrong length, which probably means it
	 * hasn't been accessed since a resize. Resize it now.
	 */
	oldlen = line[0];
	lineattrs = line[oldlen + 1];
	line = sresize(line, 2 + cols, TTYPE);
	line[0] = cols;
	for (i = oldlen; i < cols; i++)
	    line[i + 1] = ERASE_CHAR;
	line[cols + 1] = lineattrs & LATTR_MODE;
    }

    return line;
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
{
    Terminal *term;

    /*
     * Allocate a new Terminal structure and initialise the fields
     * that need it.
     */
    term = smalloc(sizeof(Terminal));
    term->frontend = frontend;
    term->ucsdata = ucsdata;
    term->cfg = *mycfg;		       /* STRUCTURE COPY */
    term->logctx = NULL;
    term->compatibility_level = TM_PUTTY;
    strcpy(term->id_string, "\033[?6c");
    term->last_blink = term->last_tblink = 0;







|







368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
{
    Terminal *term;

    /*
     * Allocate a new Terminal structure and initialise the fields
     * that need it.
     */
    term = snew(Terminal);
    term->frontend = frontend;
    term->ucsdata = ucsdata;
    term->cfg = *mycfg;		       /* STRUCTURE COPY */
    term->logctx = NULL;
    term->compatibility_level = TM_PUTTY;
    strcpy(term->id_string, "\033[?6c");
    term->last_blink = term->last_tblink = 0;
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
	    line = delpos234(term->scrollback, --sblen);
	    term->tempsblines -= 1;
	    addpos234(term->screen, line, 0);
	    term->curs.y += 1;
	    term->savecurs.y += 1;
	} else {
	    /* Add a new blank line at the bottom of the screen. */
	    line = smalloc(TSIZE * (newcols + 2));
	    line[0] = newcols;
	    for (j = 0; j < newcols; j++)
		line[j + 1] = ERASE_CHAR;
            line[newcols + 1] = LATTR_NORM;
	    addpos234(term->screen, line, count234(term->screen));
	}
	term->rows += 1;







|







507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
	    line = delpos234(term->scrollback, --sblen);
	    term->tempsblines -= 1;
	    addpos234(term->screen, line, 0);
	    term->curs.y += 1;
	    term->savecurs.y += 1;
	} else {
	    /* Add a new blank line at the bottom of the screen. */
	    line = snewn(newcols + 2, TTYPE);
	    line[0] = newcols;
	    for (j = 0; j < newcols; j++)
		line[j + 1] = ERASE_CHAR;
            line[newcols + 1] = LATTR_NORM;
	    addpos234(term->screen, line, count234(term->screen));
	}
	term->rows += 1;
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
    if (sblen < term->tempsblines)
	term->tempsblines = sblen;
    assert(count234(term->scrollback) <= newsavelines);
    assert(count234(term->scrollback) >= term->tempsblines);
    term->disptop = 0;

    /* Make a new displayed text buffer. */
    newdisp = smalloc(newrows * (newcols + 1) * TSIZE);
    for (i = 0; i < newrows * (newcols + 1); i++)
	newdisp[i] = ATTR_INVALID;
    sfree(term->disptext);
    term->disptext = newdisp;
    term->dispcurs = NULL;

    /* Make a new alternate screen. */
    newalt = newtree234(NULL);
    for (i = 0; i < newrows; i++) {
	line = smalloc(TSIZE * (newcols + 2));
	line[0] = newcols;
	for (j = 0; j < newcols; j++)
	    line[j + 1] = term->erase_char;
        line[newcols + 1] = LATTR_NORM;
	addpos234(newalt, line, i);
    }
    if (term->alt_screen) {
	while (NULL != (line = delpos234(term->alt_screen, 0)))
	    sfree(line);
	freetree234(term->alt_screen);
    }
    term->alt_screen = newalt;
    term->alt_sblines = 0;

    term->tabs = srealloc(term->tabs, newcols * sizeof(*term->tabs));
    {
	int i;
	for (i = (term->cols > 0 ? term->cols : 0); i < newcols; i++)
	    term->tabs[i] = (i % 8 == 0 ? TRUE : FALSE);
    }

    /* Check that the cursor positions are still valid. */







|









|














|







547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
    if (sblen < term->tempsblines)
	term->tempsblines = sblen;
    assert(count234(term->scrollback) <= newsavelines);
    assert(count234(term->scrollback) >= term->tempsblines);
    term->disptop = 0;

    /* Make a new displayed text buffer. */
    newdisp = snewn(newrows * (newcols + 1), TTYPE);
    for (i = 0; i < newrows * (newcols + 1); i++)
	newdisp[i] = ATTR_INVALID;
    sfree(term->disptext);
    term->disptext = newdisp;
    term->dispcurs = NULL;

    /* Make a new alternate screen. */
    newalt = newtree234(NULL);
    for (i = 0; i < newrows; i++) {
	line = snewn(newcols + 2, TTYPE);
	line[0] = newcols;
	for (j = 0; j < newcols; j++)
	    line[j + 1] = term->erase_char;
        line[newcols + 1] = LATTR_NORM;
	addpos234(newalt, line, i);
    }
    if (term->alt_screen) {
	while (NULL != (line = delpos234(term->alt_screen, 0)))
	    sfree(line);
	freetree234(term->alt_screen);
    }
    term->alt_screen = newalt;
    term->alt_sblines = 0;

    term->tabs = sresize(term->tabs, newcols, unsigned char);
    {
	int i;
	for (i = (term->cols > 0 ? term->cols : 0); i < newcols; i++)
	    term->tabs[i] = (i % 8 == 0 ? TRUE : FALSE);
    }

    /* Check that the cursor positions are still valid. */
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
		 * remove a line from the top of the scrollback to
		 * replace it, or allocate a new one if the
		 * scrollback isn't full.
		 */
		if (sblen == term->savelines) {
		    sblen--, line2 = delpos234(term->scrollback, 0);
		} else {
		    line2 = smalloc(TSIZE * (term->cols + 2));
		    line2[0] = term->cols;
		    term->tempsblines += 1;
		}
		addpos234(term->scrollback, line, sblen);
		line = line2;

		/*







|







793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
		 * remove a line from the top of the scrollback to
		 * replace it, or allocate a new one if the
		 * scrollback isn't full.
		 */
		if (sblen == term->savelines) {
		    sblen--, line2 = delpos234(term->scrollback, 0);
		} else {
		    line2 = snewn(term->cols + 2, TTYPE);
		    line2[0] = term->cols;
		    term->tempsblines += 1;
		}
		addpos234(term->scrollback, line, sblen);
		line = line2;

		/*
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
{
    struct scrollregion *newscroll;
    if (term->scrolltail &&
	term->scrolltail->topline == topline && 
	term->scrolltail->botline == botline) {
	term->scrolltail->lines += lines;
    } else {
	newscroll = smalloc(sizeof(struct scrollregion));
	newscroll->topline = topline;
	newscroll->botline = botline;
	newscroll->lines = lines;
	newscroll->next = NULL;

	if (!term->scrollhead)
	    term->scrollhead = newscroll;







|







885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
{
    struct scrollregion *newscroll;
    if (term->scrolltail &&
	term->scrolltail->topline == topline && 
	term->scrolltail->botline == botline) {
	term->scrolltail->lines += lines;
    } else {
	newscroll = snew(struct scrollregion);
	newscroll->topline = topline;
	newscroll->botline = botline;
	newscroll->lines = lines;
	newscroll->next = NULL;

	if (!term->scrollhead)
	    term->scrollhead = newscroll;
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
		{
		    struct beeptime *newbeep;
		    unsigned long ticks;

		    ticks = GETTICKCOUNT();

		    if (!term->beep_overloaded) {
			newbeep = smalloc(sizeof(struct beeptime));
			newbeep->ticks = ticks;
			newbeep->next = NULL;
			if (!term->beephead)
			    term->beephead = newbeep;
			else
			    term->beeptail->next = newbeep;
			term->beeptail = newbeep;







|







1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
		{
		    struct beeptime *newbeep;
		    unsigned long ticks;

		    ticks = GETTICKCOUNT();

		    if (!term->beep_overloaded) {
			newbeep = snew(struct beeptime);
			newbeep->ticks = ticks;
			newbeep->next = NULL;
			if (!term->beephead)
			    term->beephead = newbeep;
			else
			    term->beeptail->next = newbeep;
			term->beeptail = newbeep;
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
    wchar_t *workbuf;
    wchar_t *wbptr;		       /* where next char goes within workbuf */
    int old_top_x;
    int wblen = 0;		       /* workbuf len */
    int buflen;			       /* amount of memory allocated to workbuf */

    buflen = 5120;		       /* Default size */
    workbuf = smalloc(buflen * sizeof(wchar_t));
    wbptr = workbuf;		       /* start filling here */
    old_top_x = top.x;		       /* needed for rect==1 */

    while (poslt(top, bottom)) {
	int nl = FALSE;
	unsigned long *ldata = lineptr(top.y);
	pos nlpos;







|







3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
    wchar_t *workbuf;
    wchar_t *wbptr;		       /* where next char goes within workbuf */
    int old_top_x;
    int wblen = 0;		       /* workbuf len */
    int buflen;			       /* amount of memory allocated to workbuf */

    buflen = 5120;		       /* Default size */
    workbuf = snewn(buflen, wchar_t);
    wbptr = workbuf;		       /* start filling here */
    old_top_x = top.x;		       /* needed for rect==1 */

    while (poslt(top, bottom)) {
	int nl = FALSE;
	unsigned long *ldata = lineptr(top.y);
	pos nlpos;
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
		}
	    }
#endif

	    for (p = cbuf; *p; p++) {
		/* Enough overhead for trailing NL and nul */
		if (wblen >= buflen - 16) {
		    workbuf =
			srealloc(workbuf,
				 sizeof(wchar_t) * (buflen += 100));
		    wbptr = workbuf + wblen;
		}
		wblen++;
		*wbptr++ = *p;
	    }
	    top.x++;
	}







|
|
<







3675
3676
3677
3678
3679
3680
3681
3682
3683

3684
3685
3686
3687
3688
3689
3690
		}
	    }
#endif

	    for (p = cbuf; *p; p++) {
		/* Enough overhead for trailing NL and nul */
		if (wblen >= buflen - 16) {
		    buflen += 100;
		    workbuf = sresize(workbuf, buflen, wchar_t);

		    wbptr = workbuf + wblen;
		}
		wblen++;
		*wbptr++ = *p;
	    }
	    top.x++;
	}
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
        wchar_t *p, *q;

	term_seen_key_event(term);     /* pasted data counts */

        if (term->paste_buffer)
            sfree(term->paste_buffer);
        term->paste_pos = term->paste_hold = term->paste_len = 0;
        term->paste_buffer = smalloc(len * sizeof(wchar_t));

        p = q = data;
        while (p < data + len) {
            while (p < data + len &&
                   !(p <= data + len - sel_nl_sz &&
                     !memcmp(p, sel_nl, sizeof(sel_nl))))
                p++;







|







3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
        wchar_t *p, *q;

	term_seen_key_event(term);     /* pasted data counts */

        if (term->paste_buffer)
            sfree(term->paste_buffer);
        term->paste_pos = term->paste_hold = term->paste_len = 0;
        term->paste_buffer = snewn(len, wchar_t);

        p = q = data;
        while (p < data + len) {
            while (p < data + len &&
                   !(p <= data + len - sel_nl_sz &&
                     !memcmp(p, sel_nl, sizeof(sel_nl))))
                p++;
Changes to terminal.h.
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
#define VBELL_TIMEOUT (TICKSPERSEC/10) /* visual bell lasts 1/10 sec */

    struct beeptime *beephead, *beeptail;
    int nbeeps;
    int beep_overloaded;
    long lastbeep;


#define TSIZE (sizeof(unsigned long))
#define fix_cpos do { \
    term->cpos = lineptr(term->curs.y) + term->curs.x; \
} while(0)

#ifdef OPTIMISE_SCROLL
    struct scrollregion *scrollhead, *scrolltail;
#endif /* OPTIMISE_SCROLL */







>
|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#define VBELL_TIMEOUT (TICKSPERSEC/10) /* visual bell lasts 1/10 sec */

    struct beeptime *beephead, *beeptail;
    int nbeeps;
    int beep_overloaded;
    long lastbeep;

#define TTYPE unsigned long
#define TSIZE (sizeof(TTYPE))
#define fix_cpos do { \
    term->cpos = lineptr(term->curs.y) + term->curs.x; \
} while(0)

#ifdef OPTIMISE_SCROLL
    struct scrollregion *scrollhead, *scrolltail;
#endif /* OPTIMISE_SCROLL */
Changes to testback.c.
1
2
3
4
5
6
7
8
/* $Id: testback.c 2615 2003-01-15 23:30:21Z ben $ */
/*
 * Copyright (c) 1999 Simon Tatham
 * Copyright (c) 1999 Ben Harris
 * All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
|







1
2
3
4
5
6
7
8
/* $Id: testback.c 3014 2003-03-29 16:14:26Z simon $ */
/*
 * Copyright (c) 1999 Simon Tatham
 * Copyright (c) 1999 Ben Harris
 * All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

    return NULL;
}

static char *loop_init(void *frontend_handle, void **backend_handle,
		       Config *cfg, char *host, int port, char **realhost,
		       int nodelay) {
    struct loop_state *st = smalloc(sizeof(*st));

    st->term = frontend_handle;
    *backend_handle = st;
    return NULL;
}

static void null_free(void *handle)







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

    return NULL;
}

static char *loop_init(void *frontend_handle, void **backend_handle,
		       Config *cfg, char *host, int port, char **realhost,
		       int nodelay) {
    struct loop_state *st = snew(struct loop_state);

    st->term = frontend_handle;
    *backend_handle = st;
    return NULL;
}

static void null_free(void *handle)
Changes to tree234.c.
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40
41
42
43
44
45
 * SOFTWARE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>


#include "tree234.h"

#define smalloc malloc
#define sfree free

#define mknew(typ) ( (typ *) smalloc (sizeof (typ)) )

#ifdef TEST
#define LOG(x) (printf x)
#else
#define LOG(x)
#endif

typedef struct node234_Tag node234;







>


<
<
<
<
<







25
26
27
28
29
30
31
32
33
34





35
36
37
38
39
40
41
 * SOFTWARE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "puttymem.h"
#include "tree234.h"






#ifdef TEST
#define LOG(x) (printf x)
#else
#define LOG(x)
#endif

typedef struct node234_Tag node234;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
};

/*
 * Create a 2-3-4 tree.
 */
tree234 *newtree234(cmpfn234 cmp)
{
    tree234 *ret = mknew(tree234);
    LOG(("created tree %p\n", ret));
    ret->root = NULL;
    ret->cmp = cmp;
    return ret;
}

/*







|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
};

/*
 * Create a 2-3-4 tree.
 */
tree234 *newtree234(cmpfn234 cmp)
{
    tree234 *ret = snew(tree234);
    LOG(("created tree %p\n", ret));
    ret->root = NULL;
    ret->cmp = cmp;
    return ret;
}

/*
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
{
    node234 *n, **np, *left, *right;
    void *orig_e = e;
    int c, lcount, rcount;

    LOG(("adding node %p to tree %p\n", e, t));
    if (t->root == NULL) {
	t->root = mknew(node234);
	t->root->elems[1] = t->root->elems[2] = NULL;
	t->root->kids[0] = t->root->kids[1] = NULL;
	t->root->kids[2] = t->root->kids[3] = NULL;
	t->root->counts[0] = t->root->counts[1] = 0;
	t->root->counts[2] = t->root->counts[3] = 0;
	t->root->parent = NULL;
	t->root->elems[0] = e;







|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
{
    node234 *n, **np, *left, *right;
    void *orig_e = e;
    int c, lcount, rcount;

    LOG(("adding node %p to tree %p\n", e, t));
    if (t->root == NULL) {
	t->root = snew(node234);
	t->root->elems[1] = t->root->elems[2] = NULL;
	t->root->kids[0] = t->root->kids[1] = NULL;
	t->root->kids[2] = t->root->kids[3] = NULL;
	t->root->counts[0] = t->root->counts[1] = 0;
	t->root->counts[2] = t->root->counts[3] = 0;
	t->root->parent = NULL;
	t->root->elems[0] = e;
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
	    if (n->kids[2])
		n->kids[2]->parent = n;
	    if (n->kids[3])
		n->kids[3]->parent = n;
	    LOG(("  done\n"));
	    break;
	} else {
	    node234 *m = mknew(node234);
	    m->parent = n->parent;
	    LOG(("  splitting a 4-node; created new node %p\n", m));
	    /*
	     * Insert in a 4-node; split into a 2-node and a
	     * 3-node, and move focus up a level.
	     * 
	     * I don't think it matters which way round we put the







|







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
	    if (n->kids[2])
		n->kids[2]->parent = n;
	    if (n->kids[3])
		n->kids[3]->parent = n;
	    LOG(("  done\n"));
	    break;
	} else {
	    node234 *m = snew(node234);
	    m->parent = n->parent;
	    LOG(("  splitting a 4-node; created new node %p\n", m));
	    /*
	     * Insert in a 4-node; split into a 2-node and a
	     * 3-node, and move focus up a level.
	     * 
	     * I don't think it matters which way round we put the
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
			n->parent->kids[1] == n ? 1 :
			n->parent->kids[2] == n ? 2 : 3);
	    n->parent->counts[childnum] = count;
	    n = n->parent;
	}
    } else {
	LOG(("  root is overloaded, split into two\n"));
	t->root = mknew(node234);
	t->root->kids[0] = left;
	t->root->counts[0] = lcount;
	t->root->elems[0] = e;
	t->root->kids[1] = right;
	t->root->counts[1] = rcount;
	t->root->elems[1] = NULL;
	t->root->kids[2] = NULL;







|







415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
			n->parent->kids[1] == n ? 1 :
			n->parent->kids[2] == n ? 2 : 3);
	    n->parent->counts[childnum] = count;
	    n = n->parent;
	}
    } else {
	LOG(("  root is overloaded, split into two\n"));
	t->root = snew(node234);
	t->root->kids[0] = left;
	t->root->counts[0] = lcount;
	t->root->elems[0] = e;
	t->root->kids[1] = right;
	t->root->counts[1] = rcount;
	t->root->elems[1] = NULL;
	t->root->kids[2] = NULL;
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
 * definition correctly ordered. It also ensures all nodes are
 * distinct, because the enum functions would get caught in a loop
 * if not.)
 */

#include <stdarg.h>

#define srealloc realloc

/*
 * Error reporting function.
 */
void error(char *fmt, ...)
{
    va_list ap;
    printf("ERROR: ");







<
<







1004
1005
1006
1007
1008
1009
1010


1011
1012
1013
1014
1015
1016
1017
 * definition correctly ordered. It also ensures all nodes are
 * distinct, because the enum functions would get caught in a loop
 * if not.)
 */

#include <stdarg.h>



/*
 * Error reporting function.
 */
void error(char *fmt, ...)
{
    va_list ap;
    printf("ERROR: ");
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
void internal_addtest(void *elem, int index, void *realret)
{
    int i, j;
    void *retval;

    if (arraysize < arraylen + 1) {
	arraysize = arraylen + 1 + 256;
	array = (array == NULL ? smalloc(arraysize * sizeof(*array)) :
		 srealloc(array, arraysize * sizeof(*array)));
    }

    i = index;
    /* now i points to the first element >= elem */
    retval = elem;		       /* expect elem returned (success) */
    for (j = arraylen; j > i; j--)
	array[j] = array[j - 1];







<
|







1191
1192
1193
1194
1195
1196
1197

1198
1199
1200
1201
1202
1203
1204
1205
void internal_addtest(void *elem, int index, void *realret)
{
    int i, j;
    void *retval;

    if (arraysize < arraylen + 1) {
	arraysize = arraylen + 1 + 256;

	array = sresize(array, arraysize, void *);
    }

    i = index;
    /* now i points to the first element >= elem */
    retval = elem;		       /* expect elem returned (success) */
    for (j = arraylen; j > i; j--)
	array[j] = array[j - 1];
Changes to unicode.c.
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
    if (!used_dtf) {
	for (i = 0; i < 256; i++) {
	    if (DIRECT_CHAR(ucsdata->unitab_line[i]))
		continue;
	    if (DIRECT_FONT(ucsdata->unitab_line[i]))
		continue;
	    if (!ucsdata->uni_tbl) {
		ucsdata->uni_tbl = smalloc(256 * sizeof(char *));
		memset(ucsdata->uni_tbl, 0, 256 * sizeof(char *));
	    }
	    j = ((ucsdata->unitab_line[i] >> 8) & 0xFF);
	    if (!ucsdata->uni_tbl[j]) {
		ucsdata->uni_tbl[j] = smalloc(256 * sizeof(char));
		memset(ucsdata->uni_tbl[j], 0, 256 * sizeof(char));
	    }
	    ucsdata->uni_tbl[j][ucsdata->unitab_line[i] & 0xFF] = i;
	}
    }

    /* Find the line control characters. */







|




|







512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
    if (!used_dtf) {
	for (i = 0; i < 256; i++) {
	    if (DIRECT_CHAR(ucsdata->unitab_line[i]))
		continue;
	    if (DIRECT_FONT(ucsdata->unitab_line[i]))
		continue;
	    if (!ucsdata->uni_tbl) {
		ucsdata->uni_tbl = snewn(256, char *);
		memset(ucsdata->uni_tbl, 0, 256 * sizeof(char *));
	    }
	    j = ((ucsdata->unitab_line[i] >> 8) & 0xFF);
	    if (!ucsdata->uni_tbl[j]) {
		ucsdata->uni_tbl[j] = snewn(256, char);
		memset(ucsdata->uni_tbl[j], 0, 256 * sizeof(char));
	    }
	    ucsdata->uni_tbl[j][ucsdata->unitab_line[i] & 0xFF] = i;
	}
    }

    /* Find the line control characters. */
Changes to unix/gtkdlg.c.
203
204
205
206
207
208
209




210
211
212
213
214
215
216
    uc->privdata_needs_free = FALSE;
}

void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size)
{
    struct dlgparam *dp = (struct dlgparam *)dlg;
    struct uctrl *uc = dlg_find_byctrl(dp, ctrl);




    uc->privdata = smalloc(size);
    uc->privdata_needs_free = FALSE;
    return uc->privdata;
}

union control *dlg_last_focused(union control *ctrl, void *dlg)
{







>
>
>
>







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
    uc->privdata_needs_free = FALSE;
}

void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size)
{
    struct dlgparam *dp = (struct dlgparam *)dlg;
    struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
    /*
     * This is an internal allocation routine, so it's allowed to
     * use smalloc directly.
     */
    uc->privdata = smalloc(size);
    uc->privdata_needs_free = FALSE;
    return uc->privdata;
}

union control *dlg_last_focused(union control *ctrl, void *dlg)
{
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
	ncols = 1;
	for (i = 0; text[i]; i++)
	    if (text[i] == '\t')
		ncols++;

	assert(ncols <=
	       (uc->ctrl->listbox.ncols ? uc->ctrl->listbox.ncols : 1));
	percents = smalloc(ncols * sizeof(gint));
	percents[ncols-1] = 100;
	for (i = 0; i < ncols-1; i++) {
	    percents[i] = uc->ctrl->listbox.percentages[i];
	    percents[ncols-1] -= percents[i];
	}
	columns_set_cols(COLUMNS(cols), ncols, percents);
	sfree(percents);







|







379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
	ncols = 1;
	for (i = 0; text[i]; i++)
	    if (text[i] == '\t')
		ncols++;

	assert(ncols <=
	       (uc->ctrl->listbox.ncols ? uc->ctrl->listbox.ncols : 1));
	percents = snewn(ncols, gint);
	percents[ncols-1] = 100;
	for (i = 0; i < ncols-1; i++) {
	    percents[i] = uc->ctrl->listbox.percentages[i];
	    percents[ncols-1] -= percents[i];
	}
	columns_set_cols(COLUMNS(cols), ncols, percents);
	sfree(percents);
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
		struct uctrl *uc = dlg_find_byctrl(dp, ctrl->tabdelay.ctrl);
		if (uc)
		    columns_taborder_last(cols, uc->toplevel);
	    }
            continue;                  /* no actual control created */
	}

	uc = smalloc(sizeof(struct uctrl));
	uc->ctrl = ctrl;
	uc->privdata = NULL;
	uc->privdata_needs_free = FALSE;
	uc->buttons = NULL;
	uc->entry = uc->list = uc->menu = NULL;
	uc->button = uc->optmenu = uc->text = NULL;








|







1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
		struct uctrl *uc = dlg_find_byctrl(dp, ctrl->tabdelay.ctrl);
		if (uc)
		    columns_taborder_last(cols, uc->toplevel);
	    }
            continue;                  /* no actual control created */
	}

	uc = snew(struct uctrl);
	uc->ctrl = ctrl;
	uc->privdata = NULL;
	uc->privdata_needs_free = FALSE;
	uc->buttons = NULL;
	uc->entry = uc->list = uc->menu = NULL;
	uc->button = uc->optmenu = uc->text = NULL;

1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
                }
                columns_set_cols(COLUMNS(w), ctrl->radio.ncolumns,
                                 percentages);
                g_free(percentages);
                group = NULL;

		uc->nbuttons = ctrl->radio.nbuttons;
		uc->buttons = smalloc(uc->nbuttons * sizeof(GtkWidget *));

                for (i = 0; i < ctrl->radio.nbuttons; i++) {
                    GtkWidget *b;
                    gint colstart;

                    b = (gtk_radio_button_new_with_label
                         (group, ctrl->radio.buttons[i]));







|







1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
                }
                columns_set_cols(COLUMNS(w), ctrl->radio.ncolumns,
                                 percentages);
                g_free(percentages);
                group = NULL;

		uc->nbuttons = ctrl->radio.nbuttons;
		uc->buttons = snewn(uc->nbuttons, GtkWidget *);

                for (i = 0; i < ctrl->radio.nbuttons; i++) {
                    GtkWidget *b;
                    gint colstart;

                    b = (gtk_radio_button_new_with_label
                         (group, ctrl->radio.buttons[i]));
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
		if (first) {
		    panels_switch_to(PANELS(panels), panelvbox);
		    gtk_tree_select_child(GTK_TREE(tree), treeitem);
		}

		if (nselparams >= selparamsize) {
		    selparamsize += 16;
		    selparams = srealloc(selparams,
					 selparamsize * sizeof(*selparams));
		}
		selparams[nselparams].dp = &dp;
		selparams[nselparams].panels = PANELS(panels);
		selparams[nselparams].panel = panelvbox;
		selparams[nselparams].shortcuts = scs;   /* structure copy */
		selparams[nselparams].treeitem = treeitem;
		nselparams++;

	    }

	    w = layout_ctrls(&dp,
			     &selparams[nselparams-1].shortcuts,
			     s, listitemheight, NULL);
	    gtk_box_pack_start(GTK_BOX(panelvbox), w, FALSE, FALSE, 0);
            gtk_widget_show(w);
	}
    }

    dp.ntreeitems = nselparams;
    dp.treeitems = smalloc(dp.ntreeitems * sizeof(GtkWidget *));

    for (index = 0; index < nselparams; index++) {
	gtk_signal_connect(GTK_OBJECT(selparams[index].treeitem), "select",
			   GTK_SIGNAL_FUNC(treeitem_sel),
			   &selparams[index]);
        dp.treeitems[index] = selparams[index].treeitem;
    }







|
|



















|







2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
		if (first) {
		    panels_switch_to(PANELS(panels), panelvbox);
		    gtk_tree_select_child(GTK_TREE(tree), treeitem);
		}

		if (nselparams >= selparamsize) {
		    selparamsize += 16;
		    selparams = sresize(selparams, selparamsize,
					struct selparam);
		}
		selparams[nselparams].dp = &dp;
		selparams[nselparams].panels = PANELS(panels);
		selparams[nselparams].panel = panelvbox;
		selparams[nselparams].shortcuts = scs;   /* structure copy */
		selparams[nselparams].treeitem = treeitem;
		nselparams++;

	    }

	    w = layout_ctrls(&dp,
			     &selparams[nselparams-1].shortcuts,
			     s, listitemheight, NULL);
	    gtk_box_pack_start(GTK_BOX(panelvbox), w, FALSE, FALSE, 0);
            gtk_widget_show(w);
	}
    }

    dp.ntreeitems = nselparams;
    dp.treeitems = snewn(dp.ntreeitems, GtkWidget *);

    for (index = 0; index < nselparams; index++) {
	gtk_signal_connect(GTK_OBJECT(selparams[index].treeitem), "select",
			   GTK_SIGNAL_FUNC(treeitem_sel),
			   &selparams[index]);
        dp.treeitems[index] = selparams[index].treeitem;
    }
Changes to unix/pterm.c.
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
     * Set up UTF-8 paste data. This only happens if we aren't in
     * direct-to-font mode using the D800 hack.
     */
    if (!inst->direct_to_font) {
	wchar_t *tmp = data;
	int tmplen = len;

	inst->pasteout_data_utf8 = smalloc(len*6);
	inst->pasteout_data_utf8_len = len*6;
	inst->pasteout_data_utf8_len =
	    charset_from_unicode(&tmp, &tmplen, inst->pasteout_data_utf8,
				 inst->pasteout_data_utf8_len,
				 CS_UTF8, NULL, NULL, 0);
	if (inst->pasteout_data_utf8_len == 0) {
	    sfree(inst->pasteout_data_utf8);
	    inst->pasteout_data_utf8 = NULL;
	} else {
	    inst->pasteout_data_utf8 =
		srealloc(inst->pasteout_data_utf8,
			 inst->pasteout_data_utf8_len);
	}
    } else {
	inst->pasteout_data_utf8 = NULL;
	inst->pasteout_data_utf8_len = 0;
    }

    inst->pasteout_data = smalloc(len*6);
    inst->pasteout_data_len = len*6;
    inst->pasteout_data_len = wc_to_mb(inst->ucsdata.line_codepage, 0,
				       data, len, inst->pasteout_data,
				       inst->pasteout_data_len,
				       NULL, NULL, NULL);
    if (inst->pasteout_data_len == 0) {
	sfree(inst->pasteout_data);
	inst->pasteout_data = NULL;
    } else {
	inst->pasteout_data =
	    srealloc(inst->pasteout_data, inst->pasteout_data_len);
    }

    if (gtk_selection_owner_set(inst->area, GDK_SELECTION_PRIMARY,
				GDK_CURRENT_TIME)) {
	gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
				 GDK_SELECTION_TYPE_STRING, 1);
	gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,







|










|
|






|










|







1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
     * Set up UTF-8 paste data. This only happens if we aren't in
     * direct-to-font mode using the D800 hack.
     */
    if (!inst->direct_to_font) {
	wchar_t *tmp = data;
	int tmplen = len;

	inst->pasteout_data_utf8 = snewn(len*6, char);
	inst->pasteout_data_utf8_len = len*6;
	inst->pasteout_data_utf8_len =
	    charset_from_unicode(&tmp, &tmplen, inst->pasteout_data_utf8,
				 inst->pasteout_data_utf8_len,
				 CS_UTF8, NULL, NULL, 0);
	if (inst->pasteout_data_utf8_len == 0) {
	    sfree(inst->pasteout_data_utf8);
	    inst->pasteout_data_utf8 = NULL;
	} else {
	    inst->pasteout_data_utf8 =
		sresize(inst->pasteout_data_utf8,
			inst->pasteout_data_utf8_len, char);
	}
    } else {
	inst->pasteout_data_utf8 = NULL;
	inst->pasteout_data_utf8_len = 0;
    }

    inst->pasteout_data = snewn(len*6, char);
    inst->pasteout_data_len = len*6;
    inst->pasteout_data_len = wc_to_mb(inst->ucsdata.line_codepage, 0,
				       data, len, inst->pasteout_data,
				       inst->pasteout_data_len,
				       NULL, NULL, NULL);
    if (inst->pasteout_data_len == 0) {
	sfree(inst->pasteout_data);
	inst->pasteout_data = NULL;
    } else {
	inst->pasteout_data =
	    sresize(inst->pasteout_data, inst->pasteout_data_len, char);
    }

    if (gtk_selection_owner_set(inst->area, GDK_SELECTION_PRIMARY,
				GDK_CURRENT_TIME)) {
	gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
				 GDK_SELECTION_TYPE_STRING, 1);
	gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
	(seldata->type != GDK_SELECTION_TYPE_STRING &&
	 seldata->type != inst->utf8_string_atom))
	return;			       /* Nothing happens. */

    if (inst->pastein_data)
	sfree(inst->pastein_data);

    inst->pastein_data = smalloc(seldata->length * sizeof(wchar_t));
    inst->pastein_data_len = seldata->length;
    inst->pastein_data_len =
	mb_to_wc((seldata->type == inst->utf8_string_atom ?
		  CS_UTF8 : inst->ucsdata.line_codepage),
		 0, seldata->data, seldata->length,
		 inst->pastein_data, inst->pastein_data_len);








|







1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
	(seldata->type != GDK_SELECTION_TYPE_STRING &&
	 seldata->type != inst->utf8_string_atom))
	return;			       /* Nothing happens. */

    if (inst->pastein_data)
	sfree(inst->pastein_data);

    inst->pastein_data = snewn(seldata->length, wchar_t);
    inst->pastein_data_len = seldata->length;
    inst->pastein_data_len =
	mb_to_wc((seldata->type == inst->utf8_string_atom ?
		  CS_UTF8 : inst->ucsdata.line_codepage),
		 0, seldata->data, seldata->length,
		 inst->pastein_data, inst->pastein_data_len);

1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
{
    struct gui_data *inst = (struct gui_data *)frontend;
    struct draw_ctx *dctx;

    if (!inst->area->window)
	return NULL;

    dctx = smalloc(sizeof(*dctx));
    dctx->inst = inst;
    dctx->gc = gdk_gc_new(inst->area->window);
    return dctx;
}

void free_ctx(Context ctx)
{







|







1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
{
    struct gui_data *inst = (struct gui_data *)frontend;
    struct draw_ctx *dctx;

    if (!inst->area->window)
	return NULL;

    dctx = snew(struct draw_ctx);
    dctx->inst = inst;
    dctx->gc = gdk_gc_new(inst->area->window);
    return dctx;
}

void free_ctx(Context ctx)
{
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
    gdk_gc_set_foreground(gc, &inst->cols[nfg]);
    {
	GdkWChar *gwcs;
	gchar *gcs;
	wchar_t *wcs;
	int i;

	wcs = smalloc(sizeof(wchar_t) * (len+1));
	for (i = 0; i < len; i++) {
	    wcs[i] = (wchar_t) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));
	}

	if (inst->fonts[fontid] == NULL) {
	    /*
	     * The font for this contingency does not exist.







|







1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
    gdk_gc_set_foreground(gc, &inst->cols[nfg]);
    {
	GdkWChar *gwcs;
	gchar *gcs;
	wchar_t *wcs;
	int i;

	wcs = snewn(len+1, wchar_t);
	for (i = 0; i < len; i++) {
	    wcs[i] = (wchar_t) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));
	}

	if (inst->fonts[fontid] == NULL) {
	    /*
	     * The font for this contingency does not exist.
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
	     * takes the doubled length seriously, then (a) the
	     * array will stand scrutiny up to the full length, (b)
	     * the spare elements of the array are full of zeroes
	     * which will probably be an empty glyph in the font,
	     * and (c) the clip rectangle should prevent it causing
	     * trouble anyway.
	     */
	    gwcs = smalloc(sizeof(GdkWChar) * (len*2+1));
	    memset(gwcs, 0, sizeof(GdkWChar) * (len*2+1));
	    /*
	     * FIXME: when we have a wide-char equivalent of
	     * from_unicode, use it instead of this.
	     */
	    for (i = 0; i <= len; i++)
		gwcs[i] = wcs[i];
	    gdk_draw_text_wc(inst->pixmap, inst->fonts[fontid], gc,
			     x*inst->font_width+inst->cfg.window_border,
			     y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
			     gwcs, len*2);
	    sfree(gwcs);
	} else {
	    gcs = smalloc(sizeof(GdkWChar) * (len+1));
	    wc_to_mb(inst->fontinfo[fontid].charset, 0,
		     wcs, len, gcs, len, ".", NULL, NULL);
	    gdk_draw_text(inst->pixmap, inst->fonts[fontid], gc,
			  x*inst->font_width+inst->cfg.window_border,
			  y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
			  gcs, len);
	    sfree(gcs);







|













|







1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
	     * takes the doubled length seriously, then (a) the
	     * array will stand scrutiny up to the full length, (b)
	     * the spare elements of the array are full of zeroes
	     * which will probably be an empty glyph in the font,
	     * and (c) the clip rectangle should prevent it causing
	     * trouble anyway.
	     */
	    gwcs = snewn(len*2+1, GdkWChar);
	    memset(gwcs, 0, sizeof(GdkWChar) * (len*2+1));
	    /*
	     * FIXME: when we have a wide-char equivalent of
	     * from_unicode, use it instead of this.
	     */
	    for (i = 0; i <= len; i++)
		gwcs[i] = wcs[i];
	    gdk_draw_text_wc(inst->pixmap, inst->fonts[fontid], gc,
			     x*inst->font_width+inst->cfg.window_border,
			     y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
			     gwcs, len*2);
	    sfree(gwcs);
	} else {
	    gcs = snewn(len+1, gchar);
	    wc_to_mb(inst->fontinfo[fontid].charset, 0,
		     wcs, len, gcs, len, ".", NULL, NULL);
	    gdk_draw_text(inst->pixmap, inst->fonts[fontid], gc,
			  x*inst->font_width+inst->cfg.window_border,
			  y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
			  gcs, len);
	    sfree(gcs);
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
	} else if (!strcmp(p, "-e")) {
	    /* This option swallows all further arguments. */
	    if (!do_everything)
		break;

	    if (--argc > 0) {
		int i;
		pty_argv = smalloc((argc+1) * sizeof(char *));
		++argv;
		for (i = 0; i < argc; i++)
		    pty_argv[i] = argv[i];
		pty_argv[argc] = NULL;
		break;		       /* finished command-line processing */
	    } else
		err = 1, fprintf(stderr, "pterm: -e expects an argument\n");







|







2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
	} else if (!strcmp(p, "-e")) {
	    /* This option swallows all further arguments. */
	    if (!do_everything)
		break;

	    if (--argc > 0) {
		int i;
		pty_argv = snewn(argc+1, char *);
		++argv;
		for (i = 0; i < argc; i++)
		    pty_argv[i] = argv[i];
		pty_argv[argc] = NULL;
		break;		       /* finished command-line processing */
	    } else
		err = 1, fprintf(stderr, "pterm: -e expects an argument\n");
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
    pty_pre_init();

    gtk_init(&argc, &argv);

    /*
     * Create an instance structure and initialise to zeroes
     */
    inst = smalloc(sizeof(*inst));
    memset(inst, 0, sizeof(*inst));
    inst->alt_keycode = -1;            /* this one needs _not_ to be zero */

    if (do_cmdline(argc, argv, 0, &inst->cfg))
	exit(1);		       /* pre-defaults pass to get -class */
    do_defaults(NULL, &inst->cfg);
    if (do_cmdline(argc, argv, 1, &inst->cfg))







|







2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
    pty_pre_init();

    gtk_init(&argc, &argv);

    /*
     * Create an instance structure and initialise to zeroes
     */
    inst = snew(struct gui_data);
    memset(inst, 0, sizeof(*inst));
    inst->alt_keycode = -1;            /* this one needs _not_ to be zero */

    if (do_cmdline(argc, argv, 0, &inst->cfg))
	exit(1);		       /* pre-defaults pass to get -class */
    do_defaults(NULL, &inst->cfg);
    if (do_cmdline(argc, argv, 1, &inst->cfg))
Changes to unix/pty.c.
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
	if (pty_argv)
	    execvp(pty_argv[0], pty_argv);
	else {
	    char *shell = getenv("SHELL");
	    char *shellname;
	    if (cfg->login_shell) {
		char *p = strrchr(shell, '/');
		shellname = smalloc(2+strlen(shell));
		p = p ? p+1 : shell;
		sprintf(shellname, "-%s", p);
	    } else
		shellname = shell;
	    execl(getenv("SHELL"), shellname, NULL);
	}








|







494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
	if (pty_argv)
	    execvp(pty_argv[0], pty_argv);
	else {
	    char *shell = getenv("SHELL");
	    char *shellname;
	    if (cfg->login_shell) {
		char *p = strrchr(shell, '/');
		shellname = snewn(2+strlen(shell), char);
		p = p ? p+1 : shell;
		sprintf(shellname, "-%s", p);
	    } else
		shellname = shell;
	    execl(getenv("SHELL"), shellname, NULL);
	}

Changes to unix/ux_x11.c.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
	command = dupprintf("xauth list %s 2>/dev/null", display);
    fp = popen(command, "r");
    sfree(command);

    if (!fp)
        return;                        /* assume no auth */

    localbuf = smalloc(maxsize);

    while (1) {
        /*
         * Read a line from stdin, and attempt to parse it into a
         * display name (ignored), auth protocol, and auth string.
         */
        int c, i, hexdigit, proto;







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
	command = dupprintf("xauth list %s 2>/dev/null", display);
    fp = popen(command, "r");
    sfree(command);

    if (!fp)
        return;                        /* assume no auth */

    localbuf = snewn(maxsize, char);

    while (1) {
        /*
         * Read a line from stdin, and attempt to parse it into a
         * display name (ignored), auth protocol, and auth string.
         */
        int c, i, hexdigit, proto;
Changes to unix/uxagentc.c.
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
	    retsize = GET_32BIT(retbuf);
	    if (retsize <= 0) {
		close(sock);
		goto failure;
	    }
	    retsize += 4;
	    assert(retbuf == sizebuf);
	    retbuf = smalloc(retsize);
	    memcpy(retbuf, sizebuf, 4);
	}
    }

    assert(retbuf != sizebuf);
    *out = retbuf;
    *outlen = retlen;







|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
	    retsize = GET_32BIT(retbuf);
	    if (retsize <= 0) {
		close(sock);
		goto failure;
	    }
	    retsize += 4;
	    assert(retbuf == sizebuf);
	    retbuf = snewn(retsize, char);
	    memcpy(retbuf, sizebuf, 4);
	}
    }

    assert(retbuf != sizebuf);
    *out = retbuf;
    *outlen = retlen;
Changes to unix/uxnet.c.
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
char *error_string(int error)
{
    return strerror(error);
}

SockAddr sk_namelookup(const char *host, char **canonicalname)
{
    SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
    unsigned long a;
    struct hostent *h = NULL;
    char realhost[8192];

    /* Clear the structure and default to IPv4. */
    memset(ret, 0, sizeof(struct SockAddr_tag));
    ret->family = 0;		       /* We set this one when we have resolved the host. */







|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
char *error_string(int error)
{
    return strerror(error);
}

SockAddr sk_namelookup(const char *host, char **canonicalname)
{
    SockAddr ret = snew(struct SockAddr_tag);
    unsigned long a;
    struct hostent *h = NULL;
    char realhost[8192];

    /* Clear the structure and default to IPv4. */
    memset(ret, 0, sizeof(struct SockAddr_tag));
    ret->family = 0;		       /* We set this one when we have resolved the host. */
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
	 * success return from inet_addr.
	 */
	ret->family = AF_INET;
	strncpy(realhost, host, sizeof(realhost));
    }
    ret->address = ntohl(a);
    realhost[lenof(realhost)-1] = '\0';
    *canonicalname = smalloc(1+strlen(realhost));
    strcpy(*canonicalname, realhost);
    return ret;
}

SockAddr sk_nonamelookup(const char *host)
{
    SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
    ret->error = NULL;
    ret->family = AF_UNSPEC;
    strncpy(ret->hostname, host, lenof(ret->hostname));
    ret->hostname[lenof(ret->hostname)-1] = '\0';
    return ret;
}








|






|







191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
	 * success return from inet_addr.
	 */
	ret->family = AF_INET;
	strncpy(realhost, host, sizeof(realhost));
    }
    ret->address = ntohl(a);
    realhost[lenof(realhost)-1] = '\0';
    *canonicalname = snewn(1+strlen(realhost), char);
    strcpy(*canonicalname, realhost);
    return ret;
}

SockAddr sk_nonamelookup(const char *host)
{
    SockAddr ret = snew(struct SockAddr_tag);
    ret->error = NULL;
    ret->family = AF_UNSPEC;
    strncpy(ret->hostname, host, lenof(ret->hostname));
    ret->hostname[lenof(ret->hostname)-1] = '\0';
    return ret;
}

320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
Socket sk_register(void *sock, Plug plug)
{
    Actual_Socket ret;

    /*
     * Create Socket structure.
     */
    ret = smalloc(sizeof(struct Socket_tag));
    ret->fn = &tcp_fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->writable = 1;		       /* to start with */
    ret->sending_oob = 0;
    ret->frozen = 1;







|







320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
Socket sk_register(void *sock, Plug plug)
{
    Actual_Socket ret;

    /*
     * Create Socket structure.
     */
    ret = snew(struct Socket_tag);
    ret->fn = &tcp_fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->writable = 1;		       /* to start with */
    ret->sending_oob = 0;
    ret->frozen = 1;
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
    int err;
    Actual_Socket ret;
    short localport;

    /*
     * Create Socket structure.
     */
    ret = smalloc(sizeof(struct Socket_tag));
    ret->fn = &tcp_fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->connected = 0;		       /* to start with */
    ret->writable = 0;		       /* to start with */
    ret->sending_oob = 0;







|







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
    int err;
    Actual_Socket ret;
    short localport;

    /*
     * Create Socket structure.
     */
    ret = snew(struct Socket_tag);
    ret->fn = &tcp_fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->connected = 0;		       /* to start with */
    ret->writable = 0;		       /* to start with */
    ret->sending_oob = 0;
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
    Actual_Socket ret;
    int retcode;
    int on = 1;

    /*
     * Create Socket structure.
     */
    ret = smalloc(sizeof(struct Socket_tag));
    ret->fn = &tcp_fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->writable = 0;		       /* to start with */
    ret->sending_oob = 0;
    ret->frozen = 0;







|







521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
    Actual_Socket ret;
    int retcode;
    int on = 1;

    /*
     * Create Socket structure.
     */
    ret = snew(struct Socket_tag);
    ret->fn = &tcp_fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->writable = 0;		       /* to start with */
    ret->sending_oob = 0;
    ret->frozen = 0;
Changes to unix/uxplink.c.
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
		cmdlen = cmdsize = 0;
		command = NULL;

		while (argc) {
		    while (*p) {
			if (cmdlen >= cmdsize) {
			    cmdsize = cmdlen + 512;
			    command = srealloc(command, cmdsize);
			}
			command[cmdlen++]=*p++;
		    }
		    if (cmdlen >= cmdsize) {
			cmdsize = cmdlen + 512;
			command = srealloc(command, cmdsize);
		    }
		    command[cmdlen++]=' '; /* always add trailing space */
		    if (--argc) p = *++argv;
		}
		if (cmdlen) command[--cmdlen]='\0';
				       /* change trailing blank to NUL */
		cfg.remote_cmd_ptr = command;







|





|







442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
		cmdlen = cmdsize = 0;
		command = NULL;

		while (argc) {
		    while (*p) {
			if (cmdlen >= cmdsize) {
			    cmdsize = cmdlen + 512;
			    command = sresize(command, cmdsize, char);
			}
			command[cmdlen++]=*p++;
		    }
		    if (cmdlen >= cmdsize) {
			cmdsize = cmdlen + 512;
			command = sresize(command, cmdsize, char);
		    }
		    command[cmdlen++]=' '; /* always add trailing space */
		    if (--argc) p = *++argv;
		}
		if (cmdlen) command[--cmdlen]='\0';
				       /* change trailing blank to NUL */
		cfg.remote_cmd_ptr = command;
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
	i = 0;
	for (socket = first_socket(&socketstate, &rwx); socket >= 0;
	     socket = next_socket(&socketstate, &rwx)) i++;

	/* Expand the sklist buffer if necessary. */
	if (i > sksize) {
	    sksize = i + 16;
	    sklist = srealloc(sklist, sksize * sizeof(*sklist));
	}

	/*
	 * Add all currently open sockets to the select sets, and
	 * store them in sklist as well.
	 */
	skcount = 0;







|







627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
	i = 0;
	for (socket = first_socket(&socketstate, &rwx); socket >= 0;
	     socket = next_socket(&socketstate, &rwx)) i++;

	/* Expand the sklist buffer if necessary. */
	if (i > sksize) {
	    sksize = i + 16;
	    sklist = sresize(sklist, sksize, int);
	}

	/*
	 * Add all currently open sockets to the select sets, and
	 * store them in sklist as well.
	 */
	skcount = 0;
Changes to unix/uxprint.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

struct printer_job_tag {
    FILE *fp;
};

printer_job *printer_start_job(char *printer)
{
    printer_job *ret = smalloc(sizeof(printer_job));
    /*
     * On Unix, we treat the printer string as the name of a
     * command to pipe to - typically lpr, of course.
     */
    ret->fp = popen(printer, "w");
    if (!ret->fp) {
	sfree(ret);







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

struct printer_job_tag {
    FILE *fp;
};

printer_job *printer_start_job(char *printer)
{
    printer_job *ret = snew(printer_job);
    /*
     * On Unix, we treat the printer string as the name of a
     * command to pipe to - typically lpr, of course.
     */
    ret->fp = popen(printer, "w");
    if (!ret->fp) {
	sfree(ret);
Changes to unix/uxstore.c.
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
	fprintf(stderr, "pterm: expected a colon in resource string"
		" \"%s\"\n", string);
	return;
    }
    q++;
    while (p > string && p[-1] != '.' && p[-1] != '*')
	p--;
    xrms = smalloc(sizeof(struct xrm_string));
    key = smalloc(q-p);
    memcpy(key, p, q-p);
    key[q-p-1] = '\0';
    xrms->key = key;
    while (*q && isspace((unsigned char)*q))
	q++;
    xrms->value = dupstr(q);








|
|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
	fprintf(stderr, "pterm: expected a colon in resource string"
		" \"%s\"\n", string);
	return;
    }
    q++;
    while (p > string && p[-1] != '.' && p[-1] != '*')
	p--;
    xrms = snew(struct xrm_string);
    key = snewn(q-p, char);
    memcpy(key, p, q-p);
    key[q-p-1] = '\0';
    xrms->key = key;
    while (*q && isspace((unsigned char)*q))
	q++;
    xrms->value = dupstr(q);

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

/*
 * Read an entire line of text from a file. Return a buffer
 * malloced to be as big as necessary (caller must free).
 */
static char *fgetline(FILE *fp)
{
    char *ret = smalloc(512);
    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 = srealloc(ret, size);
    }
    if (len == 0) {		       /* first fgets returned NULL */
	sfree(ret);
	return NULL;
    }
    ret[len] = '\0';
    return ret;







|






|







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

/*
 * Read an entire line of text from a file. Return a buffer
 * malloced to be as big as necessary (caller must free).
 */
static 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;
Changes to wincfg.c.
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
	for (i = 0; i < s->ncontrols; i++) {
	    c = s->ctrls[i];
	    if (c->generic.type == CTRL_RADIO &&
		c->generic.context.i == offsetof(Config, beep)) {
		assert(c->generic.handler == dlg_stdradiobutton_handler);
		c->radio.nbuttons++;
		c->radio.buttons =
		    srealloc(c->radio.buttons,
			     c->radio.nbuttons * sizeof(*c->radio.buttons));
		c->radio.buttons[c->radio.nbuttons-1] =
		    dupstr("Play a custom sound file");
		c->radio.buttondata =
		    srealloc(c->radio.buttondata,
			     c->radio.nbuttons * sizeof(*c->radio.buttondata));
		c->radio.buttondata[c->radio.nbuttons-1] = I(BELL_WAVEFILE);
		if (c->radio.shortcuts) {
		    c->radio.shortcuts =
			srealloc(c->radio.shortcuts,
				 (c->radio.nbuttons *
				  sizeof(*c->radio.shortcuts)));
		    c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT;
		}
		break;
	    }
	}
    }
    ctrl_filesel(s, "Custom sound file to play as a bell:", NO_SHORTCUT,







|
<



|
<



|
<
<







124
125
126
127
128
129
130
131

132
133
134
135

136
137
138
139


140
141
142
143
144
145
146
	for (i = 0; i < s->ncontrols; i++) {
	    c = s->ctrls[i];
	    if (c->generic.type == CTRL_RADIO &&
		c->generic.context.i == offsetof(Config, beep)) {
		assert(c->generic.handler == dlg_stdradiobutton_handler);
		c->radio.nbuttons++;
		c->radio.buttons =
		    sresize(c->radio.buttons, c->radio.nbuttons, char *);

		c->radio.buttons[c->radio.nbuttons-1] =
		    dupstr("Play a custom sound file");
		c->radio.buttondata =
		    sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);

		c->radio.buttondata[c->radio.nbuttons-1] = I(BELL_WAVEFILE);
		if (c->radio.shortcuts) {
		    c->radio.shortcuts =
			sresize(c->radio.shortcuts, c->radio.nbuttons, char);


		    c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT;
		}
		break;
	    }
	}
    }
    ctrl_filesel(s, "Custom sound file to play as a bell:", NO_SHORTCUT,
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
	for (i = 0; i < s->ncontrols; i++) {
	    c = s->ctrls[i];
	    if (c->generic.type == CTRL_RADIO &&
		c->generic.context.i == offsetof(Config, vtmode)) {
		assert(c->generic.handler == dlg_stdradiobutton_handler);
		c->radio.nbuttons += 2;
		c->radio.buttons =
		    srealloc(c->radio.buttons,
			     c->radio.nbuttons * sizeof(*c->radio.buttons));
		c->radio.buttons[c->radio.nbuttons-2] =
		    dupstr("Use font in both ANSI and OEM modes");
		c->radio.buttons[c->radio.nbuttons-1] =
		    dupstr("Use font in OEM mode only");
		c->radio.buttondata =
		    srealloc(c->radio.buttondata,
			     c->radio.nbuttons * sizeof(*c->radio.buttondata));
		c->radio.buttondata[c->radio.nbuttons-2] = I(VT_OEMANSI);
		c->radio.buttondata[c->radio.nbuttons-1] = I(VT_OEMONLY);
		if (!c->radio.shortcuts) {
		    int j;
		    c->radio.shortcuts =
			smalloc((c->radio.nbuttons *
				 sizeof(*c->radio.shortcuts)));
		    for (j = 0; j < c->radio.nbuttons; j++)
			c->radio.shortcuts[j] = NO_SHORTCUT;
		} else {
		    c->radio.shortcuts =
			srealloc(c->radio.shortcuts,
				 (c->radio.nbuttons *
				  sizeof(*c->radio.shortcuts)));
		}
		c->radio.shortcuts[c->radio.nbuttons-2] = 'b';
		c->radio.shortcuts[c->radio.nbuttons-1] = 'e';
		break;
	    }
	}
    }







|
<





|
<




|
<
<



|
<
|
<







193
194
195
196
197
198
199
200

201
202
203
204
205
206

207
208
209
210
211


212
213
214
215

216

217
218
219
220
221
222
223
	for (i = 0; i < s->ncontrols; i++) {
	    c = s->ctrls[i];
	    if (c->generic.type == CTRL_RADIO &&
		c->generic.context.i == offsetof(Config, vtmode)) {
		assert(c->generic.handler == dlg_stdradiobutton_handler);
		c->radio.nbuttons += 2;
		c->radio.buttons =
		    sresize(c->radio.buttons, c->radio.nbuttons, char *);

		c->radio.buttons[c->radio.nbuttons-2] =
		    dupstr("Use font in both ANSI and OEM modes");
		c->radio.buttons[c->radio.nbuttons-1] =
		    dupstr("Use font in OEM mode only");
		c->radio.buttondata =
		    sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);

		c->radio.buttondata[c->radio.nbuttons-2] = I(VT_OEMANSI);
		c->radio.buttondata[c->radio.nbuttons-1] = I(VT_OEMONLY);
		if (!c->radio.shortcuts) {
		    int j;
		    c->radio.shortcuts = snewn(c->radio.nbuttons, char);


		    for (j = 0; j < c->radio.nbuttons; j++)
			c->radio.shortcuts[j] = NO_SHORTCUT;
		} else {
		    c->radio.shortcuts = sresize(c->radio.shortcuts,

						 c->radio.nbuttons, char);

		}
		c->radio.shortcuts[c->radio.nbuttons-2] = 'b';
		c->radio.shortcuts[c->radio.nbuttons-1] = 'e';
		break;
	    }
	}
    }
Changes to winctrls.c.
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
	char *btext = va_arg(ap, char *);
	int bid;
	if (!btext)
	    break;
	bid = va_arg(ap, int);
    }
    va_end(ap);
    buttons = smalloc(nbuttons * sizeof(struct radio));
    va_start(ap, nacross);
    for (i = 0; i < nbuttons; i++) {
	buttons[i].text = va_arg(ap, char *);
	buttons[i].id = va_arg(ap, int);
    }
    va_end(ap);
    radioline_common(cp, text, id, nacross, buttons, nbuttons);







|







285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
	char *btext = va_arg(ap, char *);
	int bid;
	if (!btext)
	    break;
	bid = va_arg(ap, int);
    }
    va_end(ap);
    buttons = snewn(nbuttons, struct radio);
    va_start(ap, nacross);
    for (i = 0; i < nbuttons; i++) {
	buttons[i].text = va_arg(ap, char *);
	buttons[i].id = va_arg(ap, int);
    }
    va_end(ap);
    radioline_common(cp, text, id, nacross, buttons, nbuttons);
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
	char *btext = va_arg(ap, char *);
	int bid;
	if (!btext)
	    break;
	bid = va_arg(ap, int);
    }
    va_end(ap);
    buttons = smalloc(nbuttons * sizeof(struct radio));
    va_start(ap, nacross);
    for (i = 0; i < nbuttons; i++) {
	buttons[i].text = va_arg(ap, char *);
	buttons[i].id = va_arg(ap, int);
    }
    va_end(ap);
    radioline_common(cp, NULL, 0, nacross, buttons, nbuttons);







|







316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
	char *btext = va_arg(ap, char *);
	int bid;
	if (!btext)
	    break;
	bid = va_arg(ap, int);
    }
    va_end(ap);
    buttons = snewn(nbuttons, struct radio);
    va_start(ap, nacross);
    for (i = 0; i < nbuttons; i++) {
	buttons[i].text = va_arg(ap, char *);
	buttons[i].id = va_arg(ap, int);
    }
    va_end(ap);
    radioline_common(cp, NULL, 0, nacross, buttons, nbuttons);
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
	char *btext = va_arg(ap, char *);
	int bid;
	if (!btext)
	    break;
	bid = va_arg(ap, int);
    }
    va_end(ap);
    buttons = smalloc(nbuttons * sizeof(struct radio));
    va_start(ap, id);
    for (i = 0; i < nbuttons; i++) {
	buttons[i].text = va_arg(ap, char *);
	buttons[i].id = va_arg(ap, int);
    }
    va_end(ap);
    radioline_common(cp, text, id, 1, buttons, nbuttons);







|







347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
	char *btext = va_arg(ap, char *);
	int bid;
	if (!btext)
	    break;
	bid = va_arg(ap, int);
    }
    va_end(ap);
    buttons = snewn(nbuttons, struct radio);
    va_start(ap, id);
    for (i = 0; i < nbuttons; i++) {
	buttons[i].text = va_arg(ap, char *);
	buttons[i].id = va_arg(ap, int);
    }
    va_end(ap);
    radioline_common(cp, text, id, 1, buttons, nbuttons);
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
    int width, nlines, j;
    INT *pwidths, nfit;
    SIZE size;
    char *ret, *p, *q;
    RECT r;
    HFONT oldfont, newfont;

    ret = smalloc(1+strlen(text));
    p = text;
    q = ret;
    pwidths = smalloc(sizeof(INT)*(1+strlen(text)));

    /*
     * Work out the width the text will need to fit in, by doing
     * the same adjustment that the `statictext' function itself
     * will perform.
     */
    SetMapMode(hdc, MM_TEXT);	       /* ensure logical units == pixels */







|


|







391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
    int width, nlines, j;
    INT *pwidths, nfit;
    SIZE size;
    char *ret, *p, *q;
    RECT r;
    HFONT oldfont, newfont;

    ret = snewn(1+strlen(text), char);
    p = text;
    q = ret;
    pwidths = snewn(1+strlen(text), INT);

    /*
     * Work out the width the text will need to fit in, by doing
     * the same adjustment that the `statictext' function itself
     * will perform.
     */
    SetMapMode(hdc, MM_TEXT);	       /* ensure logical units == pixels */
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
 */
static void pl_moveitem(HWND hwnd, int listid, int src, int dst)
{
    int tlen, val;
    char *txt;
    /* Get the item's data. */
    tlen = SendDlgItemMessage (hwnd, listid, LB_GETTEXTLEN, src, 0);
    txt = smalloc(tlen+1);
    SendDlgItemMessage (hwnd, listid, LB_GETTEXT, src, (LPARAM) txt);
    val = SendDlgItemMessage (hwnd, listid, LB_GETITEMDATA, src, 0);
    /* Deselect old location. */
    SendDlgItemMessage (hwnd, listid, LB_SETSEL, FALSE, src);
    /* Delete it at the old location. */
    SendDlgItemMessage (hwnd, listid, LB_DELETESTRING, src, 0);
    /* Insert it at new location. */







|







969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
 */
static void pl_moveitem(HWND hwnd, int listid, int src, int dst)
{
    int tlen, val;
    char *txt;
    /* Get the item's data. */
    tlen = SendDlgItemMessage (hwnd, listid, LB_GETTEXTLEN, src, 0);
    txt = snewn(tlen+1, char);
    SendDlgItemMessage (hwnd, listid, LB_GETTEXT, src, (LPARAM) txt);
    val = SendDlgItemMessage (hwnd, listid, LB_GETITEMDATA, src, 0);
    /* Deselect old location. */
    SendDlgItemMessage (hwnd, listid, LB_SETSEL, FALSE, src);
    /* Delete it at the old location. */
    SendDlgItemMessage (hwnd, listid, LB_DELETESTRING, src, 0);
    /* Insert it at new location. */
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
{
    char *ret;
    char *p, *q;

    if (!text)
	return NULL;		       /* sfree won't choke on this */

    ret = smalloc(2*strlen(text)+1);   /* size potentially doubles! */
    shortcut = tolower((unsigned char)shortcut);

    p = text;
    q = ret;
    while (*p) {
	if (shortcut != NO_SHORTCUT &&
	    tolower((unsigned char)*p) == shortcut) {







|







1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
{
    char *ret;
    char *p, *q;

    if (!text)
	return NULL;		       /* sfree won't choke on this */

    ret = snewn(2*strlen(text)+1, char);   /* size potentially doubles! */
    shortcut = tolower((unsigned char)shortcut);

    p = text;
    q = ret;
    while (*p) {
	if (shortcut != NO_SHORTCUT &&
	    tolower((unsigned char)*p) == shortcut) {
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
    int i, actual_base_id, base_id, num_ids;
    void *data;

    base_id = *id;

    /* Start a containing box, if we have a boxname. */
    if (s->boxname && *s->boxname) {
	struct winctrl *c = smalloc(sizeof(struct winctrl));
    	c->ctrl = NULL;
	c->base_id = base_id;
	c->num_ids = 1;
	c->data = NULL;
	memset(c->shortcuts, NO_SHORTCUT, lenof(c->shortcuts));
	winctrl_add(wc, c);
	beginbox(cp, s->boxtitle, base_id);
	base_id++;
    }

    /* Draw a title, if we have one. */
    if (!s->boxname && s->boxtitle) {
	struct winctrl *c = smalloc(sizeof(struct winctrl));
    	c->ctrl = NULL;
	c->base_id = base_id;
	c->num_ids = 1;
	c->data = dupstr(s->boxtitle);
	memset(c->shortcuts, NO_SHORTCUT, lenof(c->shortcuts));
	winctrl_add(wc, c);
	paneltitle(cp, base_id);







|












|







1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
    int i, actual_base_id, base_id, num_ids;
    void *data;

    base_id = *id;

    /* Start a containing box, if we have a boxname. */
    if (s->boxname && *s->boxname) {
	struct winctrl *c = snew(struct winctrl);
    	c->ctrl = NULL;
	c->base_id = base_id;
	c->num_ids = 1;
	c->data = NULL;
	memset(c->shortcuts, NO_SHORTCUT, lenof(c->shortcuts));
	winctrl_add(wc, c);
	beginbox(cp, s->boxtitle, base_id);
	base_id++;
    }

    /* Draw a title, if we have one. */
    if (!s->boxname && s->boxtitle) {
	struct winctrl *c = snew(struct winctrl);
    	c->ctrl = NULL;
	c->base_id = base_id;
	c->num_ids = 1;
	c->data = dupstr(s->boxtitle);
	memset(c->shortcuts, NO_SHORTCUT, lenof(c->shortcuts));
	winctrl_add(wc, c);
	paneltitle(cp, base_id);
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
		struct radio *buttons;
		int i;

		escaped = shortcut_escape(ctrl->radio.label,
					  ctrl->radio.shortcut);
		shortcuts[nshortcuts++] = ctrl->radio.shortcut;

		buttons = smalloc(ctrl->radio.nbuttons * sizeof(struct radio));

		for (i = 0; i < ctrl->radio.nbuttons; i++) {
		    buttons[i].text =
			shortcut_escape(ctrl->radio.buttons[i],
					(char)(ctrl->radio.shortcuts ?
					       ctrl->radio.shortcuts[i] :
					       NO_SHORTCUT));







|







1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
		struct radio *buttons;
		int i;

		escaped = shortcut_escape(ctrl->radio.label,
					  ctrl->radio.shortcut);
		shortcuts[nshortcuts++] = ctrl->radio.shortcut;

		buttons = snewn(ctrl->radio.nbuttons, struct radio);

		for (i = 0; i < ctrl->radio.nbuttons; i++) {
		    buttons[i].text =
			shortcut_escape(ctrl->radio.buttons[i],
					(char)(ctrl->radio.shortcuts ?
					       ctrl->radio.shortcuts[i] :
					       NO_SHORTCUT));
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
	    break;
	  case CTRL_LISTBOX:
	    num_ids = 2;
	    escaped = shortcut_escape(ctrl->listbox.label,
				      ctrl->listbox.shortcut);
	    shortcuts[nshortcuts++] = ctrl->listbox.shortcut;
	    if (ctrl->listbox.draglist) {
		data = smalloc(sizeof(struct prefslist));
		num_ids = 4;
		prefslist(data, &pos, ctrl->listbox.height, escaped,
			  base_id, base_id+1, base_id+2, base_id+3);
		shortcuts[nshortcuts++] = 'u';   /* Up */
		shortcuts[nshortcuts++] = 'd';   /* Down */
	    } else if (ctrl->listbox.height == 0) {
		/* Drop-down list. */







|







1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
	    break;
	  case CTRL_LISTBOX:
	    num_ids = 2;
	    escaped = shortcut_escape(ctrl->listbox.label,
				      ctrl->listbox.shortcut);
	    shortcuts[nshortcuts++] = ctrl->listbox.shortcut;
	    if (ctrl->listbox.draglist) {
		data = snew(struct prefslist);
		num_ids = 4;
		prefslist(data, &pos, ctrl->listbox.height, escaped,
			  base_id, base_id+1, base_id+2, base_id+3);
		shortcuts[nshortcuts++] = 'u';   /* Up */
		shortcuts[nshortcuts++] = 'd';   /* Down */
	    } else if (ctrl->listbox.height == 0) {
		/* Drop-down list. */
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
		 * before MapDialogRect. But that's going to be no
		 * fun, and this should be good enough accuracy.
		 */
		int width = cp->width * ctrl->listbox.percentwidth;
		int *tabarray;
		int i, percent;

		tabarray = smalloc((ctrl->listbox.ncols-1) * sizeof(int));
		percent = 0;
		for (i = 0; i < ctrl->listbox.ncols-1; i++) {
		    percent += ctrl->listbox.percentages[i];
		    tabarray[i] = width * percent / 10000;
		}
		SendDlgItemMessage(cp->hwnd, base_id+1, LB_SETTABSTOPS,
				   ctrl->listbox.ncols-1, (LPARAM)tabarray);







|







1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
		 * before MapDialogRect. But that's going to be no
		 * fun, and this should be good enough accuracy.
		 */
		int width = cp->width * ctrl->listbox.percentwidth;
		int *tabarray;
		int i, percent;

		tabarray = snewn(ctrl->listbox.ncols-1, int);
		percent = 0;
		for (i = 0; i < ctrl->listbox.ncols-1; i++) {
		    percent += ctrl->listbox.percentages[i];
		    tabarray[i] = width * percent / 10000;
		}
		SendDlgItemMessage(cp->hwnd, base_id+1, LB_SETTABSTOPS,
				   ctrl->listbox.ncols-1, (LPARAM)tabarray);
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
	    num_ids = 3;
	    escaped = shortcut_escape(ctrl->fontselect.label,
				      ctrl->fontselect.shortcut);
	    shortcuts[nshortcuts++] = ctrl->fontselect.shortcut;
	    statictext(&pos, escaped, 1, base_id);
	    staticbtn(&pos, "", base_id+1, "Change...", base_id+2);
	    sfree(escaped);
	    data = smalloc(sizeof(FontSpec));
	    break;
	  default:
	    assert(!"Can't happen");
	    num_ids = 0;	       /* placate gcc */
	    break;
	}

	/*
	 * Create a `struct winctrl' for this control, and advance
	 * the dialog ID counter, if it's actually been created
	 * (and isn't tabdelayed).
	 */
	if (pos.hwnd) {
	    struct winctrl *c = smalloc(sizeof(struct winctrl));

	    c->ctrl = ctrl;
	    c->base_id = actual_base_id;
	    c->num_ids = num_ids;
	    c->data = data;
	    memcpy(c->shortcuts, shortcuts, sizeof(shortcuts));
	    winctrl_add(wc, c);







|













|







1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
	    num_ids = 3;
	    escaped = shortcut_escape(ctrl->fontselect.label,
				      ctrl->fontselect.shortcut);
	    shortcuts[nshortcuts++] = ctrl->fontselect.shortcut;
	    statictext(&pos, escaped, 1, base_id);
	    staticbtn(&pos, "", base_id+1, "Change...", base_id+2);
	    sfree(escaped);
	    data = snew(FontSpec);
	    break;
	  default:
	    assert(!"Can't happen");
	    num_ids = 0;	       /* placate gcc */
	    break;
	}

	/*
	 * Create a `struct winctrl' for this control, and advance
	 * the dialog ID counter, if it's actually been created
	 * (and isn't tabdelayed).
	 */
	if (pos.hwnd) {
	    struct winctrl *c = snew(struct winctrl);

	    c->ctrl = ctrl;
	    c->base_id = actual_base_id;
	    c->num_ids = num_ids;
	    c->data = data;
	    memcpy(c->shortcuts, shortcuts, sizeof(shortcuts));
	    winctrl_add(wc, c);
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
		int index, len;
		char *text;

		index = SendDlgItemMessage(dp->hwnd, c->base_id+1,
					   CB_GETCURSEL, 0, 0);
		len = SendDlgItemMessage(dp->hwnd, c->base_id+1,
					 CB_GETLBTEXTLEN, index, 0);
		text = smalloc(len+1);
		SendDlgItemMessage(dp->hwnd, c->base_id+1, CB_GETLBTEXT,
				   index, (LPARAM)text);
		SetDlgItemText(dp->hwnd, c->base_id+1, text);
		sfree(text);
		ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
	    } else if (HIWORD(wParam) == CBN_EDITCHANGE) {
		ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);







|







1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
		int index, len;
		char *text;

		index = SendDlgItemMessage(dp->hwnd, c->base_id+1,
					   CB_GETCURSEL, 0, 0);
		len = SendDlgItemMessage(dp->hwnd, c->base_id+1,
					 CB_GETLBTEXTLEN, index, 0);
		text = snewn(len+1, char);
		SendDlgItemMessage(dp->hwnd, c->base_id+1, CB_GETLBTEXT,
				   index, (LPARAM)text);
		SetDlgItemText(dp->hwnd, c->base_id+1, text);
		sfree(text);
		ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
	    } else if (HIWORD(wParam) == CBN_EDITCHANGE) {
		ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527




2528
2529
2530
void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr)
{
    struct dlgparam *dp = (struct dlgparam *)dlg;
    struct perctrl_privdata tmp, *p;
    tmp.ctrl = ctrl;
    p = find234(dp->privdata, &tmp, NULL);
    if (!p) {
	p = smalloc(sizeof(struct perctrl_privdata));
	p->ctrl = ctrl;
	p->needs_free = FALSE;
	add234(dp->privdata, p);
    }
    p->data = ptr;
}

void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size)
{
    struct dlgparam *dp = (struct dlgparam *)dlg;
    struct perctrl_privdata tmp, *p;
    tmp.ctrl = ctrl;
    p = find234(dp->privdata, &tmp, NULL);
    if (!p) {
	p = smalloc(sizeof(struct perctrl_privdata));
	p->ctrl = ctrl;
	p->needs_free = FALSE;
	add234(dp->privdata, p);
    }
    assert(!p->needs_free);
    p->needs_free = TRUE;




    p->data = smalloc(size);
    return p->data;
}







|














|






>
>
>
>



2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr)
{
    struct dlgparam *dp = (struct dlgparam *)dlg;
    struct perctrl_privdata tmp, *p;
    tmp.ctrl = ctrl;
    p = find234(dp->privdata, &tmp, NULL);
    if (!p) {
	p = snew(struct perctrl_privdata);
	p->ctrl = ctrl;
	p->needs_free = FALSE;
	add234(dp->privdata, p);
    }
    p->data = ptr;
}

void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size)
{
    struct dlgparam *dp = (struct dlgparam *)dlg;
    struct perctrl_privdata tmp, *p;
    tmp.ctrl = ctrl;
    p = find234(dp->privdata, &tmp, NULL);
    if (!p) {
	p = snew(struct perctrl_privdata);
	p->ctrl = ctrl;
	p->needs_free = FALSE;
	add234(dp->privdata, p);
    }
    assert(!p->needs_free);
    p->needs_free = TRUE;
    /*
     * This is an internal allocation routine, so it's allowed to
     * use smalloc directly.
     */
    p->data = smalloc(size);
    return p->data;
}
Changes to windlg.c.
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
		selcount = SendDlgItemMessage(hwnd, IDN_LIST,
					      LB_GETSELCOUNT, 0, 0);
		if (selcount == 0) {   /* don't even try to copy zero items */
		    MessageBeep(0);
		    break;
		}

		selitems = smalloc(selcount * sizeof(int));
		if (selitems) {
		    int count = SendDlgItemMessage(hwnd, IDN_LIST,
						   LB_GETSELITEMS,
						   selcount,
						   (LPARAM) selitems);
		    int i;
		    int size;
		    char *clipdata;
		    static unsigned char sel_nl[] = SEL_NL;

		    if (count == 0) {  /* can't copy zero stuff */
			MessageBeep(0);
			break;
		    }

		    size = 0;
		    for (i = 0; i < count; i++)
			size +=
			    strlen(events[selitems[i]]) + sizeof(sel_nl);

		    clipdata = smalloc(size);
		    if (clipdata) {
			char *p = clipdata;
			for (i = 0; i < count; i++) {
			    char *q = events[selitems[i]];
			    int qlen = strlen(q);
			    memcpy(p, q, qlen);
			    p += qlen;







|




















|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
		selcount = SendDlgItemMessage(hwnd, IDN_LIST,
					      LB_GETSELCOUNT, 0, 0);
		if (selcount == 0) {   /* don't even try to copy zero items */
		    MessageBeep(0);
		    break;
		}

		selitems = snewn(selcount, int);
		if (selitems) {
		    int count = SendDlgItemMessage(hwnd, IDN_LIST,
						   LB_GETSELITEMS,
						   selcount,
						   (LPARAM) selitems);
		    int i;
		    int size;
		    char *clipdata;
		    static unsigned char sel_nl[] = SEL_NL;

		    if (count == 0) {  /* can't copy zero stuff */
			MessageBeep(0);
			break;
		    }

		    size = 0;
		    for (i = 0; i < count; i++)
			size +=
			    strlen(events[selitems[i]]) + sizeof(sel_nl);

		    clipdata = snewn(size, char);
		    if (clipdata) {
			char *p = clipdata;
			for (i = 0; i < count; i++) {
			    char *q = events[selitems[i]];
			    int qlen = strlen(q);
			    memcpy(p, q, qlen);
			    p += qlen;
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
    char timebuf[40];
    time_t t;

    log_eventlog(logctx, string);

    if (nevents >= negsize) {
	negsize += 64;
	events = srealloc(events, negsize * sizeof(*events));
    }

    time(&t);
    strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S\t",
	     localtime(&t));

    events[nevents] = smalloc(strlen(timebuf) + strlen(string) + 1);
    strcpy(events[nevents], timebuf);
    strcat(events[nevents], string);
    if (logbox) {
	int count;
	SendDlgItemMessage(logbox, IDN_LIST, LB_ADDSTRING,
			   0, (LPARAM) events[nevents]);
	count = SendDlgItemMessage(logbox, IDN_LIST, LB_GETCOUNT, 0, 0);







|






|







644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
    char timebuf[40];
    time_t t;

    log_eventlog(logctx, string);

    if (nevents >= negsize) {
	negsize += 64;
	events = sresize(events, negsize, char *);
    }

    time(&t);
    strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S\t",
	     localtime(&t));

    events[nevents] = snewn(strlen(timebuf) + strlen(string) + 1, char);
    strcpy(events[nevents], timebuf);
    strcat(events[nevents], string);
    if (logbox) {
	int count;
	SendDlgItemMessage(logbox, IDN_LIST, LB_ADDSTRING,
			   0, (LPARAM) events[nevents]);
	count = SendDlgItemMessage(logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
Changes to window.c.
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

    /*
     * Set up a caret bitmap, with no content.
     */
    {
	char *bits;
	int size = (font_width + 15) / 16 * 2 * font_height;
	bits = smalloc(size);
	memset(bits, 0, size);
	caretbm = CreateBitmap(font_width, font_height, 1, 1, bits);
	sfree(bits);
    }
    CreateCaret(hwnd, caretbm, font_width, font_height);

    /*







|







596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

    /*
     * Set up a caret bitmap, with no content.
     */
    {
	char *bits;
	int size = (font_width + 15) / 16 * 2 * font_height;
	bits = snewn(size, char);
	memset(bits, 0, size);
	caretbm = CreateBitmap(font_width, font_height, 1, 1, bits);
	sfree(bits);
    }
    CreateCaret(hwnd, caretbm, font_width, font_height);

    /*
995
996
997
998
999
1000
1001




1002
1003
1004
1005
1006
1007
1008
 */
static void init_palette(void)
{
    int i;
    HDC hdc = GetDC(hwnd);
    if (hdc) {
	if (cfg.try_palette && GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) {




	    logpal = smalloc(sizeof(*logpal)
			     - sizeof(logpal->palPalEntry)
			     + NCOLOURS * sizeof(PALETTEENTRY));
	    logpal->palVersion = 0x300;
	    logpal->palNumEntries = NCOLOURS;
	    for (i = 0; i < NCOLOURS; i++) {
		logpal->palPalEntry[i].peRed = defpal[i].rgbtRed;







>
>
>
>







995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
 */
static void init_palette(void)
{
    int i;
    HDC hdc = GetDC(hwnd);
    if (hdc) {
	if (cfg.try_palette && GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) {
	    /*
	     * This is a genuine case where we must use smalloc
	     * because the snew macros can't cope.
	     */
	    logpal = smalloc(sizeof(*logpal)
			     - sizeof(logpal->palPalEntry)
			     + NCOLOURS * sizeof(PALETTEENTRY));
	    logpal->palVersion = 0x300;
	    logpal->palNumEntries = NCOLOURS;
	    for (i = 0; i < NCOLOURS; i++) {
		logpal->palPalEntry[i].peRed = defpal[i].rgbtRed;
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
		    }
		    sprintf(c, "putty &%p", filemap);
		    cl = c;
		} else if (wParam == IDM_SAVEDSESS) {
		    if ((lParam - IDM_SAVED_MIN) / 16 < sesslist.nsessions) {
			char *session =
			    sesslist.sessions[(lParam - IDM_SAVED_MIN) / 16];
			cl = smalloc(16 + strlen(session));
				       /* 8, but play safe */
			if (!cl)
			    cl = NULL;    
				       /* not a very important failure mode */
			else {
			    sprintf(cl, "putty @%s", session);
			    freecl = TRUE;







|







1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
		    }
		    sprintf(c, "putty &%p", filemap);
		    cl = c;
		} else if (wParam == IDM_SAVEDSESS) {
		    if ((lParam - IDM_SAVED_MIN) / 16 < sesslist.nsessions) {
			char *session =
			    sesslist.sessions[(lParam - IDM_SAVED_MIN) / 16];
			cl = snewn(16 + strlen(session), char);
				       /* 8, but play safe */
			if (!cl)
			    cl = NULL;    
				       /* not a very important failure mode */
			else {
			    sprintf(cl, "putty @%s", session);
			    freecl = TRUE;
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
		break; /* fall back to DefWindowProc */

	    hIMC = ImmGetContext(hwnd);
	    n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);

	    if (n > 0) {
		int i;
		buff = (char*) smalloc(n);
		ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, n);
		/*
		 * Jaeyoun Chung reports that Korean character
		 * input doesn't work correctly if we do a single
		 * luni_send() covering the whole of buff. So
		 * instead we luni_send the characters one by one.
		 */







|







2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
		break; /* fall back to DefWindowProc */

	    hIMC = ImmGetContext(hwnd);
	    n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);

	    if (n > 0) {
		int i;
		buff = snewn(n, char);
		ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, n);
		/*
		 * Jaeyoun Chung reports that Korean character
		 * input doesn't work correctly if we do a single
		 * luni_send() covering the whole of buff. So
		 * instead we luni_send the characters one by one.
		 */
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
    if (attr & ATTR_WIDE)
	char_width *= 2;

    if (len > IpDxLEN || IpDx[0] != char_width) {
	int i;
	if (len > IpDxLEN) {
	    sfree(IpDx);
	    IpDx = smalloc((len + 16) * sizeof(int));
	    IpDxLEN = (len + 16);
	}
	for (i = 0; i < IpDxLEN; i++)
	    IpDx[i] = char_width;
    }

    /* Only want the left half of double width lines */







|







2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
    if (attr & ATTR_WIDE)
	char_width *= 2;

    if (len > IpDxLEN || IpDx[0] != char_width) {
	int i;
	if (len > IpDxLEN) {
	    sfree(IpDx);
	    IpDx = snewn(len + 16, int);
	    IpDxLEN = (len + 16);
	}
	for (i = 0; i < IpDxLEN; i++)
	    IpDx[i] = char_width;
    }

    /* Only want the left half of double width lines */
2846
2847
2848
2849
2850
2851
2852
2853

2854
2855
2856
2857
2858
2859
2860
	/* Ho Hum, dbcs fonts are a PITA! */
	/* To display on W9x I have to convert to UCS */
	static wchar_t *uni_buf = 0;
	static int uni_len = 0;
	int nlen, mptr;
	if (len > uni_len) {
	    sfree(uni_buf);
	    uni_buf = smalloc((uni_len = len) * sizeof(wchar_t));

	}

	for(nlen = mptr = 0; mptr<len; mptr++) {
	    uni_buf[nlen] = 0xFFFD;
	    if (IsDBCSLeadByteEx(ucsdata.font_codepage, (BYTE) text[mptr])) {
		IpDx[nlen] += char_width;
	        MultiByteToWideChar(ucsdata.font_codepage, MB_USEGLYPHCHARS,







|
>







2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
	/* Ho Hum, dbcs fonts are a PITA! */
	/* To display on W9x I have to convert to UCS */
	static wchar_t *uni_buf = 0;
	static int uni_len = 0;
	int nlen, mptr;
	if (len > uni_len) {
	    sfree(uni_buf);
	    uni_len = len;
	    uni_buf = snewn(uni_len, wchar_t);
	}

	for(nlen = mptr = 0; mptr<len; mptr++) {
	    uni_buf[nlen] = 0xFFFD;
	    if (IsDBCSLeadByteEx(ucsdata.font_codepage, (BYTE) text[mptr])) {
		IpDx[nlen] += char_width;
	        MultiByteToWideChar(ucsdata.font_codepage, MB_USEGLYPHCHARS,
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
	/* And 'normal' unicode characters */
	static WCHAR *wbuf = NULL;
	static int wlen = 0;
	int i;
	if (wlen < len) {
	    sfree(wbuf);
	    wlen = len;
	    wbuf = smalloc(wlen * sizeof(WCHAR));
	}
	for (i = 0; i < len; i++)
	    wbuf[i] = (WCHAR) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));

	ExtTextOutW(hdc, x,
		    y - font_height * (lattr == LATTR_BOT) + text_adjust,
		    ETO_CLIPPED | ETO_OPAQUE, &line_box, wbuf, len, IpDx);







|







2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
	/* And 'normal' unicode characters */
	static WCHAR *wbuf = NULL;
	static int wlen = 0;
	int i;
	if (wlen < len) {
	    sfree(wbuf);
	    wlen = len;
	    wbuf = snewn(wlen, WCHAR);
	}
	for (i = 0; i < len; i++)
	    wbuf[i] = (WCHAR) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));

	ExtTextOutW(hdc, x,
		    y - font_height * (lattr == LATTR_BOT) + text_adjust,
		    ETO_CLIPPED | ETO_OPAQUE, &line_box, wbuf, len, IpDx);
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
     */
    term_do_paste(term);
}

void set_title(void *frontend, char *title)
{
    sfree(window_name);
    window_name = smalloc(1 + strlen(title));
    strcpy(window_name, title);
    if (cfg.win_name_always || !IsIconic(hwnd))
	SetWindowText(hwnd, title);
}

void set_icon(void *frontend, char *title)
{
    sfree(icon_name);
    icon_name = smalloc(1 + strlen(title));
    strcpy(icon_name, title);
    if (!cfg.win_name_always && IsIconic(hwnd))
	SetWindowText(hwnd, title);
}

void set_sbar(void *frontend, int total, int start, int page)
{







|








|







3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
     */
    term_do_paste(term);
}

void set_title(void *frontend, char *title)
{
    sfree(window_name);
    window_name = snewn(1 + strlen(title), char);
    strcpy(window_name, title);
    if (cfg.win_name_always || !IsIconic(hwnd))
	SetWindowText(hwnd, title);
}

void set_icon(void *frontend, char *title)
{
    sfree(icon_name);
    icon_name = snewn(1 + strlen(title), char);
    strcpy(icon_name, title);
    if (!cfg.win_name_always && IsIconic(hwnd))
	SetWindowText(hwnd, title);
}

void set_sbar(void *frontend, int total, int start, int page)
{
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
	int rtfsize = 0;
	int multilen, blen, alen, totallen, i;
	char before[16], after[4];

	get_unitab(CP_ACP, unitab, 0);

	rtfsize = 100 + strlen(cfg.font.name);
	rtf = smalloc(rtfsize);
	sprintf(rtf, "{\\rtf1\\ansi%d{\\fonttbl\\f0\\fmodern %s;}\\f0",
		GetACP(), cfg.font.name);
	rtflen = strlen(rtf);

	/*
	 * We want to construct a piece of RTF that specifies the
	 * same Unicode text. To do this we will read back in







|







4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
	int rtfsize = 0;
	int multilen, blen, alen, totallen, i;
	char before[16], after[4];

	get_unitab(CP_ACP, unitab, 0);

	rtfsize = 100 + strlen(cfg.font.name);
	rtf = snewn(rtfsize, char);
	sprintf(rtf, "{\\rtf1\\ansi%d{\\fonttbl\\f0\\fmodern %s;}\\f0",
		GetACP(), cfg.font.name);
	rtflen = strlen(rtf);

	/*
	 * We want to construct a piece of RTF that specifies the
	 * same Unicode text. To do this we will read back in
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
		    totallen += 4;
		else
		    totallen++;
	    }

	    if (rtfsize < rtflen + totallen + 3) {
		rtfsize = rtflen + totallen + 512;
		rtf = srealloc(rtf, rtfsize);
	    }

	    strcpy(rtf + rtflen, before); rtflen += blen;
	    for (i = 0; i < multilen; i++) {
		if (tdata[tindex+i] == '\\' ||
		    tdata[tindex+i] == '{' ||
		    tdata[tindex+i] == '}') {







|







4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
		    totallen += 4;
		else
		    totallen++;
	    }

	    if (rtfsize < rtflen + totallen + 3) {
		rtfsize = rtflen + totallen + 512;
		rtf = sresize(rtf, rtfsize, char);
	    }

	    strcpy(rtf + rtflen, before); rtflen += blen;
	    for (i = 0; i < multilen; i++) {
		if (tdata[tindex+i] == '\\' ||
		    tdata[tindex+i] == '{' ||
		    tdata[tindex+i] == '}') {
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
	    }
	} else if ( (clipdata = GetClipboardData(CF_TEXT)) ) {
	    char *s;
	    int i;
	    CloseClipboard();
	    s = GlobalLock(clipdata);
	    i = MultiByteToWideChar(CP_ACP, 0, s, strlen(s) + 1, 0, 0);
	    *p = converted = smalloc(i * sizeof(wchar_t));
	    MultiByteToWideChar(CP_ACP, 0, s, strlen(s) + 1, converted, i);
	    *len = i - 1;
	    return;
	} else
	    CloseClipboard();
    }








|







4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
	    }
	} else if ( (clipdata = GetClipboardData(CF_TEXT)) ) {
	    char *s;
	    int i;
	    CloseClipboard();
	    s = GlobalLock(clipdata);
	    i = MultiByteToWideChar(CP_ACP, 0, s, strlen(s) + 1, 0, 0);
	    *p = converted = snewn(i, wchar_t);
	    MultiByteToWideChar(CP_ACP, 0, s, strlen(s) + 1, converted, i);
	    *len = i - 1;
	    return;
	} else
	    CloseClipboard();
    }

Changes to winnet.c.
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
      default:
	return "Unknown network error";
    }
}

SockAddr sk_namelookup(const char *host, char **canonicalname)
{
    SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
    unsigned long a;
    struct hostent *h = NULL;
    char realhost[8192];

    /* Clear the structure and default to IPv4. */
    memset(ret, 0, sizeof(struct SockAddr_tag));
    ret->family = 0;		       /* We set this one when we have resolved the host. */







|







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
      default:
	return "Unknown network error";
    }
}

SockAddr sk_namelookup(const char *host, char **canonicalname)
{
    SockAddr ret = snew(struct SockAddr_tag);
    unsigned long a;
    struct hostent *h = NULL;
    char realhost[8192];

    /* Clear the structure and default to IPv4. */
    memset(ret, 0, sizeof(struct SockAddr_tag));
    ret->family = 0;		       /* We set this one when we have resolved the host. */
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
	 * success return from inet_addr.
	 */
	ret->family = AF_INET;
	strncpy(realhost, host, sizeof(realhost));
    }
    ret->address = ntohl(a);
    realhost[lenof(realhost)-1] = '\0';
    *canonicalname = smalloc(1+strlen(realhost));
    strcpy(*canonicalname, realhost);
    return ret;
}

SockAddr sk_nonamelookup(const char *host)
{
    SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
    ret->error = NULL;
    ret->family = AF_UNSPEC;
    strncpy(ret->hostname, host, lenof(ret->hostname));
    ret->hostname[lenof(ret->hostname)-1] = '\0';
    return ret;
}








|






|







353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
	 * success return from inet_addr.
	 */
	ret->family = AF_INET;
	strncpy(realhost, host, sizeof(realhost));
    }
    ret->address = ntohl(a);
    realhost[lenof(realhost)-1] = '\0';
    *canonicalname = snewn(1+strlen(realhost), char);
    strcpy(*canonicalname, realhost);
    return ret;
}

SockAddr sk_nonamelookup(const char *host)
{
    SockAddr ret = snew(struct SockAddr_tag);
    ret->error = NULL;
    ret->family = AF_UNSPEC;
    strncpy(ret->hostname, host, lenof(ret->hostname));
    ret->hostname[lenof(ret->hostname)-1] = '\0';
    return ret;
}

486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
    DWORD err;
    char *errstr;
    Actual_Socket ret;

    /*
     * Create Socket structure.
     */
    ret = smalloc(sizeof(struct Socket_tag));
    ret->fn = &fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->writable = 1;		       /* to start with */
    ret->sending_oob = 0;
    ret->frozen = 1;







|







486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
    DWORD err;
    char *errstr;
    Actual_Socket ret;

    /*
     * Create Socket structure.
     */
    ret = snew(struct Socket_tag);
    ret->fn = &fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->writable = 1;		       /* to start with */
    ret->sending_oob = 0;
    ret->frozen = 1;
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
    char *errstr;
    Actual_Socket ret;
    short localport;

    /*
     * Create Socket structure.
     */
    ret = smalloc(sizeof(struct Socket_tag));
    ret->fn = &fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->connected = 0;		       /* to start with */
    ret->writable = 0;		       /* to start with */
    ret->sending_oob = 0;







|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
    char *errstr;
    Actual_Socket ret;
    short localport;

    /*
     * Create Socket structure.
     */
    ret = snew(struct Socket_tag);
    ret->fn = &fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->connected = 0;		       /* to start with */
    ret->writable = 0;		       /* to start with */
    ret->sending_oob = 0;
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
    Actual_Socket ret;
    int retcode;
    int on = 1;

    /*
     * Create Socket structure.
     */
    ret = smalloc(sizeof(struct Socket_tag));
    ret->fn = &fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->writable = 0;		       /* to start with */
    ret->sending_oob = 0;
    ret->frozen = 0;







|







728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
    Actual_Socket ret;
    int retcode;
    int on = 1;

    /*
     * Create Socket structure.
     */
    ret = snew(struct Socket_tag);
    ret->fn = &fn_table;
    ret->error = NULL;
    ret->plug = plug;
    bufchain_init(&ret->output_data);
    ret->writable = 0;		       /* to start with */
    ret->sending_oob = 0;
    ret->frozen = 0;
Changes to winstore.c.
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    HKEY subkey1, sesskey;
    int ret;
    char *p;

    if (!sessionname || !*sessionname)
	sessionname = "Default Settings";

    p = smalloc(3 * strlen(sessionname) + 1);
    mungestr(sessionname, p);

    ret = RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1);
    if (ret != ERROR_SUCCESS) {
	sfree(p);
	return NULL;
    }







|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    HKEY subkey1, sesskey;
    int ret;
    char *p;

    if (!sessionname || !*sessionname)
	sessionname = "Default Settings";

    p = snewn(3 * strlen(sessionname) + 1, char);
    mungestr(sessionname, p);

    ret = RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1);
    if (ret != ERROR_SUCCESS) {
	sfree(p);
	return NULL;
    }
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
{
    HKEY subkey1, sesskey;
    char *p;

    if (!sessionname || !*sessionname)
	sessionname = "Default Settings";

    p = smalloc(3 * strlen(sessionname) + 1);
    mungestr(sessionname, p);

    if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
	sesskey = NULL;
    } else {
	if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
	    sesskey = NULL;







|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
{
    HKEY subkey1, sesskey;
    char *p;

    if (!sessionname || !*sessionname)
	sessionname = "Default Settings";

    p = snewn(3 * strlen(sessionname) + 1, char);
    mungestr(sessionname, p);

    if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
	sesskey = NULL;
    } else {
	if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
	    sesskey = NULL;
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
{
    HKEY subkey1;
    char *p;

    if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
	return;

    p = smalloc(3 * strlen(sessionname) + 1);
    mungestr(sessionname, p);
    RegDeleteKey(subkey1, p);
    sfree(p);

    RegCloseKey(subkey1);
}

struct enumsettings {
    HKEY key;
    int i;
};

void *enum_settings_start(void)
{
    struct enumsettings *ret;
    HKEY key;

    if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &key) != ERROR_SUCCESS)
	return NULL;

    ret = smalloc(sizeof(*ret));
    if (ret) {
	ret->key = key;
	ret->i = 0;
    }

    return ret;
}

char *enum_settings_next(void *handle, char *buffer, int buflen)
{
    struct enumsettings *e = (struct enumsettings *) handle;
    char *otherbuf;
    otherbuf = smalloc(3 * buflen);
    if (RegEnumKey(e->key, e->i++, otherbuf, 3 * buflen) == ERROR_SUCCESS) {
	unmungestr(otherbuf, buffer, buflen);
	sfree(otherbuf);
	return buffer;
    } else {
	sfree(otherbuf);
	return NULL;







|




















|












|







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
{
    HKEY subkey1;
    char *p;

    if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
	return;

    p = snewn(3 * strlen(sessionname) + 1, char);
    mungestr(sessionname, p);
    RegDeleteKey(subkey1, p);
    sfree(p);

    RegCloseKey(subkey1);
}

struct enumsettings {
    HKEY key;
    int i;
};

void *enum_settings_start(void)
{
    struct enumsettings *ret;
    HKEY key;

    if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &key) != ERROR_SUCCESS)
	return NULL;

    ret = snew(struct enumsettings);
    if (ret) {
	ret->key = key;
	ret->i = 0;
    }

    return ret;
}

char *enum_settings_next(void *handle, char *buffer, int buflen)
{
    struct enumsettings *e = (struct enumsettings *) handle;
    char *otherbuf;
    otherbuf = snewn(3 * buflen, char);
    if (RegEnumKey(e->key, e->i++, otherbuf, 3 * buflen) == ERROR_SUCCESS) {
	unmungestr(otherbuf, buffer, buflen);
	sfree(otherbuf);
	return buffer;
    } else {
	sfree(otherbuf);
	return NULL;
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340

    len = 1 + strlen(key);

    /*
     * Now read a saved key in from the registry and see what it
     * says.
     */
    otherstr = smalloc(len);
    regname = smalloc(3 * (strlen(hostname) + strlen(keytype)) + 15);

    hostkey_regname(regname, hostname, port, keytype);

    if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
		   &rkey) != ERROR_SUCCESS)
	return 1;		       /* key does not exist in registry */

    readlen = len;
    ret = RegQueryValueEx(rkey, regname, NULL, &type, otherstr, &readlen);

    if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA &&
	!strcmp(keytype, "rsa")) {
	/*
	 * Key didn't exist. If the key type is RSA, we'll try
	 * another trick, which is to look up the _old_ key format
	 * under just the hostname and translate that.
	 */
	char *justhost = regname + 1 + strcspn(regname, ":");
	char *oldstyle = smalloc(len + 10);	/* safety margin */
	readlen = len;
	ret = RegQueryValueEx(rkey, justhost, NULL, &type,
			      oldstyle, &readlen);

	if (ret == ERROR_SUCCESS && type == REG_SZ) {
	    /*
	     * The old format is two old-style bignums separated by







|
|


















|







306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340

    len = 1 + strlen(key);

    /*
     * Now read a saved key in from the registry and see what it
     * says.
     */
    otherstr = snewn(len, char);
    regname = snewn(3 * (strlen(hostname) + strlen(keytype)) + 15, char);

    hostkey_regname(regname, hostname, port, keytype);

    if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
		   &rkey) != ERROR_SUCCESS)
	return 1;		       /* key does not exist in registry */

    readlen = len;
    ret = RegQueryValueEx(rkey, regname, NULL, &type, otherstr, &readlen);

    if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA &&
	!strcmp(keytype, "rsa")) {
	/*
	 * Key didn't exist. If the key type is RSA, we'll try
	 * another trick, which is to look up the _old_ key format
	 * under just the hostname and translate that.
	 */
	char *justhost = regname + 1 + strcspn(regname, ":");
	char *oldstyle = snewn(len + 10, char);	/* safety margin */
	readlen = len;
	ret = RegQueryValueEx(rkey, justhost, NULL, &type,
			      oldstyle, &readlen);

	if (ret == ERROR_SUCCESS && type == REG_SZ) {
	    /*
	     * The old format is two old-style bignums separated by
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416

void store_host_key(const char *hostname, int port,
		    const char *keytype, const char *key)
{
    char *regname;
    HKEY rkey;

    regname = smalloc(3 * (strlen(hostname) + strlen(keytype)) + 15);

    hostkey_regname(regname, hostname, port, keytype);

    if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
		     &rkey) != ERROR_SUCCESS)
	return;			       /* key does not exist in registry */
    RegSetValueEx(rkey, regname, 0, REG_SZ, key, strlen(key) + 1);







|







402
403
404
405
406
407
408
409
410
411
412
413
414
415
416

void store_host_key(const char *hostname, int port,
		    const char *keytype, const char *key)
{
    char *regname;
    HKEY rkey;

    regname = snewn(3 * (strlen(hostname) + strlen(keytype)) + 15, char);

    hostkey_regname(regname, hostname, port, keytype);

    if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
		     &rkey) != ERROR_SUCCESS)
	return;			       /* key does not exist in registry */
    RegSetValueEx(rkey, regname, 0, REG_SZ, key, strlen(key) + 1);
Changes to winutils.c.
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
	return;
    }

    /*
     * This will guaranteeably be big enough; we can realloc it
     * down later.
     */
    outputline = smalloc(1+strlen(cmdline));
    outputargv = smalloc(sizeof(char *) * (strlen(cmdline)+1 / 2));
    outputargstart = smalloc(sizeof(char *) * (strlen(cmdline)+1 / 2));

    p = cmdline; q = outputline; outputargc = 0;

    while (*p) {
	int quote;

	/* Skip whitespace searching for start of argument. */







|
|
|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
	return;
    }

    /*
     * This will guaranteeably be big enough; we can realloc it
     * down later.
     */
    outputline = snewn(1+strlen(cmdline), char);
    outputargv = snewn(strlen(cmdline)+1 / 2, char *);
    outputargstart = snewn(strlen(cmdline)+1 / 2, char *);

    p = cmdline; q = outputline; outputargc = 0;

    while (*p) {
	int quote;

	/* Skip whitespace searching for start of argument. */
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
	    }
	}

	/* At the end of an argument, just append a trailing NUL. */
	*q++ = '\0';
    }

    outputargv = srealloc(outputargv, sizeof(char *) * outputargc);
    outputargstart = srealloc(outputargstart, sizeof(char *) * outputargc);

    if (argc) *argc = outputargc;
    if (argv) *argv = outputargv; else sfree(outputargv);
    if (argstart) *argstart = outputargstart; else sfree(outputargstart);
}

#ifdef TESTMODE







|
|







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
	    }
	}

	/* At the end of an argument, just append a trailing NUL. */
	*q++ = '\0';
    }

    outputargv = sresize(outputargv, outputargc, char *);
    outputargstart = sresize(outputargstart, outputargc, char *);

    if (argc) *argc = outputargc;
    if (argv) *argv = outputargv; else sfree(outputargv);
    if (argstart) *argstart = outputargstart; else sfree(outputargstart);
}

#ifdef TESTMODE
Changes to x11fwd.c.
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    void *c;			       /* data used by ssh.c */
    Socket s;
};

void *x11_invent_auth(char *proto, int protomaxlen,
		      char *data, int datamaxlen, int proto_id)
{
    struct X11Auth *auth = smalloc(sizeof(struct X11Auth));
    char ourdata[64];
    int i;

    if (proto_id == X11_MIT) {
	auth->fakeproto = X11_MIT;

	/* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    void *c;			       /* data used by ssh.c */
    Socket s;
};

void *x11_invent_auth(char *proto, int protomaxlen,
		      char *data, int datamaxlen, int proto_id)
{
    struct X11Auth *auth = snew(struct X11Auth);
    char ourdata[64];
    int i;

    if (proto_id == X11_MIT) {
	auth->fakeproto = X11_MIT;

	/* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
    addr = name_lookup(host, port, &dummy_realhost, cfg);
    if ((err = sk_addr_error(addr)) != NULL)
	return err;

    /*
     * Open socket.
     */
    pr = (struct X11Private *) smalloc(sizeof(struct X11Private));
    pr->fn = &fn_table;
    pr->auth_protocol = NULL;
    pr->auth = (struct X11Auth *)auth;
    pr->verified = 0;
    pr->data_read = 0;
    pr->throttled = pr->throttle_override = 0;
    pr->c = c;







|







278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
    addr = name_lookup(host, port, &dummy_realhost, cfg);
    if ((err = sk_addr_error(addr)) != NULL)
	return err;

    /*
     * Open socket.
     */
    pr = snew(struct X11Private);
    pr->fn = &fn_table;
    pr->auth_protocol = NULL;
    pr->auth = (struct X11Auth *)auth;
    pr->verified = 0;
    pr->data_read = 0;
    pr->throttled = pr->throttle_override = 0;
    pr->c = c;
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
     */
    if (!pr->auth_protocol) {
	pr->auth_plen = GET_16BIT(pr->firstpkt[0], pr->firstpkt + 6);
	pr->auth_dlen = GET_16BIT(pr->firstpkt[0], pr->firstpkt + 8);
	pr->auth_psize = (pr->auth_plen + 3) & ~3;
	pr->auth_dsize = (pr->auth_dlen + 3) & ~3;
	/* Leave room for a terminating zero, to make our lives easier. */
	pr->auth_protocol = (char *) smalloc(pr->auth_psize + 1);
	pr->auth_data = (unsigned char *) smalloc(pr->auth_dsize);
    }

    /*
     * Read the auth_protocol and auth_data strings.
     */
    while (len > 0 && pr->data_read < 12 + pr->auth_psize)
	pr->auth_protocol[pr->data_read++ - 12] = (len--, *data++);







|
|







380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
     */
    if (!pr->auth_protocol) {
	pr->auth_plen = GET_16BIT(pr->firstpkt[0], pr->firstpkt + 6);
	pr->auth_dlen = GET_16BIT(pr->firstpkt[0], pr->firstpkt + 8);
	pr->auth_psize = (pr->auth_plen + 3) & ~3;
	pr->auth_dsize = (pr->auth_dlen + 3) & ~3;
	/* Leave room for a terminating zero, to make our lives easier. */
	pr->auth_protocol = snewn(pr->auth_psize + 1, char);
	pr->auth_data = snewn(pr->auth_dsize, char);
    }

    /*
     * Read the auth_protocol and auth_data strings.
     */
    while (len > 0 && pr->data_read < 12 + pr->auth_psize)
	pr->auth_protocol[pr->data_read++ - 12] = (len--, *data++);
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
	if (err) {
	    char *message;
	    int msglen, msgsize;
	    unsigned char *reply;

	    message = dupprintf("PuTTY X11 proxy: %s", err);
	    msglen = strlen(message);
	    reply = smalloc(8 + msglen+1 + 4);   /* include zero byte */
	    msgsize = (msglen + 3) & ~3;
	    reply[0] = 0;	       /* failure */
	    reply[1] = msglen;	       /* length of reason string */
	    memcpy(reply + 2, pr->firstpkt + 2, 4);	/* major/minor proto vsn */
	    PUT_16BIT(pr->firstpkt[0], reply + 6, msgsize >> 2);/* data len */
	    memset(reply + 8, 0, msgsize);
	    memcpy(reply + 8, message, msglen);







|







417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
	if (err) {
	    char *message;
	    int msglen, msgsize;
	    unsigned char *reply;

	    message = dupprintf("PuTTY X11 proxy: %s", err);
	    msglen = strlen(message);
	    reply = snewn(8 + msglen+1 + 4, unsigned char); /* include zero */
	    msgsize = (msglen + 3) & ~3;
	    reply[0] = 0;	       /* failure */
	    reply[1] = msglen;	       /* length of reason string */
	    memcpy(reply + 2, pr->firstpkt + 2, 4);	/* major/minor proto vsn */
	    PUT_16BIT(pr->firstpkt[0], reply + 6, msgsize >> 2);/* data len */
	    memset(reply + 8, 0, msgsize);
	    memcpy(reply + 8, message, msglen);