9
9
#include "storage.h"
10
10
11
11
/* The cipher order given here is the default order. */
12
- static const struct keyval ciphernames [] = {
13
- { "aes" , CIPHER_AES },
14
- { "blowfish" , CIPHER_BLOWFISH },
15
- { "3des" , CIPHER_3DES },
16
- { "WARN" , CIPHER_WARN },
17
- { "arcfour" , CIPHER_ARCFOUR },
18
- { "des" , CIPHER_DES }
12
+ static const struct keyvalwhere ciphernames [] = {
13
+ { "aes" , CIPHER_AES , -1 , -1 },
14
+ { "blowfish" , CIPHER_BLOWFISH , -1 , -1 },
15
+ { "3des" , CIPHER_3DES , -1 , -1 },
16
+ { "WARN" , CIPHER_WARN , -1 , -1 },
17
+ { "arcfour" , CIPHER_ARCFOUR , -1 , -1 },
18
+ { "des" , CIPHER_DES , -1 , -1 }
19
19
};
20
20
21
- static const struct keyval kexnames [] = {
22
- { "dh-gex-sha1" , KEX_DHGEX },
23
- { "dh-group14-sha1" , KEX_DHGROUP14 },
24
- { "dh-group1-sha1" , KEX_DHGROUP1 },
25
- { "rsa" , KEX_RSA },
26
- { "WARN" , KEX_WARN }
21
+ static const struct keyvalwhere kexnames [] = {
22
+ { "dh-gex-sha1" , KEX_DHGEX , -1 , -1 },
23
+ { "dh-group14-sha1" , KEX_DHGROUP14 , -1 , -1 },
24
+ { "dh-group1-sha1" , KEX_DHGROUP1 , -1 , -1 },
25
+ { "rsa" , KEX_RSA , KEX_WARN , -1 },
26
+ { "WARN" , KEX_WARN , -1 , -1 }
27
27
};
28
28
29
29
/*
@@ -188,15 +188,17 @@ static void wmap(void *handle, char const *key, char const *value, int len)
188
188
sfree (buf );
189
189
}
190
190
191
- static int key2val (const struct keyval * mapping , int nmaps , char * key )
191
+ static int key2val (const struct keyvalwhere * mapping ,
192
+ int nmaps , char * key )
192
193
{
193
194
int i ;
194
195
for (i = 0 ; i < nmaps ; i ++ )
195
196
if (!strcmp (mapping [i ].s , key )) return mapping [i ].v ;
196
197
return -1 ;
197
198
}
198
199
199
- static const char * val2key (const struct keyval * mapping , int nmaps , int val )
200
+ static const char * val2key (const struct keyvalwhere * mapping ,
201
+ int nmaps , int val )
200
202
{
201
203
int i ;
202
204
for (i = 0 ; i < nmaps ; i ++ )
@@ -211,66 +213,115 @@ static const char *val2key(const struct keyval *mapping, int nmaps, int val)
211
213
* XXX: assumes vals in 'mapping' are small +ve integers
212
214
*/
213
215
static void gprefs (void * sesskey , char * name , char * def ,
214
- const struct keyval * mapping , int nvals ,
216
+ const struct keyvalwhere * mapping , int nvals ,
215
217
int * array )
216
218
{
217
- char commalist [80 ];
218
- char * tokarg = commalist ;
219
- int n ;
219
+ char commalist [256 ];
220
+ char * p , * q ;
221
+ int i , j , n , v , pos ;
220
222
unsigned long seen = 0 ; /* bitmap for weeding dups etc */
223
+
224
+ /*
225
+ * Fetch the string which we'll parse as a comma-separated list.
226
+ */
221
227
gpps (sesskey , name , def , commalist , sizeof (commalist ));
222
228
223
- /* Grotty parsing of commalist. */
229
+ /*
230
+ * Go through that list and convert it into values.
231
+ */
224
232
n = 0 ;
225
- do {
226
- int v ;
227
- char * key ;
228
- key = strtok (tokarg , "," ); /* sorry */
229
- tokarg = NULL ;
230
- if (!key ) break ;
231
- if (((v = key2val (mapping , nvals , key )) != -1 ) &&
232
- !(seen & 1 <<v )) {
233
- array [n ] = v ;
234
- n ++ ;
235
- seen |= 1 <<v ;
233
+ p = commalist ;
234
+ while (1 ) {
235
+ while (* p && * p == ',' ) p ++ ;
236
+ if (!* p )
237
+ break ; /* no more words */
238
+
239
+ q = p ;
240
+ while (* p && * p != ',' ) p ++ ;
241
+ if (* p ) * p ++ = '\0' ;
242
+
243
+ v = key2val (mapping , nvals , q );
244
+ if (v != -1 && !(seen & (1 << v ))) {
245
+ seen |= (1 << v );
246
+ array [n ++ ] = v ;
236
247
}
237
- } while (n < nvals );
238
- /* Add any missing values (backward compatibility ect). */
239
- {
240
- int i ;
241
- for (i = 0 ; i < nvals ; i ++ ) {
248
+ }
249
+
250
+ /*
251
+ * Now go through 'mapping' and add values that weren't mentioned
252
+ * in the list we fetched. We may have to loop over it multiple
253
+ * times so that we add values before other values whose default
254
+ * positions depend on them.
255
+ */
256
+ while (n < nvals ) {
257
+ for (i = 0 ; i < nvals ; i ++ ) {
242
258
assert (mapping [i ].v < 32 );
243
- if (!(seen & 1 <<mapping [i ].v )) {
244
- array [n ] = mapping [i ].v ;
245
- n ++ ;
246
- }
247
- }
259
+
260
+ if (!(seen & (1 << mapping [i ].v ))) {
261
+ /*
262
+ * This element needs adding. But can we add it yet?
263
+ */
264
+ if (mapping [i ].vrel != -1 && !(seen & (1 << mapping [i ].vrel )))
265
+ continue ; /* nope */
266
+
267
+ /*
268
+ * OK, we can work out where to add this element, so
269
+ * do so.
270
+ */
271
+ if (mapping [i ].vrel == -1 ) {
272
+ pos = (mapping [i ].where < 0 ? n : 0 );
273
+ } else {
274
+ for (j = 0 ; j < n ; j ++ )
275
+ if (array [j ] == mapping [i ].vrel )
276
+ break ;
277
+ assert (j < n ); /* implied by (seen & (1<<vrel)) */
278
+ pos = (mapping [i ].where < 0 ? j : j + 1 );
279
+ }
280
+
281
+ /*
282
+ * And add it.
283
+ */
284
+ for (j = n - 1 ; j >= pos ; j -- )
285
+ array [j + 1 ] = array [j ];
286
+ array [pos ] = mapping [i ].v ;
287
+ n ++ ;
288
+ }
289
+ }
248
290
}
249
291
}
250
292
251
293
/*
252
294
* Write out a preference list.
253
295
*/
254
296
static void wprefs (void * sesskey , char * name ,
255
- const struct keyval * mapping , int nvals ,
297
+ const struct keyvalwhere * mapping , int nvals ,
256
298
int * array )
257
299
{
258
- char buf [ 80 ] = "" ; /* XXX assumed big enough */
259
- int l = sizeof ( buf ) - 1 , i ;
260
- buf [ l ] = '\0' ;
261
- for (i = 0 ; l > 0 && i < nvals ; i ++ ) {
300
+ char * buf , * p ;
301
+ int i , maxlen ;
302
+
303
+ for (maxlen = i = 0 ; i < nvals ; i ++ ) {
262
304
const char * s = val2key (mapping , nvals , array [i ]);
263
305
if (s ) {
264
- int sl = strlen (s );
265
- if (i > 0 ) {
266
- strncat (buf , "," , l );
267
- l -- ;
268
- }
269
- strncat (buf , s , l );
270
- l -= sl ;
306
+ maxlen += 1 + strlen (s );
307
+ }
308
+ }
309
+
310
+ buf = snewn (maxlen , char );
311
+ p = buf ;
312
+
313
+ for (i = 0 ; i < nvals ; i ++ ) {
314
+ const char * s = val2key (mapping , nvals , array [i ]);
315
+ if (s ) {
316
+ p += sprintf (p , "%s%s" , (p > buf ? "," : "" ), s );
271
317
}
272
318
}
319
+
320
+ assert (p - buf == maxlen - 1 ); /* maxlen counted the NUL */
321
+
273
322
write_setting_s (sesskey , name , buf );
323
+
324
+ sfree (buf );
274
325
}
275
326
276
327
char * save_settings (char * section , Config * cfg )
0 commit comments