From Balint Reczey:
[obnox/wireshark/wip.git] / epan / prefs.c
1 /* prefs.c
2  * Routines for handling preferences
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <errno.h>
33
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include <glib.h>
39
40 #include <epan/filesystem.h>
41 #include <epan/address.h>
42 #include <epan/addr_resolv.h>
43 #include <epan/packet.h>
44 #include <epan/prefs.h>
45 #include <epan/proto.h>
46 #include "cfile.h"
47 #include <epan/column.h>
48 #include "print.h"
49 #include <wsutil/file_util.h>
50
51 #include <epan/prefs-int.h>
52 #include <epan/uat-int.h>
53
54 /* Internal functions */
55 static module_t *find_subtree(module_t *parent, const char *tilte);
56 static module_t *prefs_register_module_or_subtree(module_t *parent,
57     const char *name, const char *title, const char *description, gboolean is_subtree,
58     void (*apply_cb)(void));
59 static struct preference *find_preference(module_t *, const char *);
60 static prefs_set_pref_e set_pref(gchar*, gchar*, void *);
61 static gchar *put_string_list(GList *);
62 static void   free_col_info(e_prefs *);
63
64 #define PF_NAME         "preferences"
65 #define OLD_GPF_NAME    "wireshark.conf"        /* old name for global preferences file */
66
67 static gboolean prefs_initialized = FALSE;
68 static gchar *gpf_path = NULL;
69
70 /*
71  * XXX - variables to allow us to attempt to interpret the first
72  * "mgcp.{tcp,udp}.port" in a preferences file as
73  * "mgcp.{tcp,udp}.gateway_port" and the second as
74  * "mgcp.{tcp,udp}.callagent_port".
75  */
76 static int mgcp_tcp_port_count;
77 static int mgcp_udp_port_count;
78
79 e_prefs prefs;
80
81 static const gchar      *gui_ptree_line_style_text[] =
82         { "NONE", "SOLID", "DOTTED", "TABBED", NULL };
83
84 static const gchar      *gui_ptree_expander_style_text[] =
85         { "NONE", "SQUARE", "TRIANGLE", "CIRCULAR", NULL };
86
87 static const gchar      *gui_hex_dump_highlight_style_text[] =
88         { "BOLD", "INVERSE", NULL };
89
90 static const gchar      *gui_console_open_text[] =
91         { "NEVER", "AUTOMATIC", "ALWAYS", NULL };
92
93 static const gchar      *gui_fileopen_style_text[] =
94         { "LAST_OPENED", "SPECIFIED", NULL };
95
96 /* GTK knows of two ways representing "both", vertical and horizontal aligned.
97  * as this may not work on other guis, we use only "both" in general here */
98 static const gchar      *gui_toolbar_style_text[] =
99         { "ICONS", "TEXT", "BOTH", NULL };
100
101 static const gchar      *gui_layout_content_text[] =
102         { "NONE", "PLIST", "PDETAILS", "PBYTES", NULL };
103
104 /*
105  * List of all modules with preference settings.
106  */
107 static emem_tree_t *prefs_modules = NULL;
108
109 /*
110  * List of all modules that should show up at the top level of the
111  * tree in the preference dialog box.
112  */
113 static emem_tree_t *prefs_top_level_modules = NULL;
114
115 /** Sets up memory used by proto routines. Called at program startup */
116 void prefs_init(void)
117 {
118   prefs_modules = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK, "prefs_modules");
119   prefs_top_level_modules = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK, "prefs_top_level_modules");
120 }
121
122 /** Frees memory used by proto routines. Called at program shutdown */
123 void prefs_cleanup(void)
124 {
125 }
126
127 /*
128  * Register a module that will have preferences.
129  * Specify the module under which to register it or NULL to register it
130  * at the top level, the name used for the module in the preferences file,
131  * the title used in the tab for it in a preferences dialog box, and a
132  * routine to call back when we apply the preferences.
133  */
134 module_t *
135 prefs_register_module(module_t *parent, const char *name, const char *title,
136     const char *description, void (*apply_cb)(void))
137 {
138         return prefs_register_module_or_subtree(parent, name, title, description,
139             FALSE, apply_cb);
140 }
141
142 /*
143  * Register a subtree that will have modules under it.
144  * Specify the module under which to register it or NULL to register it
145  * at the top level and the title used in the tab for it in a preferences
146  * dialog box.
147  */
148 module_t *
149 prefs_register_subtree(module_t *parent, const char *title, const char *description)
150 {
151         return prefs_register_module_or_subtree(parent, NULL, title, description, TRUE,
152             NULL);
153 }
154
155 static module_t *
156 prefs_register_module_or_subtree(module_t *parent, const char *name,
157     const char *title, const char *description, gboolean is_subtree, void (*apply_cb)(void))
158 {
159         module_t *module;
160         const char *p;
161         guchar c;
162
163         /* this module may have been created as a subtree item previously */
164         if((module = find_subtree(parent, title))) {
165           /* the module is currently a subtree */
166           module->name = name;
167           module->apply_cb = apply_cb;
168           module->description = description;
169
170           if (prefs_find_module(name) == NULL) {
171                 pe_tree_insert_string(prefs_modules, name, module, EMEM_TREE_STRING_NOCASE);
172           }
173
174           return module;
175         }
176
177         module = g_malloc(sizeof (module_t));
178         module->name = name;
179         module->title = title;
180         module->description = description;
181         module->apply_cb = apply_cb;
182         module->prefs = NULL;   /* no preferences, to start */
183         module->submodules = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK, "prefs_submodules");
184         module->numprefs = 0;
185         module->prefs_changed = FALSE;
186         module->obsolete = FALSE;
187
188         /*
189          * Do we have a module name?
190          */
191         if (name != NULL) {
192                 /*
193                  * Yes.
194                  * Make sure that only lower-case ASCII letters, numbers,
195                  * underscores, hyphens, and dots appear in the name.
196                  *
197                  * Crash if there is, as that's an error in the code;
198                  * you can make the title a nice string with capitalization,
199                  * white space, punctuation, etc., but the name can be used
200                  * on the command line, and shouldn't require quoting,
201                  * shifting, etc.
202                  */
203                 for (p = name; (c = *p) != '\0'; p++)
204                         g_assert(isascii(c) &&
205                             (islower(c) || isdigit(c) || c == '_' ||
206                              c == '-' || c == '.'));
207
208                 /*
209                  * Make sure there's not already a module with that
210                  * name.  Crash if there is, as that's an error in the
211                  * code, and the code has to be fixed not to register
212                  * more than one module with the same name.
213                  *
214                  * We search the list of all modules; the subtree stuff
215                  * doesn't require preferences in subtrees to have names
216                  * that reflect the subtree they're in (that would require
217                  * protocol preferences to have a bogus "protocol.", or
218                  * something such as that, to be added to all their names).
219                  */
220                 g_assert(prefs_find_module(name) == NULL);
221
222                 /*
223                  * Insert this module in the list of all modules.
224                  */
225                 pe_tree_insert_string(prefs_modules, name, module, EMEM_TREE_STRING_NOCASE);
226         } else {
227                 /*
228                  * This has no name, just a title; check to make sure it's a
229                  * subtree, and crash if it's not.
230                  */
231                 g_assert(is_subtree);
232         }
233
234         /*
235          * Insert this module into the appropriate place in the display
236          * tree.
237          */
238         if (parent == NULL) {
239                 /*
240                  * It goes at the top.
241                  */
242                 pe_tree_insert_string(prefs_top_level_modules, title, module, EMEM_TREE_STRING_NOCASE);
243         } else {
244                 /*
245                  * It goes into the list for this module.
246                  */
247                 pe_tree_insert_string(parent->submodules, title, module, EMEM_TREE_STRING_NOCASE);
248         }
249
250         return module;
251 }
252
253 /*
254  * Register that a protocol has preferences.
255  */
256 module_t *protocols_module;
257
258 module_t *
259 prefs_register_protocol(int id, void (*apply_cb)(void))
260 {
261         protocol_t *protocol;
262
263         /*
264          * Have we yet created the "Protocols" subtree?
265          */
266         if (protocols_module == NULL) {
267                 /*
268                  * No.  Do so.
269                  */
270                 protocols_module = prefs_register_subtree(NULL, "Protocols", NULL);
271         }
272         protocol = find_protocol_by_id(id);
273         return prefs_register_module(protocols_module,
274             proto_get_protocol_filter_name(id),
275             proto_get_protocol_short_name(protocol),
276             proto_get_protocol_name(id), apply_cb);
277 }
278
279
280 module_t *
281 prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
282 {
283         protocol_t *protocol;
284         module_t   *subtree_module;
285         module_t   *new_module;
286         char       *sep = NULL, *ptr = NULL;
287         char       *csubtree = NULL;
288
289         /*
290          * Have we yet created the "Protocols" subtree?
291          */
292         if (protocols_module == NULL) {
293                 /*
294                  * No.  Do so.
295                  */
296                 protocols_module = prefs_register_subtree(NULL, "Protocols", NULL);
297         }
298
299         subtree_module = protocols_module;
300
301         if(subtree) {
302           /* take a copy of the buffer */
303           ptr = csubtree = g_strdup(subtree);
304
305           while(ptr && *ptr) {
306
307             if((sep = strchr(ptr, '/')))
308               *sep++ = '\0';
309
310             if(!(new_module = find_subtree(subtree_module, ptr))) {
311               /* create it */
312               new_module = prefs_register_subtree(subtree_module, ptr, NULL);
313             }
314
315             subtree_module = new_module;
316             ptr = sep;
317
318           }
319
320           /* g_free(csubtree); */
321
322         }
323
324         protocol = find_protocol_by_id(id);
325         return prefs_register_module(subtree_module,
326             proto_get_protocol_filter_name(id),
327             proto_get_protocol_short_name(protocol),
328             proto_get_protocol_name(id), apply_cb);
329 }
330
331
332 /*
333  * Register that a protocol used to have preferences but no longer does,
334  * by creating an "obsolete" module for it.
335  */
336 module_t *
337 prefs_register_protocol_obsolete(int id)
338 {
339         module_t *module;
340         protocol_t *protocol;
341
342         /*
343          * Have we yet created the "Protocols" subtree?
344          */
345         if (protocols_module == NULL) {
346                 /*
347                  * No.  Do so.
348                  */
349                 protocols_module = prefs_register_subtree(NULL, "Protocols", NULL);
350         }
351         protocol = find_protocol_by_id(id);
352         module = prefs_register_module(protocols_module,
353             proto_get_protocol_filter_name(id),
354             proto_get_protocol_short_name(protocol),
355             proto_get_protocol_name(id), NULL);
356         module->obsolete = TRUE;
357         return module;
358 }
359
360 module_t *
361 prefs_find_module(const char *name)
362 {
363         return pe_tree_lookup_string(prefs_modules, name, EMEM_TREE_STRING_NOCASE);
364 }
365
366 static module_t *
367 find_subtree(module_t *parent, const char *name)
368 {
369         return pe_tree_lookup_string(parent ? parent->submodules : prefs_top_level_modules, name, EMEM_TREE_STRING_NOCASE);
370 }
371
372 /*
373  * Call a callback function, with a specified argument, for each module
374  * in a list of modules.  If the list is NULL, searches the top-level
375  * list in the display tree of modules.  If any callback returns a
376  * non-zero value, we stop and return that value, otherwise we
377  * return 0.
378  *
379  * Ignores "obsolete" modules; their sole purpose is to allow old
380  * preferences for dissectors that no longer have preferences to be
381  * silently ignored in preference files.  Does not ignore subtrees,
382  * as this can be used when walking the display tree of modules.
383  */
384
385 typedef struct {
386         module_cb callback;
387         gpointer user_data;
388         guint ret;
389 } call_foreach_t;
390
391 static gboolean
392 call_foreach_cb(void *value, void *data)
393 {
394         module_t *module = (module_t*)value;
395         call_foreach_t *call_data = (call_foreach_t*)data;
396
397         if (!module->obsolete) {
398                 call_data->ret = (*call_data->callback)(module, call_data->user_data);
399         }
400         return (call_data->ret != 0);
401 }
402
403 static guint
404 prefs_module_list_foreach(emem_tree_t *module_list, module_cb callback,
405     gpointer user_data)
406 {
407         call_foreach_t call_data;
408
409         if (module_list == NULL)
410                 module_list = prefs_top_level_modules;
411
412         call_data.callback = callback;
413         call_data.user_data = user_data;
414         call_data.ret = 0;
415         pe_tree_foreach(module_list, call_foreach_cb, &call_data);
416         return call_data.ret;
417 }
418
419 /*
420  * Returns TRUE if module has any submodules
421  */
422 gboolean prefs_module_has_submodules(module_t *module)
423 {
424         if (module->submodules == NULL) {
425                 return FALSE;
426         }
427
428         if (module->submodules->tree == NULL) {
429                 return FALSE;
430         }
431
432         return TRUE;
433 }
434
435 /*
436  * Call a callback function, with a specified argument, for each module
437  * in the list of all modules.  (This list does not include subtrees.)
438  *
439  * Ignores "obsolete" modules; their sole purpose is to allow old
440  * preferences for dissectors that no longer have preferences to be
441  * silently ignored in preference files.
442  */
443 guint
444 prefs_modules_foreach(module_cb callback, gpointer user_data)
445 {
446         return prefs_module_list_foreach(prefs_modules, callback, user_data);
447 }
448
449 /*
450  * Call a callback function, with a specified argument, for each submodule
451  * of specified modules.  If the module is NULL, goes through the top-level
452  * list in the display tree of modules.
453  *
454  * Ignores "obsolete" modules; their sole purpose is to allow old
455  * preferences for dissectors that no longer have preferences to be
456  * silently ignored in preference files.  Does not ignore subtrees,
457  * as this can be used when walking the display tree of modules.
458  */
459 guint
460 prefs_modules_foreach_submodules(module_t *module, module_cb callback, gpointer user_data)
461 {
462         return prefs_module_list_foreach((module)?module->submodules:prefs_top_level_modules, callback, user_data);
463 }
464
465 static gboolean
466 call_apply_cb(void *value, void *data _U_)
467 {
468         module_t *module = value;
469
470         if (module->obsolete)
471                 return FALSE;
472         if (module->prefs_changed) {
473                 if (module->apply_cb != NULL)
474                         (*module->apply_cb)();
475                 module->prefs_changed = FALSE;
476         }
477         return FALSE;
478 }
479
480 /*
481  * Call the "apply" callback function for each module if any of its
482  * preferences have changed, and then clear the flag saying its
483  * preferences have changed, as the module has been notified of that
484  * fact.
485  */
486 void
487 prefs_apply_all(void)
488 {
489         pe_tree_foreach(prefs_modules, call_apply_cb, NULL);
490 }
491
492 /*
493  * Call the "apply" callback function for a specific module if any of
494  * its preferences have changed, and then clear the flag saying its
495  * preferences have changed, as the module has been notified of that
496  * fact.
497  */
498 void
499 prefs_apply(module_t *module)
500 {
501         if (module && module->prefs_changed)
502                 call_apply_cb(module, NULL);
503 }
504
505 /*
506  * Register a preference in a module's list of preferences.
507  * If it has a title, give it an ordinal number; otherwise, it's a
508  * preference that won't show up in the UI, so it shouldn't get an
509  * ordinal number (the ordinal should be the ordinal in the set of
510  * *visible* preferences).
511  */
512 static pref_t *
513 register_preference(module_t *module, const char *name, const char *title,
514     const char *description, pref_type_t type)
515 {
516         pref_t *preference;
517         const gchar *p;
518
519         preference = g_malloc(sizeof (pref_t));
520         preference->name = name;
521         preference->title = title;
522         preference->description = description;
523         preference->type = type;
524         if (title != NULL)
525                 preference->ordinal = module->numprefs;
526         else
527                 preference->ordinal = -1;       /* no ordinal for you */
528
529         /*
530          * Make sure that only lower-case ASCII letters, numbers,
531          * underscores, and dots appear in the preference name.
532          *
533          * Crash if there is, as that's an error in the code;
534          * you can make the title and description nice strings
535          * with capitalization, white space, punctuation, etc.,
536          * but the name can be used on the command line,
537          * and shouldn't require quoting, shifting, etc.
538          */
539         for (p = name; *p != '\0'; p++)
540                 g_assert(isascii((guchar)*p) &&
541                     (islower((guchar)*p) || isdigit((guchar)*p) || *p == '_' || *p == '.'));
542
543         /*
544          * Make sure there's not already a preference with that
545          * name.  Crash if there is, as that's an error in the
546          * code, and the code has to be fixed not to register
547          * more than one preference with the same name.
548          */
549         g_assert(find_preference(module, name) == NULL);
550
551         if (type != PREF_OBSOLETE) {
552                 /*
553                  * Make sure the preference name doesn't begin with the
554                  * module name, as that's redundant and Just Silly.
555                  */
556                 g_assert((strncmp(name, module->name, strlen(module->name)) != 0) ||
557                         (((name[strlen(module->name)]) != '.') && ((name[strlen(module->name)]) != '_')));
558         }
559
560         /*
561          * There isn't already one with that name, so add the
562          * preference.
563          */
564         module->prefs = g_list_append(module->prefs, preference);
565         if (title != NULL)
566                 module->numprefs++;
567
568         return preference;
569 }
570
571 /*
572  * Find a preference in a module's list of preferences, given the module
573  * and the preference's name.
574  */
575 static gint
576 preference_match(gconstpointer a, gconstpointer b)
577 {
578         const pref_t *pref = a;
579         const char *name = b;
580
581         return strcmp(name, pref->name);
582 }
583
584 static struct preference *
585 find_preference(module_t *module, const char *name)
586 {
587         GList *list_entry;
588
589         list_entry = g_list_find_custom(module->prefs, name,
590             preference_match);
591
592         if (list_entry == NULL)
593                 return NULL;    /* no such preference */
594         return (struct preference *) list_entry->data;
595 }
596
597 /*
598  * Returns TRUE if the given protocol has registered preferences
599  */
600 gboolean
601 prefs_is_registered_protocol(const char *name)
602 {
603         module_t *m = prefs_find_module(name);
604
605         return (m != NULL && !m->obsolete);
606 }
607
608 /*
609  * Returns the module title of a registered protocol
610  */
611 const char *
612 prefs_get_title_by_name(const char *name)
613 {
614         module_t *m = prefs_find_module(name);
615
616         return (m != NULL && !m->obsolete) ? m->title : NULL;
617 }
618
619 /*
620  * Register a preference with an unsigned integral value.
621  */
622 void
623 prefs_register_uint_preference(module_t *module, const char *name,
624     const char *title, const char *description, guint base, guint *var)
625 {
626         pref_t *preference;
627
628         preference = register_preference(module, name, title, description,
629             PREF_UINT);
630         preference->varp.uint = var;
631         g_assert(base > 0 && base != 1 && base < 37);
632         preference->info.base = base;
633 }
634
635 /*
636  * Register a preference with an Boolean value.
637  */
638 void
639 prefs_register_bool_preference(module_t *module, const char *name,
640     const char *title, const char *description, gboolean *var)
641 {
642         pref_t *preference;
643
644         preference = register_preference(module, name, title, description,
645             PREF_BOOL);
646         preference->varp.boolp = var;
647 }
648
649 /*
650  * Register a preference with an enumerated value.
651  */
652 void
653 prefs_register_enum_preference(module_t *module, const char *name,
654     const char *title, const char *description, gint *var,
655     const enum_val_t *enumvals, gboolean radio_buttons)
656 {
657         pref_t *preference;
658
659         preference = register_preference(module, name, title, description,
660             PREF_ENUM);
661         preference->varp.enump = var;
662         preference->info.enum_info.enumvals = enumvals;
663         preference->info.enum_info.radio_buttons = radio_buttons;
664 }
665
666 /*
667  * Register a preference with a character-string value.
668  */
669 void
670 prefs_register_string_preference(module_t *module, const char *name,
671     const char *title, const char *description, const char **var)
672 {
673         pref_t *preference;
674
675         preference = register_preference(module, name, title, description,
676             PREF_STRING);
677
678         /*
679          * String preference values should be non-null (as you can't
680          * keep them null after using the preferences GUI, you can at best
681          * have them be null strings) and freeable (as we free them
682          * if we change them).
683          *
684          * If the value is a null pointer, make it a copy of a null
685          * string, otherwise make it a copy of the value.
686          */
687         if (*var == NULL)
688                 *var = g_strdup("");
689         else
690                 *var = g_strdup(*var);
691         preference->varp.string = var;
692         preference->saved_val.string = NULL;
693 }
694
695 /*
696  * Register a preference with a ranged value.
697  */
698 void
699 prefs_register_range_preference(module_t *module, const char *name,
700     const char *title, const char *description, range_t **var,
701     guint32 max_value)
702 {
703         pref_t *preference;
704
705         preference = register_preference(module, name, title, description,
706                                          PREF_RANGE);
707         preference->info.max_value = max_value;
708
709
710         /*
711          * Range preference values should be non-null (as you can't
712          * keep them null after using the preferences GUI, you can at best
713          * have them be empty ranges) and freeable (as we free them
714          * if we change them).
715          *
716          * If the value is a null pointer, make it an empty range.
717          */
718         if (*var == NULL)
719                 *var = range_empty();
720         preference->varp.range = var;
721         preference->saved_val.range = NULL;
722 }
723
724 /*
725  * Register a static text 'preference'.  It can be used to add explanatory
726  * text inline with other preferences in the GUI.
727  * Note: Static preferences are not saved to the preferences file.
728  */
729 void prefs_register_static_text_preference(module_t *module, const char *name,
730     const char *title, const char *description)
731 {
732         register_preference(module, name, title, description, PREF_STATIC_TEXT);
733 }
734
735 /*
736  * Register a uat 'preference'. It adds a button that opens the uat's window in the
737  * preferences tab of the module.
738  */
739 extern void prefs_register_uat_preference(module_t *module,
740                                                                                   const char *name,
741                                                                                   const char *title,
742                                                                                   const char *description,
743                                                                                   void* uat) {
744
745         pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
746
747         preference->varp.uat = uat;
748
749 }
750
751
752
753 /*
754  * Register a preference that used to be supported but no longer is.
755  */
756 void
757 prefs_register_obsolete_preference(module_t *module, const char *name)
758 {
759         register_preference(module, name, NULL, NULL, PREF_OBSOLETE);
760 }
761
762 /*
763  * Call a callback function, with a specified argument, for each preference
764  * in a given module.
765  *
766  * If any of the callbacks return a non-zero value, stop and return that
767  * value, otherwise return 0.
768  */
769 guint
770 prefs_pref_foreach(module_t *module, pref_cb callback, gpointer user_data)
771 {
772         GList *elem;
773         pref_t *pref;
774         guint ret;
775
776         for (elem = g_list_first(module->prefs); elem != NULL;
777             elem = g_list_next(elem)) {
778                 pref = elem->data;
779                 if (pref->type == PREF_OBSOLETE) {
780                         /*
781                          * This preference is no longer supported; it's
782                          * not a real preference, so we don't call the
783                          * callback for it (i.e., we treat it as if it
784                          * weren't found in the list of preferences,
785                          * and we weren't called in the first place).
786                          */
787                         continue;
788                 }
789
790                 ret = (*callback)(pref, user_data);
791                 if (ret != 0)
792                         return ret;
793         }
794         return 0;
795 }
796
797 /*
798  * Register all non-dissector modules' preferences.
799  */
800 void
801 prefs_register_modules(void)
802 {
803 }
804
805 /* Parse through a list of comma-separated, possibly quoted strings.
806    Return a list of the string data. */
807 GList *
808 prefs_get_string_list(gchar *str)
809 {
810   enum { PRE_STRING, IN_QUOT, NOT_IN_QUOT };
811
812   gint      state = PRE_STRING, i = 0, j = 0;
813   gboolean  backslash = FALSE;
814   guchar    cur_c;
815   gchar    *slstr = NULL;
816   GList    *sl = NULL;
817
818   /* Allocate a buffer for the first string.   */
819   slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
820   j = 0;
821
822   for (;;) {
823     cur_c = str[i];
824     if (cur_c == '\0') {
825       /* It's the end of the input, so it's the end of the string we
826          were working on, and there's no more input. */
827       if (state == IN_QUOT || backslash) {
828         /* We were in the middle of a quoted string or backslash escape,
829            and ran out of characters; that's an error.  */
830         g_free(slstr);
831         prefs_clear_string_list(sl);
832         return NULL;
833       }
834       slstr[j] = '\0';
835       sl = g_list_append(sl, slstr);
836       break;
837     }
838     if (cur_c == '"' && ! backslash) {
839       switch (state) {
840         case PRE_STRING:
841           /* We hadn't yet started processing a string; this starts the
842              string, and we're now quoting.  */
843           state = IN_QUOT;
844           break;
845         case IN_QUOT:
846           /* We're in the middle of a quoted string, and we saw a quotation
847              mark; we're no longer quoting.   */
848           state = NOT_IN_QUOT;
849           break;
850         case NOT_IN_QUOT:
851           /* We're working on a string, but haven't seen a quote; we're
852              now quoting.  */
853           state = IN_QUOT;
854           break;
855         default:
856           break;
857       }
858     } else if (cur_c == '\\' && ! backslash) {
859       /* We saw a backslash, and the previous character wasn't a
860          backslash; escape the next character.
861
862          This also means we've started a new string. */
863       backslash = TRUE;
864       if (state == PRE_STRING)
865         state = NOT_IN_QUOT;
866     } else if (cur_c == ',' && state != IN_QUOT && ! backslash) {
867       /* We saw a comma, and we're not in the middle of a quoted string
868          and it wasn't preceded by a backslash; it's the end of
869          the string we were working on...  */
870       slstr[j] = '\0';
871       sl = g_list_append(sl, slstr);
872
873       /* ...and the beginning of a new string.  */
874       state = PRE_STRING;
875       slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
876       j = 0;
877     } else if (!isspace(cur_c) || state != PRE_STRING) {
878       /* Either this isn't a white-space character, or we've started a
879          string (i.e., already seen a non-white-space character for that
880          string and put it into the string).
881
882          The character is to be put into the string; do so if there's
883          room.  */
884       if (j < COL_MAX_LEN) {
885         slstr[j] = cur_c;
886         j++;
887       }
888
889       /* If it was backslash-escaped, we're done with the backslash escape.  */
890       backslash = FALSE;
891     }
892     i++;
893   }
894   return(sl);
895 }
896
897 #define MAX_FMT_PREF_LEN      1024
898 #define MAX_FMT_PREF_LINE_LEN   60
899 static gchar *
900 put_string_list(GList *sl)
901 {
902   static gchar  pref_str[MAX_FMT_PREF_LEN] = "";
903   GList        *clp = g_list_first(sl);
904   gchar        *str;
905   int           cur_pos = 0, cur_len = 0;
906   gchar        *quoted_str;
907   int           str_len;
908   gchar        *strp, *quoted_strp, c;
909   int           fmt_len;
910
911   while (clp) {
912     str = clp->data;
913
914     /* Allocate a buffer big enough to hold the entire string, with each
915        character quoted (that's the worst case).  */
916     str_len = strlen(str);
917     quoted_str = g_malloc(str_len*2 + 1);
918
919     /* Now quote any " or \ characters in it. */
920     strp = str;
921     quoted_strp = quoted_str;
922     while ((c = *strp++) != '\0') {
923       if (c == '"' || c == '\\') {
924         /* It has to be backslash-quoted.  */
925         *quoted_strp++ = '\\';
926       }
927       *quoted_strp++ = c;
928     }
929     *quoted_strp = '\0';
930
931     fmt_len = strlen(quoted_str) + 4;
932     if ((fmt_len + cur_len) < (MAX_FMT_PREF_LEN - 1)) {
933       if ((fmt_len + cur_pos) > MAX_FMT_PREF_LINE_LEN) {
934         /* Wrap the line.  */
935         cur_len--;
936         cur_pos = 0;
937         pref_str[cur_len] = '\n'; cur_len++;
938         pref_str[cur_len] = '\t'; cur_len++;
939       }
940       g_snprintf(&pref_str[cur_len], MAX_FMT_PREF_LEN - cur_len, "\"%s\", ", quoted_str);
941       cur_pos += fmt_len;
942       cur_len += fmt_len;
943     }
944     g_free(quoted_str);
945     clp = clp->next;
946   }
947
948   /* If the string is at least two characters long, the last two characters
949      are ", ", and should be discarded, as there are no more items in the
950      string.  */
951   if (cur_len >= 2)
952     pref_str[cur_len - 2] = '\0';
953
954   return(pref_str);
955 }
956
957 void
958 prefs_clear_string_list(GList *sl)
959 {
960   GList *l = sl;
961
962   while (l) {
963     g_free(l->data);
964     l = g_list_remove_link(l, l);
965   }
966 }
967
968 /*
969  * Takes a string, a pointer to an array of "enum_val_t"s, and a default gint
970  * value.
971  * The array must be terminated by an entry with a null "name" string.
972  *
973  * If the string matches a "name" string in an entry, the value from that
974  * entry is returned.
975  *
976  * Otherwise, if a string matches a "desctiption" string in an entry, the
977  * value from that entry is returned; we do that for backwards compatibility,
978  * as we used to have only a "name" string that was used both for command-line
979  * and configuration-file values and in the GUI (which meant either that
980  * the GUI had what might be somewhat cryptic values to select from or that
981  * the "-o" flag took long strings, often with spaces in them).
982  *
983  * Otherwise, the default value that was passed as the third argument is
984  * returned.
985  */
986 gint
987 find_val_for_string(const char *needle, const enum_val_t *haystack,
988     gint default_value)
989 {
990         int i;
991
992         for (i = 0; haystack[i].name != NULL; i++) {
993                 if (g_ascii_strcasecmp(needle, haystack[i].name) == 0) {
994                         return haystack[i].value;
995                 }
996         }
997         for (i = 0; haystack[i].name != NULL; i++) {
998                 if (g_ascii_strcasecmp(needle, haystack[i].description) == 0) {
999                         return haystack[i].value;
1000                 }
1001         }
1002         return default_value;
1003 }
1004
1005 /* Takes an string and a pointer to an array of strings, and a default int value.
1006  * The array must be terminated by a NULL string. If the string is found in the array
1007  * of strings, the index of that string in the array is returned. Otherwise, the
1008  * default value that was passed as the third argument is returned.
1009  */
1010 static int
1011 find_index_from_string_array(char *needle, const char **haystack, int default_value)
1012 {
1013         int i = 0;
1014
1015         while (haystack[i] != NULL) {
1016                 if (strcmp(needle, haystack[i]) == 0) {
1017                         return i;
1018                 }
1019                 i++;
1020         }
1021         return default_value;
1022 }
1023
1024 /* Preferences file format:
1025  * - Configuration directives start at the beginning of the line, and
1026  *   are terminated with a colon.
1027  * - Directives can be continued on the next line by preceding them with
1028  *   whitespace.
1029  *
1030  * Example:
1031
1032 # This is a comment line
1033 print.command: lpr
1034 print.file: /a/very/long/path/
1035         to/wireshark-out.ps
1036  *
1037  */
1038
1039 #define DEF_NUM_COLS    6
1040
1041 /* Initialize preferences to wired-in default values.
1042  * They may be overridden by the global preferences file or the
1043  *  user's preferences file.
1044  */
1045 static void
1046 init_prefs(void) {
1047   int         i;
1048   fmt_data    *cfmt;
1049   const gchar *col_fmt[] = {"No.",      "%m", "Time",        "%t",
1050                            "Source",   "%s", "Destination", "%d",
1051                            "Protocol", "%p", "Info",        "%i"};
1052
1053   if (prefs_initialized)
1054     return;
1055
1056   uat_load_all();
1057
1058   prefs.pr_format  = PR_FMT_TEXT;
1059   prefs.pr_dest    = PR_DEST_CMD;
1060   prefs.pr_file    = g_strdup("wireshark.out");
1061   prefs.pr_cmd     = g_strdup("lpr");
1062   prefs.col_list = NULL;
1063   for (i = 0; i < DEF_NUM_COLS; i++) {
1064     cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
1065     cfmt->title = g_strdup(col_fmt[i * 2]);
1066     cfmt->fmt   = g_strdup(col_fmt[(i * 2) + 1]);
1067     cfmt->custom_field = NULL;
1068     prefs.col_list = g_list_append(prefs.col_list, cfmt);
1069   }
1070   prefs.num_cols  = DEF_NUM_COLS;
1071   prefs.st_client_fg.pixel =     0;
1072   prefs.st_client_fg.red   = 32767;
1073   prefs.st_client_fg.green =     0;
1074   prefs.st_client_fg.blue  =     0;
1075   prefs.st_client_bg.pixel =     0;
1076   prefs.st_client_bg.red   = 64507;
1077   prefs.st_client_bg.green = 60909;
1078   prefs.st_client_bg.blue  = 60909;
1079   prefs.st_server_fg.pixel =     0;
1080   prefs.st_server_fg.red   =     0;
1081   prefs.st_server_fg.green =     0;
1082   prefs.st_server_fg.blue  = 32767;
1083   prefs.st_server_bg.pixel =     0;
1084   prefs.st_server_bg.red   = 60909;
1085   prefs.st_server_bg.green = 60909;
1086   prefs.st_server_bg.blue  = 64507;
1087   prefs.gui_scrollbar_on_right = TRUE;
1088   prefs.gui_plist_sel_browse = FALSE;
1089   prefs.gui_ptree_sel_browse = FALSE;
1090   prefs.gui_altern_colors = FALSE;
1091   prefs.gui_ptree_line_style = 0;
1092   prefs.gui_ptree_expander_style = 1;
1093   prefs.gui_hex_dump_highlight_style = 1;
1094   prefs.filter_toolbar_show_in_statusbar = FALSE;
1095   prefs.gui_toolbar_main_style = TB_STYLE_ICONS;
1096 #ifdef _WIN32
1097   prefs.gui_font_name = g_strdup("Lucida Console 10");
1098 #else
1099   /*
1100    * XXX - for now, we make the initial font name a pattern that matches
1101    * only ISO 8859/1 fonts, so that we don't match 2-byte fonts such
1102    * as ISO 10646 fonts.
1103    *
1104    * Users in locales using other one-byte fonts will have to choose
1105    * a different font from the preferences dialog - or put the font
1106    * selection in the global preferences file to make that font the
1107    * default for all users who don't explicitly specify a different
1108    * font.
1109    *
1110    * Making this a font set rather than a font has two problems:
1111    *
1112    *    1) as far as I know, you can't select font sets with the
1113    *       font selection dialog;
1114    *
1115    *  2) if you use a font set, the text to be drawn must be a
1116    *       multi-byte string in the appropriate locale, but
1117    *       Wireshark does *NOT* guarantee that's the case - in
1118    *       the hex-dump window, each character in the text portion
1119    *       of the display must be a *single* byte, and in the
1120    *       packet-list and protocol-tree windows, text extracted
1121    *       from the packet is not necessarily in the right format.
1122    *
1123    * "Doing this right" may, for the packet-list and protocol-tree
1124    * windows, require that dissectors know what the locale is
1125    * *AND* know what locale and text representation is used in
1126    * the packets they're dissecting, and may be impossible in
1127    * the hex-dump window (except by punting and displaying only
1128    * ASCII characters).
1129    *
1130    * GTK+ 2.0 may simplify part of the problem, as it will, as I
1131    * understand it, use UTF-8-encoded Unicode as its internal
1132    * character set; however, we'd still have to know whatever
1133    * character set and encoding is used in the packet (which
1134    * may differ for different protocols, e.g. SMB might use
1135    * PC code pages for some strings and Unicode for others, whilst
1136    * NFS might use some UNIX character set encoding, e.g. ISO 8859/x,
1137    * or one of the EUC character sets for Asian languages, or one
1138    * of the other multi-byte character sets, or UTF-8, or...).
1139    *
1140    * I.e., as far as I can tell, "internationalizing" the packet-list,
1141    * protocol-tree, and hex-dump windows involves a lot more than, say,
1142    * just using font sets rather than fonts.
1143    */
1144   /* XXX - the above comment was about the GTK1 font stuff, just remove this comment now */
1145   /* XXX- is this the correct default font name for GTK2 none win32? */
1146   prefs.gui_font_name = g_strdup("Monospace 10");
1147 #endif
1148   prefs.gui_marked_fg.pixel        =     65535;
1149   prefs.gui_marked_fg.red          =     65535;
1150   prefs.gui_marked_fg.green        =     65535;
1151   prefs.gui_marked_fg.blue         =     65535;
1152   prefs.gui_marked_bg.pixel        =         0;
1153   prefs.gui_marked_bg.red          =         0;
1154   prefs.gui_marked_bg.green        =         0;
1155   prefs.gui_marked_bg.blue         =         0;
1156   prefs.gui_colorized_fg           = g_strdup("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000");
1157   prefs.gui_colorized_bg           = g_strdup("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0");
1158   prefs.gui_geometry_save_position =         FALSE;
1159   prefs.gui_geometry_save_size     =         TRUE;
1160   prefs.gui_geometry_save_maximized=         TRUE;
1161   prefs.gui_geometry_save_column_width =     FALSE;
1162   prefs.gui_console_open           = console_open_never;
1163   prefs.gui_fileopen_style         = FO_STYLE_LAST_OPENED;
1164   prefs.gui_recent_files_count_max = 10;
1165   prefs.gui_fileopen_dir           = g_strdup(get_persdatafile_dir());
1166   prefs.gui_fileopen_preview       = 3;
1167   prefs.gui_ask_unsaved            = TRUE;
1168   prefs.gui_find_wrap              = TRUE;
1169   prefs.gui_use_pref_save          = FALSE;
1170   prefs.gui_webbrowser             = g_strdup(HTML_VIEWER " %s");
1171   prefs.gui_window_title           = g_strdup("");
1172   prefs.gui_layout_type            = layout_type_5;
1173   prefs.gui_layout_content_1       = layout_pane_content_plist;
1174   prefs.gui_layout_content_2       = layout_pane_content_pdetails;
1175   prefs.gui_layout_content_3       = layout_pane_content_pbytes;
1176   prefs.console_log_level          =
1177       G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR;
1178
1179 /* set the default values for the capture dialog box */
1180   prefs.capture_device           = NULL;
1181   prefs.capture_devices_linktypes= NULL;
1182   prefs.capture_devices_descr    = NULL;
1183   prefs.capture_devices_hide     = NULL;
1184   prefs.capture_prom_mode        = TRUE;
1185   prefs.capture_real_time        = TRUE;
1186   prefs.capture_auto_scroll      = TRUE;
1187   prefs.capture_show_info        = FALSE;
1188
1189 /* set the default values for the name resolution dialog box */
1190   prefs.name_resolve             = RESOLV_ALL ^ RESOLV_NETWORK;
1191   prefs.name_resolve_concurrency = 500;
1192
1193 /* set the default values for the tap/statistics dialog box */
1194   prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
1195   prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
1196
1197   prefs.display_hidden_proto_items = FALSE;
1198
1199   prefs_initialized = TRUE;
1200 }
1201
1202 /* Reset preferences */
1203 void
1204 prefs_reset(void)
1205 {
1206   prefs_initialized = FALSE;
1207   if (prefs.pr_file)
1208     g_free(prefs.pr_file);
1209   if (prefs.pr_cmd)
1210     g_free(prefs.pr_cmd);
1211   free_col_info(&prefs);
1212   if (prefs.gui_font_name)
1213     g_free(prefs.gui_font_name);
1214   if (prefs.gui_colorized_fg)
1215     g_free(prefs.gui_colorized_fg);
1216   if (prefs.gui_colorized_bg)
1217     g_free(prefs.gui_colorized_bg);
1218   if (prefs.gui_fileopen_dir)
1219     g_free(prefs.gui_fileopen_dir);
1220   if (prefs.gui_webbrowser)
1221     g_free(prefs.gui_webbrowser);
1222   if (prefs.gui_window_title)
1223     g_free(prefs.gui_window_title);
1224   if (prefs.capture_device)
1225     g_free(prefs.capture_device);
1226   if (prefs.capture_devices_linktypes)
1227     g_free(prefs.capture_devices_linktypes);
1228   if (prefs.capture_devices_descr)
1229     g_free(prefs.capture_devices_descr);
1230   if (prefs.capture_devices_hide)
1231     g_free(prefs.capture_devices_hide);
1232
1233   uat_unload_all();
1234   init_prefs();
1235 }
1236
1237 /* Read the preferences file, fill in "prefs", and return a pointer to it.
1238
1239    If we got an error (other than "it doesn't exist") trying to read
1240    the global preferences file, stuff the errno into "*gpf_errno_return"
1241    and a pointer to the path of the file into "*gpf_path_return", and
1242    return NULL.
1243
1244    If we got an error (other than "it doesn't exist") trying to read
1245    the user's preferences file, stuff the errno into "*pf_errno_return"
1246    and a pointer to the path of the file into "*pf_path_return", and
1247    return NULL. */
1248 e_prefs *
1249 read_prefs(int *gpf_errno_return, int *gpf_read_errno_return,
1250            char **gpf_path_return, int *pf_errno_return,
1251            int *pf_read_errno_return, char **pf_path_return)
1252 {
1253   int         err;
1254   char        *pf_path;
1255   FILE        *pf;
1256
1257   init_prefs();
1258
1259   /*
1260    * If we don't already have the pathname of the global preferences
1261    * file, construct it.  Then, in either case, try to open the file.
1262    */
1263   if (gpf_path == NULL) {
1264     /*
1265      * We don't have the path; try the new path first, and, if that
1266      * file doesn't exist, try the old path.
1267      */
1268     gpf_path = get_datafile_path(PF_NAME);
1269     if ((pf = ws_fopen(gpf_path, "r")) == NULL && errno == ENOENT) {
1270       /*
1271        * It doesn't exist by the new name; try the old name.
1272        */
1273       g_free(gpf_path);
1274       gpf_path = get_datafile_path(OLD_GPF_NAME);
1275       pf = ws_fopen(gpf_path, "r");
1276     }
1277   } else {
1278     /*
1279      * We have the path; try it.
1280      */
1281     pf = ws_fopen(gpf_path, "r");
1282   }
1283
1284   /*
1285    * If we were able to open the file, read it.
1286    * XXX - if it failed for a reason other than "it doesn't exist",
1287    * report the error.
1288    */
1289   *gpf_path_return = NULL;
1290   if (pf != NULL) {
1291     /*
1292      * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
1293      * seen.
1294      */
1295     mgcp_tcp_port_count = 0;
1296     mgcp_udp_port_count = 0;
1297
1298     /* We succeeded in opening it; read it. */
1299     err = read_prefs_file(gpf_path, pf, set_pref, NULL);
1300     if (err != 0) {
1301       /* We had an error reading the file; return the errno and the
1302          pathname, so our caller can report the error. */
1303       *gpf_errno_return = 0;
1304       *gpf_read_errno_return = err;
1305       *gpf_path_return = gpf_path;
1306     }
1307     fclose(pf);
1308   } else {
1309     /* We failed to open it.  If we failed for some reason other than
1310        "it doesn't exist", return the errno and the pathname, so our
1311        caller can report the error. */
1312     if (errno != ENOENT) {
1313       *gpf_errno_return = errno;
1314       *gpf_read_errno_return = 0;
1315       *gpf_path_return = gpf_path;
1316     }
1317   }
1318
1319   /* Construct the pathname of the user's preferences file. */
1320   pf_path = get_persconffile_path(PF_NAME, TRUE, FALSE);
1321
1322   /* Read the user's preferences file, if it exists. */
1323   *pf_path_return = NULL;
1324   if ((pf = ws_fopen(pf_path, "r")) != NULL) {
1325     /*
1326      * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
1327      * seen.
1328      */
1329     mgcp_tcp_port_count = 0;
1330     mgcp_udp_port_count = 0;
1331
1332     /* We succeeded in opening it; read it. */
1333     err = read_prefs_file(pf_path, pf, set_pref, NULL);
1334     if (err != 0) {
1335       /* We had an error reading the file; return the errno and the
1336          pathname, so our caller can report the error. */
1337       *pf_errno_return = 0;
1338       *pf_read_errno_return = err;
1339       *pf_path_return = pf_path;
1340     } else
1341       g_free(pf_path);
1342     fclose(pf);
1343   } else {
1344     /* We failed to open it.  If we failed for some reason other than
1345        "it doesn't exist", return the errno and the pathname, so our
1346        caller can report the error. */
1347     if (errno != ENOENT) {
1348       *pf_errno_return = errno;
1349       *pf_read_errno_return = 0;
1350       *pf_path_return = pf_path;
1351     } else
1352       g_free(pf_path);
1353   }
1354
1355   return &prefs;
1356 }
1357
1358 /* read the preferences file (or similiar) and call the callback
1359  * function to set each key/value pair found */
1360 int
1361 read_prefs_file(const char *pf_path, FILE *pf, pref_set_pair_cb pref_set_pair_fct, void *private_data)
1362 {
1363   enum { START, IN_VAR, PRE_VAL, IN_VAL, IN_SKIP };
1364   int       got_c, state = START;
1365   GString  *cur_val;
1366   GString  *cur_var;
1367   gboolean  got_val = FALSE;
1368   gint      fline = 1, pline = 1;
1369   gchar     hint[] = "(applying your preferences once should remove this warning)";
1370
1371   cur_val = g_string_new("");
1372   cur_var = g_string_new("");
1373
1374   while ((got_c = getc(pf)) != EOF) {
1375     if (got_c == '\n') {
1376       state = START;
1377       fline++;
1378       continue;
1379     }
1380
1381     switch (state) {
1382       case START:
1383         if (isalnum(got_c)) {
1384           if (cur_var->len > 0) {
1385             if (got_val) {
1386               switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data)) {
1387
1388               case PREFS_SET_OK:
1389                 break;
1390
1391               case PREFS_SET_SYNTAX_ERR:
1392                 g_warning ("%s line %d: Syntax error %s", pf_path, pline, hint);
1393                 break;
1394
1395               case PREFS_SET_NO_SUCH_PREF:
1396                 g_warning ("%s line %d: No such preference \"%s\" %s", pf_path,
1397                                 pline, cur_var->str, hint);
1398                 break;
1399
1400               case PREFS_SET_OBSOLETE:
1401                 /* We silently ignore attempts to set these; it's
1402                    probably not the user's fault that it's in there -
1403                    they may have saved preferences with a release that
1404                    supported them. */
1405                 break;
1406               }
1407             } else {
1408               g_warning ("%s line %d: Incomplete preference %s", pf_path, pline, hint);
1409             }
1410           }
1411           state      = IN_VAR;
1412           got_val    = FALSE;
1413           g_string_truncate(cur_var, 0);
1414           g_string_append_c(cur_var, (gchar) got_c);
1415           pline = fline;
1416         } else if (isspace(got_c) && cur_var->len > 0 && got_val) {
1417           state = PRE_VAL;
1418         } else if (got_c == '#') {
1419           state = IN_SKIP;
1420         } else {
1421           g_warning ("%s line %d: Malformed line %s", pf_path, fline, hint);
1422         }
1423         break;
1424       case IN_VAR:
1425         if (got_c != ':') {
1426           g_string_append_c(cur_var, (gchar) got_c);
1427         } else {
1428           state   = PRE_VAL;
1429           g_string_truncate(cur_val, 0);
1430           got_val = TRUE;
1431         }
1432         break;
1433       case PRE_VAL:
1434         if (!isspace(got_c)) {
1435           state = IN_VAL;
1436           g_string_append_c(cur_val, (gchar) got_c);
1437         }
1438         break;
1439       case IN_VAL:
1440         g_string_append_c(cur_val, (gchar) got_c);
1441         break;
1442     }
1443   }
1444   if (cur_var->len > 0) {
1445     if (got_val) {
1446       switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data)) {
1447
1448       case PREFS_SET_OK:
1449         break;
1450
1451       case PREFS_SET_SYNTAX_ERR:
1452         g_warning ("%s line %d: Syntax error %s", pf_path, pline, hint);
1453         break;
1454
1455       case PREFS_SET_NO_SUCH_PREF:
1456         g_warning ("%s line %d: No such preference \"%s\" %s", pf_path,
1457                         pline, cur_var->str, hint);
1458         break;
1459
1460       case PREFS_SET_OBSOLETE:
1461         /* We silently ignore attempts to set these; it's probably not
1462            the user's fault that it's in there - they may have saved
1463            preferences with a release that supported it. */
1464         break;
1465       }
1466     } else {
1467       g_warning ("%s line %d: Incomplete preference %s", pf_path, pline, hint);
1468     }
1469   }
1470
1471   g_string_free(cur_val, TRUE);
1472   g_string_free(cur_var, TRUE);
1473
1474   if (ferror(pf))
1475     return errno;
1476   else
1477     return 0;
1478 }
1479
1480 /*
1481  * If we were handed a preference starting with "uat:", try to turn it into
1482  * a valid uat entry.
1483  */
1484 static gboolean
1485 prefs_set_uat_pref(char *uat_entry) {
1486         gchar *p, *colonp;
1487         uat_t *uat;
1488         gchar *err;
1489
1490         colonp = strchr(uat_entry, ':');
1491         if (colonp == NULL)
1492                 return FALSE;
1493
1494         p = colonp;
1495         *p++ = '\0';
1496
1497         /*
1498          * Skip over any white space (there probably won't be any, but
1499          * as we allow it in the preferences file, we might as well
1500          * allow it here).
1501          */
1502         while (isspace((guchar)*p))
1503                 p++;
1504         if (*p == '\0') {
1505                 /*
1506                  * Put the colon back, so if our caller uses, in an
1507                  * error message, the string they passed us, the message
1508                  * looks correct.
1509                  */
1510                 *colonp = ':';
1511                 return FALSE;
1512         }
1513
1514         uat = uat_find(uat_entry);
1515         *colonp = ':';
1516         if (uat == NULL) {
1517                 return FALSE;
1518         }
1519
1520         if (uat_load_str(uat, p, &err)) {
1521                 return TRUE;
1522         }
1523         return FALSE;
1524 }
1525
1526 /*
1527  * Given a string of the form "<pref name>:<pref value>", as might appear
1528  * as an argument to a "-o" option, parse it and set the preference in
1529  * question.  Return an indication of whether it succeeded or failed
1530  * in some fashion.
1531  */
1532 prefs_set_pref_e
1533 prefs_set_pref(char *prefarg)
1534 {
1535         gchar *p, *colonp;
1536         prefs_set_pref_e ret;
1537
1538         /*
1539          * Set the counters of "mgcp.{tcp,udp}.port" entries we've
1540          * seen to values that keep us from trying to interpret tham
1541          * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
1542          * as, from the command line, we have no way of guessing which
1543          * the user had in mind.
1544          */
1545         mgcp_tcp_port_count = -1;
1546         mgcp_udp_port_count = -1;
1547
1548         colonp = strchr(prefarg, ':');
1549         if (colonp == NULL)
1550                 return PREFS_SET_SYNTAX_ERR;
1551
1552         p = colonp;
1553         *p++ = '\0';
1554
1555         /*
1556          * Skip over any white space (there probably won't be any, but
1557          * as we allow it in the preferences file, we might as well
1558          * allow it here).
1559          */
1560         while (isspace((guchar)*p))
1561                 p++;
1562         if (*p == '\0') {
1563                 /*
1564                  * Put the colon back, so if our caller uses, in an
1565                  * error message, the string they passed us, the message
1566                  * looks correct.
1567                  */
1568                 *colonp = ':';
1569                 return PREFS_SET_SYNTAX_ERR;
1570         }
1571         if (strcmp(prefarg, "uat")) {
1572                 ret = set_pref(prefarg, p, NULL);
1573         } else {
1574                 ret = prefs_set_uat_pref(p) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
1575         }
1576         *colonp = ':';  /* put the colon back */
1577         return ret;
1578 }
1579
1580 /*
1581  * Returns TRUE if the given device is hidden
1582  */
1583 gboolean
1584 prefs_is_capture_device_hidden(const char *name)
1585 {
1586         gchar *tok, *devices;
1587         size_t len;
1588
1589         if (prefs.capture_devices_hide && name) {
1590                 devices = g_strdup (prefs.capture_devices_hide);
1591                 len = strlen (name);
1592                 for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
1593                         if (strlen (tok) == len && strcmp (name, tok) == 0) {
1594                                 g_free (devices);
1595                                 return TRUE;
1596                         }
1597                 }
1598                 g_free (devices);
1599         }
1600
1601         return FALSE;
1602 }
1603
1604 #define PRS_PRINT_FMT                    "print.format"
1605 #define PRS_PRINT_DEST                   "print.destination"
1606 #define PRS_PRINT_FILE                   "print.file"
1607 #define PRS_PRINT_CMD                    "print.command"
1608 #define PRS_COL_FMT                      "column.format"
1609 #define PRS_STREAM_CL_FG                 "stream.client.fg"
1610 #define PRS_STREAM_CL_BG                 "stream.client.bg"
1611 #define PRS_STREAM_SR_FG                 "stream.server.fg"
1612 #define PRS_STREAM_SR_BG                 "stream.server.bg"
1613 #define PRS_GUI_SCROLLBAR_ON_RIGHT       "gui.scrollbar_on_right"
1614 #define PRS_GUI_PLIST_SEL_BROWSE         "gui.packet_list_sel_browse"
1615 #define PRS_GUI_PTREE_SEL_BROWSE         "gui.protocol_tree_sel_browse"
1616 #define PRS_GUI_ALTERN_COLORS            "gui.tree_view_altern_colors"
1617 #define PRS_GUI_FILTER_TOOLBAR_IN_STATUSBAR "gui.filter_toolbar_show_in_statusbar"
1618 #define PRS_GUI_PTREE_LINE_STYLE         "gui.protocol_tree_line_style"
1619 #define PRS_GUI_PTREE_EXPANDER_STYLE     "gui.protocol_tree_expander_style"
1620 #define PRS_GUI_HEX_DUMP_HIGHLIGHT_STYLE "gui.hex_dump_highlight_style"
1621 #define PRS_GUI_FONT_NAME_1              "gui.font_name"
1622 #define PRS_GUI_FONT_NAME_2              "gui.gtk2.font_name"
1623 #define PRS_GUI_MARKED_FG                "gui.marked_frame.fg"
1624 #define PRS_GUI_MARKED_BG                "gui.marked_frame.bg"
1625 #define PRS_GUI_COLORIZED_FG             "gui.colorized_frame.fg"
1626 #define PRS_GUI_COLORIZED_BG             "gui.colorized_frame.bg"
1627 #define PRS_GUI_CONSOLE_OPEN             "gui.console_open"
1628 #define PRS_GUI_FILEOPEN_STYLE           "gui.fileopen.style"
1629 #define PRS_GUI_RECENT_COUNT_MAX         "gui.recent_files_count.max"
1630 #define PRS_GUI_FILEOPEN_DIR             "gui.fileopen.dir"
1631 #define PRS_GUI_FILEOPEN_REMEMBERED_DIR  "gui.fileopen.remembered_dir"
1632 #define PRS_GUI_FILEOPEN_PREVIEW         "gui.fileopen.preview"
1633 #define PRS_GUI_ASK_UNSAVED              "gui.ask_unsaved"
1634 #define PRS_GUI_FIND_WRAP                "gui.find_wrap"
1635 #define PRS_GUI_USE_PREF_SAVE            "gui.use_pref_save"
1636 #define PRS_GUI_GEOMETRY_SAVE_POSITION   "gui.geometry.save.position"
1637 #define PRS_GUI_GEOMETRY_SAVE_SIZE       "gui.geometry.save.size"
1638 #define PRS_GUI_GEOMETRY_SAVE_MAXIMIZED  "gui.geometry.save.maximized"
1639 #define PRS_GUI_GEOMETRY_SAVE_COLUMN_WIDTH "gui.geometry.save.column_width"
1640 #define PRS_GUI_GEOMETRY_MAIN_X          "gui.geometry.main.x"
1641 #define PRS_GUI_GEOMETRY_MAIN_Y          "gui.geometry.main.y"
1642 #define PRS_GUI_GEOMETRY_MAIN_WIDTH      "gui.geometry.main.width"
1643 #define PRS_GUI_GEOMETRY_MAIN_HEIGHT     "gui.geometry.main.height"
1644 #define PRS_GUI_TOOLBAR_MAIN_SHOW        "gui.toolbar_main_show"
1645 #define PRS_GUI_TOOLBAR_MAIN_STYLE       "gui.toolbar_main_style"
1646 #define PRS_GUI_WEBBROWSER               "gui.webbrowser"
1647 #define PRS_GUI_WINDOW_TITLE             "gui.window_title"
1648 #define PRS_GUI_LAYOUT_TYPE              "gui.layout_type"
1649 #define PRS_GUI_LAYOUT_CONTENT_1         "gui.layout_content_1"
1650 #define PRS_GUI_LAYOUT_CONTENT_2         "gui.layout_content_2"
1651 #define PRS_GUI_LAYOUT_CONTENT_3         "gui.layout_content_3"
1652 #define PRS_CONSOLE_LOG_LEVEL            "console.log.level"
1653
1654 /*
1655  * This applies to more than just captures, so it's not "capture.name_resolve";
1656  * "capture.name_resolve" is supported on input for backwards compatibility.
1657  *
1658  * It's not a preference for a particular part of Wireshark, it's used all
1659  * over the place, so its name doesn't have two components.
1660  */
1661 #define PRS_NAME_RESOLVE "name_resolve"
1662 #define PRS_NAME_RESOLVE_CONCURRENCY "name_resolve_concurrency"
1663 #define PRS_CAP_NAME_RESOLVE "capture.name_resolve"
1664
1665 /*  values for the capture dialog box */
1666 #define PRS_CAP_DEVICE        "capture.device"
1667 #define PRS_CAP_DEVICES_LINKTYPES "capture.devices_linktypes"
1668 #define PRS_CAP_DEVICES_DESCR "capture.devices_descr"
1669 #define PRS_CAP_DEVICES_HIDE  "capture.devices_hide"
1670 #define PRS_CAP_PROM_MODE     "capture.prom_mode"
1671 #define PRS_CAP_REAL_TIME     "capture.real_time_update"
1672 #define PRS_CAP_AUTO_SCROLL   "capture.auto_scroll"
1673 #define PRS_CAP_SHOW_INFO     "capture.show_info"
1674
1675 #define RED_COMPONENT(x)   (guint16) (((((x) >> 16) & 0xff) * 65535 / 255))
1676 #define GREEN_COMPONENT(x) (guint16) (((((x) >>  8) & 0xff) * 65535 / 255))
1677 #define BLUE_COMPONENT(x)  (guint16) ( (((x)        & 0xff) * 65535 / 255))
1678
1679 /*  values for the rtp player preferences dialog box */
1680 #define PRS_TAP_UPDATE_INTERVAL           "taps.update_interval"
1681 #define PRS_RTP_PLAYER_MAX_VISIBLE        "taps.rtp_player_max_visible"
1682
1683 #define PRS_DISPLAY_HIDDEN_PROTO_ITEMS          "packet_list.display_hidden_proto_items"
1684
1685 static const gchar *pr_formats[] = { "text", "postscript" };
1686 static const gchar *pr_dests[]   = { "command", "file" };
1687
1688 typedef struct {
1689   char    letter;
1690   guint32 value;
1691 } name_resolve_opt_t;
1692
1693 static name_resolve_opt_t name_resolve_opt[] = {
1694   { 'm', RESOLV_MAC },
1695   { 'n', RESOLV_NETWORK },
1696   { 't', RESOLV_TRANSPORT },
1697   { 'C', RESOLV_CONCURRENT },
1698 };
1699
1700 #define N_NAME_RESOLVE_OPT      (sizeof name_resolve_opt / sizeof name_resolve_opt[0])
1701
1702 static const char *
1703 name_resolve_to_string(guint32 name_resolve)
1704 {
1705   static char string[N_NAME_RESOLVE_OPT+1];
1706   char *p;
1707   unsigned int i;
1708   gboolean all_opts_set = TRUE;
1709
1710   if (name_resolve == RESOLV_NONE)
1711     return "FALSE";
1712   p = &string[0];
1713   for (i = 0; i < N_NAME_RESOLVE_OPT; i++) {
1714     if (name_resolve & name_resolve_opt[i].value)
1715       *p++ =  name_resolve_opt[i].letter;
1716     else
1717       all_opts_set = FALSE;
1718   }
1719   *p = '\0';
1720   if (all_opts_set)
1721     return "TRUE";
1722   return string;
1723 }
1724
1725 char
1726 string_to_name_resolve(char *string, guint32 *name_resolve)
1727 {
1728   char c;
1729   unsigned int i;
1730
1731   *name_resolve = 0;
1732   while ((c = *string++) != '\0') {
1733     for (i = 0; i < N_NAME_RESOLVE_OPT; i++) {
1734       if (c == name_resolve_opt[i].letter) {
1735         *name_resolve |= name_resolve_opt[i].value;
1736         break;
1737       }
1738     }
1739     if (i == N_NAME_RESOLVE_OPT) {
1740       /*
1741        * Unrecognized letter.
1742        */
1743       return c;
1744     }
1745   }
1746   return '\0';
1747 }
1748
1749 static prefs_set_pref_e
1750 set_pref(gchar *pref_name, gchar *value, void *private_data _U_)
1751 {
1752   GList    *col_l, *col_l_elt;
1753   gint      llen;
1754   fmt_data *cfmt;
1755   unsigned long int cval;
1756   guint    uval;
1757   gboolean bval;
1758   gint     enum_val;
1759   char     *p;
1760   gchar    *dotp, *last_dotp;
1761   module_t *module;
1762   pref_t   *pref;
1763   gboolean had_a_dot;
1764   const gchar *cust_format = col_format_to_string(COL_CUSTOM);
1765   int cust_format_len = strlen(cust_format);
1766
1767   if (strcmp(pref_name, PRS_PRINT_FMT) == 0) {
1768     if (strcmp(value, pr_formats[PR_FMT_TEXT]) == 0) {
1769       prefs.pr_format = PR_FMT_TEXT;
1770     } else if (strcmp(value, pr_formats[PR_FMT_PS]) == 0) {
1771       prefs.pr_format = PR_FMT_PS;
1772     } else {
1773       return PREFS_SET_SYNTAX_ERR;
1774     }
1775   } else if (strcmp(pref_name, PRS_PRINT_DEST) == 0) {
1776     if (strcmp(value, pr_dests[PR_DEST_CMD]) == 0) {
1777       prefs.pr_dest = PR_DEST_CMD;
1778     } else if (strcmp(value, pr_dests[PR_DEST_FILE]) == 0) {
1779       prefs.pr_dest = PR_DEST_FILE;
1780     } else {
1781       return PREFS_SET_SYNTAX_ERR;
1782     }
1783   } else if (strcmp(pref_name, PRS_PRINT_FILE) == 0) {
1784     if (prefs.pr_file) g_free(prefs.pr_file);
1785     prefs.pr_file = g_strdup(value);
1786   } else if (strcmp(pref_name, PRS_PRINT_CMD) == 0) {
1787     if (prefs.pr_cmd) g_free(prefs.pr_cmd);
1788     prefs.pr_cmd = g_strdup(value);
1789   } else if (strcmp(pref_name, PRS_COL_FMT) == 0) {
1790     col_l = prefs_get_string_list(value);
1791     if (col_l == NULL)
1792       return PREFS_SET_SYNTAX_ERR;
1793     if ((g_list_length(col_l) % 2) != 0) {
1794       /* A title didn't have a matching format.  */
1795       prefs_clear_string_list(col_l);
1796       return PREFS_SET_SYNTAX_ERR;
1797     }
1798     /* Check to make sure all column formats are valid.  */
1799     col_l_elt = g_list_first(col_l);
1800     while(col_l_elt) {
1801       /* Make sure the title isn't empty.  */
1802       if (strcmp(col_l_elt->data, "") == 0) {
1803         /* It is.  */
1804         prefs_clear_string_list(col_l);
1805         return PREFS_SET_SYNTAX_ERR;
1806       }
1807
1808       /* Go past the title.  */
1809       col_l_elt = col_l_elt->next;
1810
1811       /* Check the format.  */
1812       if (strncmp(col_l_elt->data, cust_format, cust_format_len) != 0) {
1813         if (get_column_format_from_str(col_l_elt->data) == -1) {
1814           /* It's not a valid column format.  */
1815           prefs_clear_string_list(col_l);
1816           return PREFS_SET_SYNTAX_ERR;
1817         }
1818       }
1819
1820       /* Go past the format.  */
1821       col_l_elt = col_l_elt->next;
1822     }
1823     free_col_info(&prefs);
1824     prefs.col_list = NULL;
1825     llen             = g_list_length(col_l);
1826     prefs.num_cols   = llen / 2;
1827     col_l_elt = g_list_first(col_l);
1828     while(col_l_elt) {
1829       cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
1830       cfmt->title    = g_strdup(col_l_elt->data);
1831       col_l_elt      = col_l_elt->next;
1832       if (strncmp(col_l_elt->data, cust_format, cust_format_len) == 0) {
1833         gchar *fmt     = g_strdup(col_l_elt->data);
1834         cfmt->fmt      = g_strdup(cust_format);
1835         cfmt->custom_field = g_strdup(&fmt[cust_format_len+1]);  /* add 1 for ':' */
1836         g_free (fmt);
1837       } else {
1838         cfmt->fmt      = g_strdup(col_l_elt->data);
1839         cfmt->custom_field = NULL;
1840       }
1841       col_l_elt      = col_l_elt->next;
1842       prefs.col_list = g_list_append(prefs.col_list, cfmt);
1843     }
1844     prefs_clear_string_list(col_l);
1845   } else if (strcmp(pref_name, PRS_STREAM_CL_FG) == 0) {
1846     cval = strtoul(value, NULL, 16);
1847     prefs.st_client_fg.pixel = 0;
1848     prefs.st_client_fg.red   = RED_COMPONENT(cval);
1849     prefs.st_client_fg.green = GREEN_COMPONENT(cval);
1850     prefs.st_client_fg.blue  = BLUE_COMPONENT(cval);
1851   } else if (strcmp(pref_name, PRS_STREAM_CL_BG) == 0) {
1852     cval = strtoul(value, NULL, 16);
1853     prefs.st_client_bg.pixel = 0;
1854     prefs.st_client_bg.red   = RED_COMPONENT(cval);
1855     prefs.st_client_bg.green = GREEN_COMPONENT(cval);
1856     prefs.st_client_bg.blue  = BLUE_COMPONENT(cval);
1857   } else if (strcmp(pref_name, PRS_STREAM_SR_FG) == 0) {
1858     cval = strtoul(value, NULL, 16);
1859     prefs.st_server_fg.pixel = 0;
1860     prefs.st_server_fg.red   = RED_COMPONENT(cval);
1861     prefs.st_server_fg.green = GREEN_COMPONENT(cval);
1862     prefs.st_server_fg.blue  = BLUE_COMPONENT(cval);
1863   } else if (strcmp(pref_name, PRS_STREAM_SR_BG) == 0) {
1864     cval = strtoul(value, NULL, 16);
1865     prefs.st_server_bg.pixel = 0;
1866     prefs.st_server_bg.red   = RED_COMPONENT(cval);
1867     prefs.st_server_bg.green = GREEN_COMPONENT(cval);
1868     prefs.st_server_bg.blue  = BLUE_COMPONENT(cval);
1869   } else if (strcmp(pref_name, PRS_GUI_SCROLLBAR_ON_RIGHT) == 0) {
1870     if (g_ascii_strcasecmp(value, "true") == 0) {
1871             prefs.gui_scrollbar_on_right = TRUE;
1872     }
1873     else {
1874             prefs.gui_scrollbar_on_right = FALSE;
1875     }
1876   } else if (strcmp(pref_name, PRS_GUI_PLIST_SEL_BROWSE) == 0) {
1877     if (g_ascii_strcasecmp(value, "true") == 0) {
1878             prefs.gui_plist_sel_browse = TRUE;
1879     }
1880     else {
1881             prefs.gui_plist_sel_browse = FALSE;
1882     }
1883   } else if (strcmp(pref_name, PRS_GUI_PTREE_SEL_BROWSE) == 0) {
1884     if (g_ascii_strcasecmp(value, "true") == 0) {
1885             prefs.gui_ptree_sel_browse = TRUE;
1886     }
1887     else {
1888             prefs.gui_ptree_sel_browse = FALSE;
1889     }
1890   } else if (strcmp(pref_name, PRS_GUI_ALTERN_COLORS) == 0) {
1891     if (g_ascii_strcasecmp(value, "true") == 0) {
1892             prefs.gui_altern_colors = TRUE;
1893     }
1894     else {
1895             prefs.gui_altern_colors = FALSE;
1896     }
1897   } else if (strcmp(pref_name, PRS_GUI_PTREE_LINE_STYLE) == 0) {
1898     prefs.gui_ptree_line_style =
1899         find_index_from_string_array(value, gui_ptree_line_style_text, 0);
1900   } else if (strcmp(pref_name, PRS_GUI_PTREE_EXPANDER_STYLE) == 0) {
1901     prefs.gui_ptree_expander_style =
1902         find_index_from_string_array(value, gui_ptree_expander_style_text, 1);
1903   } else if (strcmp(pref_name, PRS_GUI_HEX_DUMP_HIGHLIGHT_STYLE) == 0) {
1904     prefs.gui_hex_dump_highlight_style =
1905         find_index_from_string_array(value, gui_hex_dump_highlight_style_text, 1);
1906   } else if (strcmp(pref_name, PRS_GUI_FILTER_TOOLBAR_IN_STATUSBAR) == 0) {
1907     if (g_ascii_strcasecmp(value, "true") == 0) {
1908             prefs.filter_toolbar_show_in_statusbar = TRUE;
1909     }
1910     else {
1911             prefs.filter_toolbar_show_in_statusbar = FALSE;
1912     }
1913   } else if (strcmp(pref_name, PRS_GUI_TOOLBAR_MAIN_SHOW) == 0) {
1914     /* obsoleted by recent setting */
1915   } else if (strcmp(pref_name, PRS_GUI_TOOLBAR_MAIN_STYLE) == 0) {
1916     /* see toolbar.c for details, "icons only" is default */
1917         prefs.gui_toolbar_main_style =
1918             find_index_from_string_array(value, gui_toolbar_style_text,
1919                                      TB_STYLE_ICONS);
1920   } else if (strcmp(pref_name, PRS_GUI_FONT_NAME_1) == 0) {
1921     /* GTK1 font name obsolete */
1922   } else if (strcmp(pref_name, PRS_GUI_FONT_NAME_2) == 0) {
1923     if (prefs.gui_font_name != NULL)
1924       g_free(prefs.gui_font_name);
1925     prefs.gui_font_name = g_strdup(value);
1926   } else if (strcmp(pref_name, PRS_GUI_MARKED_FG) == 0) {
1927     cval = strtoul(value, NULL, 16);
1928     prefs.gui_marked_fg.pixel = 0;
1929     prefs.gui_marked_fg.red   = RED_COMPONENT(cval);
1930     prefs.gui_marked_fg.green = GREEN_COMPONENT(cval);
1931     prefs.gui_marked_fg.blue  = BLUE_COMPONENT(cval);
1932   } else if (strcmp(pref_name, PRS_GUI_MARKED_BG) == 0) {
1933     cval = strtoul(value, NULL, 16);
1934     prefs.gui_marked_bg.pixel = 0;
1935     prefs.gui_marked_bg.red   = RED_COMPONENT(cval);
1936     prefs.gui_marked_bg.green = GREEN_COMPONENT(cval);
1937     prefs.gui_marked_bg.blue  = BLUE_COMPONENT(cval);
1938   } else if (strcmp(pref_name, PRS_GUI_COLORIZED_FG) == 0) {
1939     if (prefs.gui_colorized_fg != NULL)
1940       g_free(prefs.gui_colorized_fg);
1941     prefs.gui_colorized_fg = g_strdup(value);
1942   } else if (strcmp(pref_name, PRS_GUI_COLORIZED_BG) == 0) {
1943     if (prefs.gui_colorized_bg != NULL)
1944       g_free(prefs.gui_colorized_bg);
1945     prefs.gui_colorized_bg = g_strdup(value);
1946   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_SAVE_POSITION) == 0) {
1947     if (g_ascii_strcasecmp(value, "true") == 0) {
1948             prefs.gui_geometry_save_position = TRUE;
1949     }
1950     else {
1951             prefs.gui_geometry_save_position = FALSE;
1952     }
1953   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_SAVE_SIZE) == 0) {
1954     if (g_ascii_strcasecmp(value, "true") == 0) {
1955             prefs.gui_geometry_save_size = TRUE;
1956     }
1957     else {
1958             prefs.gui_geometry_save_size = FALSE;
1959     }
1960   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_SAVE_MAXIMIZED) == 0) {
1961     if (g_ascii_strcasecmp(value, "true") == 0) {
1962             prefs.gui_geometry_save_maximized = TRUE;
1963     }
1964     else {
1965             prefs.gui_geometry_save_maximized = FALSE;
1966     }
1967   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_SAVE_COLUMN_WIDTH) == 0) {
1968     if (g_ascii_strcasecmp(value, "true") == 0) {
1969             prefs.gui_geometry_save_column_width = TRUE;
1970     }
1971     else {
1972             prefs.gui_geometry_save_column_width = FALSE;
1973     }
1974   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_X) == 0) {         /* deprecated */
1975   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_Y) == 0) {         /* deprecated */
1976   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_WIDTH) == 0) {     /* deprecated */
1977   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {    /* deprecated */
1978   } else if (strcmp(pref_name, PRS_GUI_CONSOLE_OPEN) == 0) {
1979     prefs.gui_console_open =
1980         find_index_from_string_array(value, gui_console_open_text,
1981                                      console_open_never);
1982   } else if (strcmp(pref_name, PRS_GUI_RECENT_COUNT_MAX) == 0) {
1983     prefs.gui_recent_files_count_max = strtoul(value, NULL, 10);
1984     if (prefs.gui_recent_files_count_max == 0) {
1985       /* We really should put up a dialog box here ... */
1986       prefs.gui_recent_files_count_max = 10;
1987     }
1988   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_STYLE) == 0) {
1989     prefs.gui_fileopen_style =
1990         find_index_from_string_array(value, gui_fileopen_style_text,
1991                                      FO_STYLE_LAST_OPENED);
1992   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_DIR) == 0) {
1993     if (prefs.gui_fileopen_dir != NULL)
1994       g_free(prefs.gui_fileopen_dir);
1995     prefs.gui_fileopen_dir = g_strdup(value);
1996   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_REMEMBERED_DIR) == 0) { /* deprecated */
1997   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_PREVIEW) == 0) {
1998     prefs.gui_fileopen_preview = strtoul(value, NULL, 10);
1999   } else if (strcmp(pref_name, PRS_GUI_ASK_UNSAVED) == 0) {
2000     if (g_ascii_strcasecmp(value, "true") == 0) {
2001             prefs.gui_ask_unsaved = TRUE;
2002     }
2003     else {
2004             prefs.gui_ask_unsaved = FALSE;
2005     }
2006   } else if (strcmp(pref_name, PRS_GUI_FIND_WRAP) == 0) {
2007     if (g_ascii_strcasecmp(value, "true") == 0) {
2008             prefs.gui_find_wrap = TRUE;
2009     }
2010     else {
2011             prefs.gui_find_wrap = FALSE;
2012     }
2013   } else if (strcmp(pref_name, PRS_GUI_USE_PREF_SAVE) == 0) {
2014     if (g_ascii_strcasecmp(value, "true") == 0) {
2015             prefs.gui_use_pref_save = TRUE;
2016     }
2017     else {
2018             prefs.gui_use_pref_save = FALSE;
2019     }
2020   } else if (strcmp(pref_name, PRS_GUI_WEBBROWSER) == 0) {
2021     g_free(prefs.gui_webbrowser);
2022     prefs.gui_webbrowser = g_strdup(value);
2023   } else if (strcmp(pref_name, PRS_GUI_WINDOW_TITLE) == 0) {
2024     if (prefs.gui_window_title != NULL)
2025       g_free(prefs.gui_window_title);
2026     prefs.gui_window_title = g_strdup(value);
2027   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_TYPE) == 0) {
2028     prefs.gui_layout_type = strtoul(value, NULL, 10);
2029     if (prefs.gui_layout_type == layout_unused ||
2030         prefs.gui_layout_type >= layout_type_max) {
2031       /* XXX - report an error?  It's not a syntax error - we'd need to
2032          add a way of reporting a *semantic* error. */
2033       prefs.gui_layout_type = layout_type_5;
2034     }
2035   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_CONTENT_1) == 0) {
2036     prefs.gui_layout_content_1 =
2037         find_index_from_string_array(value, gui_layout_content_text, 0);
2038   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_CONTENT_2) == 0) {
2039     prefs.gui_layout_content_2 =
2040         find_index_from_string_array(value, gui_layout_content_text, 0);
2041   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_CONTENT_3) == 0) {
2042     prefs.gui_layout_content_3 =
2043         find_index_from_string_array(value, gui_layout_content_text, 0);
2044   } else if (strcmp(pref_name, PRS_CONSOLE_LOG_LEVEL) == 0) {
2045     prefs.console_log_level = strtoul(value, NULL, 10);
2046
2047 /* handle the capture options */
2048   } else if (strcmp(pref_name, PRS_CAP_DEVICE) == 0) {
2049     if (prefs.capture_device != NULL)
2050       g_free(prefs.capture_device);
2051     prefs.capture_device = g_strdup(value);
2052   } else if (strcmp(pref_name, PRS_CAP_DEVICES_LINKTYPES) == 0) {
2053     if (prefs.capture_devices_linktypes != NULL)
2054       g_free(prefs.capture_devices_linktypes);
2055     prefs.capture_devices_linktypes = g_strdup(value);
2056   } else if (strcmp(pref_name, PRS_CAP_DEVICES_DESCR) == 0) {
2057     if (prefs.capture_devices_descr != NULL)
2058       g_free(prefs.capture_devices_descr);
2059     prefs.capture_devices_descr = g_strdup(value);
2060   } else if (strcmp(pref_name, PRS_CAP_DEVICES_HIDE) == 0) {
2061     if (prefs.capture_devices_hide != NULL)
2062       g_free(prefs.capture_devices_hide);
2063     prefs.capture_devices_hide = g_strdup(value);
2064   } else if (strcmp(pref_name, PRS_CAP_PROM_MODE) == 0) {
2065     prefs.capture_prom_mode = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2066   } else if (strcmp(pref_name, PRS_CAP_REAL_TIME) == 0) {
2067     prefs.capture_real_time = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2068   } else if (strcmp(pref_name, PRS_CAP_AUTO_SCROLL) == 0) {
2069     prefs.capture_auto_scroll = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2070   } else if (strcmp(pref_name, PRS_CAP_SHOW_INFO) == 0) {
2071     prefs.capture_show_info = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2072
2073 /* handle the global options */
2074   } else if (strcmp(pref_name, PRS_NAME_RESOLVE) == 0 ||
2075              strcmp(pref_name, PRS_CAP_NAME_RESOLVE) == 0) {
2076     /*
2077      * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
2078      * RESOLV_ALL and RESOLV_NONE.
2079      *
2080      * Otherwise, we treat it as a list of name types we want to resolve.
2081      */
2082     if (g_ascii_strcasecmp(value, "true") == 0)
2083       prefs.name_resolve = RESOLV_ALL;
2084     else if (g_ascii_strcasecmp(value, "false") == 0)
2085       prefs.name_resolve = RESOLV_NONE;
2086     else {
2087       prefs.name_resolve = RESOLV_NONE; /* start out with none set */
2088       if (string_to_name_resolve(value, &prefs.name_resolve) != '\0')
2089         return PREFS_SET_SYNTAX_ERR;
2090     }
2091   } else if (strcmp(pref_name, PRS_NAME_RESOLVE_CONCURRENCY) == 0) {
2092     prefs.name_resolve_concurrency = strtol(value, NULL, 10);
2093   } else if ((strcmp(pref_name, PRS_RTP_PLAYER_MAX_VISIBLE) == 0) ||
2094              (strcmp(pref_name, "rtp_player.max_visible") == 0)) {
2095     /* ... also accepting old name for this preference */
2096     prefs.rtp_player_max_visible = strtol(value, NULL, 10);
2097   } else if (strcmp(pref_name, PRS_TAP_UPDATE_INTERVAL) == 0) {
2098     prefs.tap_update_interval = strtol(value, NULL, 10);
2099   } else if (strcmp(pref_name, PRS_DISPLAY_HIDDEN_PROTO_ITEMS) == 0) {
2100     prefs.display_hidden_proto_items = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2101   } else {
2102     /* To which module does this preference belong? */
2103     module = NULL;
2104     last_dotp = pref_name;
2105     had_a_dot = FALSE;
2106     while (!module) {
2107         dotp = strchr(last_dotp, '.');
2108         if (dotp == NULL) {
2109             if (had_a_dot) {
2110               /* no such module */
2111               return PREFS_SET_NO_SUCH_PREF;
2112             }
2113             else {
2114               /* no ".", so no module/name separator */
2115               return PREFS_SET_SYNTAX_ERR;
2116             }
2117         }
2118         else {
2119             had_a_dot = TRUE;
2120         }
2121         *dotp = '\0';           /* separate module and preference name */
2122         module = prefs_find_module(pref_name);
2123
2124         /*
2125          * XXX - "Diameter" rather than "diameter" was used in earlier
2126          * versions of Wireshark; if we didn't find the module, and its name
2127          * was "Diameter", look for "diameter" instead.
2128          *
2129          * In addition, the BEEP protocol used to be the BXXP protocol,
2130          * so if we didn't find the module, and its name was "bxxp",
2131          * look for "beep" instead.
2132          *
2133          * Also, the preferences for GTP v0 and v1 were combined under
2134          * a single "gtp" heading, and the preferences for SMPP were
2135          * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
2136          * However, SMPP now has its own preferences, so we just map
2137          * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
2138          *
2139          * We also renamed "dcp" to "dccp".
2140          */
2141         if (module == NULL) {
2142           if (strcmp(pref_name, "Diameter") == 0)
2143             module = prefs_find_module("diameter");
2144           else if (strcmp(pref_name, "bxxp") == 0)
2145             module = prefs_find_module("beep");
2146           else if (strcmp(pref_name, "gtpv0") == 0 ||
2147                    strcmp(pref_name, "gtpv1") == 0)
2148             module = prefs_find_module("gtp");
2149           else if (strcmp(pref_name, "smpp-gsm-sms") == 0)
2150             module = prefs_find_module("gsm-sms-ud");
2151           else if (strcmp(pref_name, "dcp") == 0)
2152             module = prefs_find_module("dccp");
2153         }
2154         *dotp = '.';            /* put the preference string back */
2155         dotp++;                 /* skip past separator to preference name */
2156         last_dotp = dotp;
2157     }
2158
2159     pref = find_preference(module, dotp);
2160
2161     if (pref == NULL) {
2162       if (strcmp(module->name, "mgcp") == 0) {
2163         /*
2164          * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
2165          * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
2166          * were used in earlier versions of Wireshark; if we didn't find the
2167          * preference, it was an MGCP preference, and its name was
2168          * "display raw text toggle" or "display dissect tree", look for
2169          * "display_raw_text" or "display_dissect_tree" instead.
2170          *
2171          * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
2172          * the gateway and callagent ports were given those names; we interpret
2173          * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
2174          * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
2175          * they were registered by the MCCP dissector and thus that's the
2176          * order in which they were written to the preferences file.  (If
2177          * we're not reading the preferences file, but are handling stuff
2178          * from a "-o" command-line option, we have no clue which the user
2179          * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
2180          * or "mgcp.{tcp,udp}.callagent_port" instead.)
2181          */
2182         if (strcmp(dotp, "display raw text toggle") == 0)
2183           pref = find_preference(module, "display_raw_text");
2184         else if (strcmp(dotp, "display dissect tree") == 0)
2185           pref = find_preference(module, "display_dissect_tree");
2186         else if (strcmp(dotp, "tcp.port") == 0) {
2187           mgcp_tcp_port_count++;
2188           if (mgcp_tcp_port_count == 1) {
2189             /* It's the first one */
2190             pref = find_preference(module, "tcp.gateway_port");
2191           } else if (mgcp_tcp_port_count == 2) {
2192             /* It's the second one */
2193             pref = find_preference(module, "tcp.callagent_port");
2194           }
2195           /* Otherwise it's from the command line, and we don't bother
2196              mapping it. */
2197         } else if (strcmp(dotp, "udp.port") == 0) {
2198           mgcp_udp_port_count++;
2199           if (mgcp_udp_port_count == 1) {
2200             /* It's the first one */
2201             pref = find_preference(module, "udp.gateway_port");
2202           } else if (mgcp_udp_port_count == 2) {
2203             /* It's the second one */
2204             pref = find_preference(module, "udp.callagent_port");
2205           }
2206           /* Otherwise it's from the command line, and we don't bother
2207              mapping it. */
2208         }
2209       } else if (strcmp(module->name, "smb") == 0) {
2210         /* Handle old names for SMB preferences. */
2211         if (strcmp(dotp, "smb.trans.reassembly") == 0)
2212           pref = find_preference(module, "trans_reassembly");
2213         else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
2214           pref = find_preference(module, "dcerpc_reassembly");
2215       } else if (strcmp(module->name, "ndmp") == 0) {
2216         /* Handle old names for NDMP preferences. */
2217         if (strcmp(dotp, "ndmp.desegment") == 0)
2218           pref = find_preference(module, "desegment");
2219       } else if (strcmp(module->name, "diameter") == 0) {
2220         /* Handle old names for Diameter preferences. */
2221         if (strcmp(dotp, "diameter.desegment") == 0)
2222           pref = find_preference(module, "desegment");
2223       } else if (strcmp(module->name, "pcli") == 0) {
2224         /* Handle old names for PCLI preferences. */
2225         if (strcmp(dotp, "pcli.udp_port") == 0)
2226           pref = find_preference(module, "udp_port");
2227       } else if (strcmp(module->name, "artnet") == 0) {
2228         /* Handle old names for ARTNET preferences. */
2229         if (strcmp(dotp, "artnet.udp_port") == 0)
2230           pref = find_preference(module, "udp_port");
2231       } else if (strcmp(module->name, "mapi") == 0) {
2232         /* Handle old names for MAPI preferences. */
2233         if (strcmp(dotp, "mapi_decrypt") == 0)
2234           pref = find_preference(module, "decrypt");
2235       } else if (strcmp(module->name, "fc") == 0) {
2236         /* Handle old names for Fibre Channel preferences. */
2237         if (strcmp(dotp, "reassemble_fc") == 0)
2238           pref = find_preference(module, "reassemble");
2239         else if (strcmp(dotp, "fc_max_frame_size") == 0)
2240           pref = find_preference(module, "max_frame_size");
2241       } else if (strcmp(module->name, "fcip") == 0) {
2242         /* Handle old names for Fibre Channel-over-IP preferences. */
2243         if (strcmp(dotp, "desegment_fcip_messages") == 0)
2244           pref = find_preference(module, "desegment");
2245         else if (strcmp(dotp, "fcip_port") == 0)
2246           pref = find_preference(module, "target_port");
2247       } else if (strcmp(module->name, "gtp") == 0) {
2248         /* Handle old names for GTP preferences. */
2249         if (strcmp(dotp, "gtpv0_port") == 0)
2250           pref = find_preference(module, "v0_port");
2251         else if (strcmp(dotp, "gtpv1c_port") == 0)
2252           pref = find_preference(module, "v1c_port");
2253         else if (strcmp(dotp, "gtpv1u_port") == 0)
2254           pref = find_preference(module, "v1u_port");
2255         else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
2256           pref = find_preference(module, "dissect_tpdu");
2257         else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
2258           pref = find_preference(module, "v0_dissect_cdr_as");
2259         else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
2260           pref = find_preference(module, "v0_check_etsi");
2261         else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
2262           pref = find_preference(module, "v1_check_etsi");
2263       } else if (strcmp(module->name, "ip") == 0) {
2264         /* Handle old names for IP preferences. */
2265         if (strcmp(dotp, "ip_summary_in_tree") == 0)
2266           pref = find_preference(module, "summary_in_tree");
2267       } else if (strcmp(module->name, "iscsi") == 0) {
2268         /* Handle old names for iSCSI preferences. */
2269         if (strcmp(dotp, "iscsi_port") == 0)
2270           pref = find_preference(module, "target_port");
2271       } else if (strcmp(module->name, "lmp") == 0) {
2272         /* Handle old names for LMP preferences. */
2273         if (strcmp(dotp, "lmp_version") == 0)
2274           pref = find_preference(module, "version");
2275       } else if (strcmp(module->name, "mtp3") == 0) {
2276         /* Handle old names for MTP3 preferences. */
2277         if (strcmp(dotp, "mtp3_standard") == 0)
2278           pref = find_preference(module, "standard");
2279         else if (strcmp(dotp, "net_addr_format") == 0)
2280           pref = find_preference(module, "addr_format");
2281       } else if (strcmp(module->name, "nlm") == 0) {
2282         /* Handle old names for NLM preferences. */
2283         if (strcmp(dotp, "nlm_msg_res_matching") == 0)
2284           pref = find_preference(module, "msg_res_matching");
2285       } else if (strcmp(module->name, "ppp") == 0) {
2286         /* Handle old names for PPP preferences. */
2287         if (strcmp(dotp, "ppp_fcs") == 0)
2288           pref = find_preference(module, "fcs_type");
2289         else if (strcmp(dotp, "ppp_vj") == 0)
2290           pref = find_preference(module, "decompress_vj");
2291       } else if (strcmp(module->name, "rsvp") == 0) {
2292         /* Handle old names for RSVP preferences. */
2293         if (strcmp(dotp, "rsvp_process_bundle") == 0)
2294           pref = find_preference(module, "process_bundle");
2295       } else if (strcmp(module->name, "tcp") == 0) {
2296         /* Handle old names for TCP preferences. */
2297         if (strcmp(dotp, "tcp_summary_in_tree") == 0)
2298           pref = find_preference(module, "summary_in_tree");
2299         else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
2300           pref = find_preference(module, "analyze_sequence_numbers");
2301         else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
2302           pref = find_preference(module, "relative_sequence_numbers");
2303       } else if (strcmp(module->name, "udp") == 0) {
2304         /* Handle old names for UDP preferences. */
2305         if (strcmp(dotp, "udp_summary_in_tree") == 0)
2306           pref = find_preference(module, "summary_in_tree");
2307       } else if (strcmp(module->name, "ndps") == 0) {
2308         /* Handle old names for NDPS preferences. */
2309         if (strcmp(dotp, "desegment_ndps") == 0)
2310           pref = find_preference(module, "desegment_tcp");
2311       } else if (strcmp(module->name, "http") == 0) {
2312         /* Handle old names for HTTP preferences. */
2313         if (strcmp(dotp, "desegment_http_headers") == 0)
2314           pref = find_preference(module, "desegment_headers");
2315         else if (strcmp(dotp, "desegment_http_body") == 0)
2316           pref = find_preference(module, "desegment_body");
2317       } else if (strcmp(module->name, "smpp") == 0) {
2318         /* Handle preferences that moved from SMPP. */
2319         module_t *new_module = prefs_find_module("gsm-sms-ud");
2320         if(new_module){
2321           if (strcmp(dotp, "port_number_udh_means_wsp") == 0)
2322             pref = find_preference(new_module, "port_number_udh_means_wsp");
2323           else if (strcmp(dotp, "try_dissect_1st_fragment") == 0)
2324             pref = find_preference(new_module, "try_dissect_1st_fragment");
2325         }
2326       } else if (strcmp(module->name, "asn1") == 0) {
2327         /* Handle old generic ASN.1 preferences (it's not really a
2328            rename, as the new preferences support multiple ports,
2329            but we might as well copy them over). */
2330         if (strcmp(dotp, "tcp_port") == 0)
2331           pref = find_preference(module, "tcp_ports");
2332         else if (strcmp(dotp, "udp_port") == 0)
2333           pref = find_preference(module, "udp_ports");
2334         else if (strcmp(dotp, "sctp_port") == 0)
2335           pref = find_preference(module, "sctp_ports");
2336       } else if (strcmp(module->name, "llcgprs") == 0) {
2337         if (strcmp(dotp, "ignore_cipher_bit") == 0)
2338           pref = find_preference(module, "autodetect_cipher_bit");
2339       } else if (strcmp(module->name, "erf") == 0) {
2340         if (strcmp(dotp, "erfeth") == 0) {
2341           /* Handle the old "erfeth" preference; map it to the new
2342              "ethfcs" preference, and map the values to those for
2343              the new preference. */
2344           pref = find_preference(module, "ethfcs");
2345           if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
2346             value = "TRUE";
2347           else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
2348             value = "FALSE";
2349           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2350             value = "TRUE";
2351         } else if (strcmp(dotp, "erfatm") == 0) {
2352           /* Handle the old "erfatm" preference; map it to the new
2353              "aal5_type" preference, and map the values to those for
2354              the new preference. */
2355           pref = find_preference(module, "aal5_type");
2356           if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
2357             value = "guess";
2358           else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
2359             value = "llc";
2360           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2361             value = "guess";
2362         } else if (strcmp(dotp, "erfhdlc") == 0) {
2363           /* Handle the old "erfhdlc" preference; map it to the new
2364              "hdlc_type" preference, and map the values to those for
2365              the new preference. */
2366           pref = find_preference(module, "hdlc_type");
2367           if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
2368             value = "chdlc";
2369           else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
2370             value = "ppp";
2371           else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
2372             value = "frelay";
2373           else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
2374             value = "mtp2";
2375           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2376             value = "guess";
2377         }
2378       }
2379     }
2380     if (pref == NULL)
2381       return PREFS_SET_NO_SUCH_PREF;    /* no such preference */
2382
2383     switch (pref->type) {
2384
2385     case PREF_UINT:
2386       uval = strtoul(value, &p, pref->info.base);
2387       if (p == value || *p != '\0')
2388         return PREFS_SET_SYNTAX_ERR;    /* number was bad */
2389       if (*pref->varp.uint != uval) {
2390         module->prefs_changed = TRUE;
2391         *pref->varp.uint = uval;
2392       }
2393       break;
2394
2395     case PREF_BOOL:
2396       /* XXX - give an error if it's neither "true" nor "false"? */
2397       if (g_ascii_strcasecmp(value, "true") == 0)
2398         bval = TRUE;
2399       else
2400         bval = FALSE;
2401       if (*pref->varp.boolp != bval) {
2402         module->prefs_changed = TRUE;
2403         *pref->varp.boolp = bval;
2404       }
2405       break;
2406
2407     case PREF_ENUM:
2408       /* XXX - give an error if it doesn't match? */
2409       enum_val = find_val_for_string(value,
2410                                         pref->info.enum_info.enumvals, 1);
2411       if (*pref->varp.enump != enum_val) {
2412         module->prefs_changed = TRUE;
2413         *pref->varp.enump = enum_val;
2414       }
2415       break;
2416
2417     case PREF_STRING:
2418       if (strcmp(*pref->varp.string, value) != 0) {
2419         module->prefs_changed = TRUE;
2420         g_free((void *)*pref->varp.string);
2421         *pref->varp.string = g_strdup(value);
2422       }
2423       break;
2424
2425     case PREF_RANGE:
2426     {
2427       range_t *newrange;
2428
2429       if (range_convert_str(&newrange, value, pref->info.max_value) !=
2430           CVT_NO_ERROR) {
2431         /* XXX - distinguish between CVT_SYNTAX_ERROR and
2432            CVT_NUMBER_TOO_BIG */
2433         return PREFS_SET_SYNTAX_ERR;    /* number was bad */
2434       }
2435
2436       if (!ranges_are_equal(*pref->varp.range, newrange)) {
2437         module->prefs_changed = TRUE;
2438         g_free(*pref->varp.range);
2439         *pref->varp.range = newrange;
2440       } else {
2441         g_free (newrange);
2442       }
2443       break;
2444     }
2445
2446     case PREF_STATIC_TEXT:
2447     case PREF_UAT:
2448     {
2449       break;
2450     }
2451
2452     case PREF_OBSOLETE:
2453       return PREFS_SET_OBSOLETE;        /* no such preference any more */
2454     }
2455   }
2456
2457   return PREFS_SET_OK;
2458 }
2459
2460 typedef struct {
2461         module_t *module;
2462         FILE    *pf;
2463 } write_pref_arg_t;
2464
2465 /*
2466  * Write out a single preference.
2467  */
2468 static void
2469 write_pref(gpointer data, gpointer user_data)
2470 {
2471         pref_t *pref = data;
2472         write_pref_arg_t *arg = user_data;
2473         const enum_val_t *enum_valp;
2474         const char *val_string;
2475         gchar **desc_lines;
2476         int i;
2477
2478         if (pref->type == PREF_OBSOLETE) {
2479                 /*
2480                  * This preference is no longer supported; it's not a
2481                  * real preference, so we don't write it out (i.e., we
2482                  * treat it as if it weren't found in the list of
2483                  * preferences, and we weren't called in the first place).
2484                  */
2485                 return;
2486         }
2487
2488         /* 
2489          * Make multiple line descriptions appear as 
2490          * multiple commented lines in prefs file.
2491          */
2492         if (g_ascii_strncasecmp(pref->description,"", 2) != 0) {
2493                 desc_lines = g_strsplit(pref->description,"\n",0);
2494                 for (i = 0; desc_lines[i] != NULL; ++i) {
2495                         fprintf(arg->pf, "\n# %s", desc_lines[i]);
2496                 }
2497                 fprintf(arg->pf, "\n");
2498                 g_strfreev(desc_lines);
2499         } else {
2500                 fprintf(arg->pf, "\n# No description\n");
2501         }
2502
2503         switch (pref->type) {
2504
2505         case PREF_UINT:
2506                 switch (pref->info.base) {
2507
2508                 case 10:
2509                         fprintf(arg->pf, "# A decimal number.\n");
2510                         fprintf(arg->pf, "%s.%s: %u\n", arg->module->name,
2511                             pref->name, *pref->varp.uint);
2512                         break;
2513
2514                 case 8:
2515                         fprintf(arg->pf, "# An octal number.\n");
2516                         fprintf(arg->pf, "%s.%s: %#o\n", arg->module->name,
2517                             pref->name, *pref->varp.uint);
2518                         break;
2519
2520                 case 16:
2521                         fprintf(arg->pf, "# A hexadecimal number.\n");
2522                         fprintf(arg->pf, "%s.%s: %#x\n", arg->module->name,
2523                             pref->name, *pref->varp.uint);
2524                         break;
2525                 }
2526                 break;
2527
2528         case PREF_BOOL:
2529                 fprintf(arg->pf, "# TRUE or FALSE (case-insensitive).\n");
2530                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2531                     *pref->varp.boolp ? "TRUE" : "FALSE");
2532                 break;
2533
2534         case PREF_ENUM:
2535                 /*
2536                  * For now, we save the "description" value, so that if we
2537                  * save the preferences older versions of Wireshark can at
2538                  * least read preferences that they supported; we support
2539                  * either the short name or the description when reading
2540                  * the preferences file or a "-o" option.
2541                  */
2542                 fprintf(arg->pf, "# One of: ");
2543                 enum_valp = pref->info.enum_info.enumvals;
2544                 val_string = NULL;
2545                 while (enum_valp->name != NULL) {
2546                         if (enum_valp->value == *pref->varp.enump)
2547                                 val_string = enum_valp->description;
2548                         fprintf(arg->pf, "%s", enum_valp->description);
2549                         enum_valp++;
2550                         if (enum_valp->name == NULL)
2551                                 fprintf(arg->pf, "\n");
2552                         else
2553                                 fprintf(arg->pf, ", ");
2554                 }
2555                 fprintf(arg->pf, "# (case-insensitive).\n");
2556                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name,
2557                     pref->name, val_string);
2558                 break;
2559
2560         case PREF_STRING:
2561                 fprintf(arg->pf, "# A string.\n");
2562                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2563                     *pref->varp.string);
2564                 break;
2565
2566         case PREF_RANGE:
2567         {
2568                 char *range_string;
2569
2570                 range_string = range_convert_range(*pref->varp.range);
2571                 fprintf(arg->pf, "# A string denoting an positive integer range (e.g., \"1-20,30-40\").\n");
2572                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2573                         range_string);
2574                 break;
2575         }
2576
2577         case PREF_STATIC_TEXT:
2578         case PREF_UAT:
2579         {
2580                 /* Nothing to do */
2581                 break;
2582         }
2583
2584         case PREF_OBSOLETE:
2585                 g_assert_not_reached();
2586                 break;
2587         }
2588 }
2589
2590 static gboolean
2591 write_module_prefs(void *value, void *data)
2592 {
2593         write_pref_arg_t arg;
2594
2595         arg.module = value;
2596         arg.pf = data;
2597         g_list_foreach(arg.module->prefs, write_pref, &arg);
2598         return FALSE;
2599 }
2600
2601 /* Write out "prefs" to the user's preferences file, and return 0.
2602
2603    If the preferences file path is NULL, write to stdout.
2604
2605    If we got an error, stuff a pointer to the path of the preferences file
2606    into "*pf_path_return", and return the errno. */
2607 int
2608 write_prefs(char **pf_path_return)
2609 {
2610   char        *pf_path;
2611   FILE        *pf;
2612   GList       *clp, *col_l;
2613   fmt_data    *cfmt;
2614   const gchar *cust_format = col_format_to_string(COL_CUSTOM);
2615
2616   /* Needed for "-G defaultprefs" */
2617   init_prefs();
2618
2619   /* To do:
2620    * - Split output lines longer than MAX_VAL_LEN
2621    * - Create a function for the preference directory check/creation
2622    *   so that duplication can be avoided with filter.c
2623    */
2624
2625   if (pf_path_return != NULL) {
2626     pf_path = get_persconffile_path(PF_NAME, TRUE, TRUE);
2627     if ((pf = ws_fopen(pf_path, "w")) == NULL) {
2628       *pf_path_return = pf_path;
2629       return errno;
2630     }
2631   } else {
2632     pf = stdout;
2633   }
2634
2635   fputs("# Configuration file for Wireshark " VERSION ".\n"
2636     "#\n"
2637     "# This file is regenerated each time preferences are saved within\n"
2638     "# Wireshark.  Making manual changes should be safe, however.\n", pf);
2639
2640   fprintf (pf, "\n######## User Interface ########\n");
2641
2642   fprintf(pf, "\n# Vertical scrollbars should be on right side?\n");
2643   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2644   fprintf(pf, PRS_GUI_SCROLLBAR_ON_RIGHT ": %s\n",
2645                   prefs.gui_scrollbar_on_right == TRUE ? "TRUE" : "FALSE");
2646
2647   fprintf(pf, "\n# Packet-list selection bar can be used to browse w/o selecting?\n");
2648   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2649   fprintf(pf, PRS_GUI_PLIST_SEL_BROWSE ": %s\n",
2650                   prefs.gui_plist_sel_browse == TRUE ? "TRUE" : "FALSE");
2651
2652   fprintf(pf, "\n# Protocol-tree selection bar can be used to browse w/o selecting?\n");
2653   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2654   fprintf(pf, PRS_GUI_PTREE_SEL_BROWSE ": %s\n",
2655                   prefs.gui_ptree_sel_browse == TRUE ? "TRUE" : "FALSE");
2656
2657   fprintf(pf, "\n# Alternating colors in TreeViews?\n");
2658   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2659   fprintf(pf, PRS_GUI_ALTERN_COLORS ": %s\n",
2660                   prefs.gui_altern_colors == TRUE ? "TRUE" : "FALSE");
2661
2662   fprintf(pf, "\n# Place filter toolbar inside the statusbar?\n");
2663   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2664   fprintf(pf, PRS_GUI_FILTER_TOOLBAR_IN_STATUSBAR ": %s\n",
2665                  prefs.filter_toolbar_show_in_statusbar == TRUE ? "TRUE" : "FALSE");
2666
2667   fprintf(pf, "\n# Protocol-tree line style.\n");
2668   fprintf(pf, "# One of: NONE, SOLID, DOTTED, TABBED\n");
2669   fprintf(pf, PRS_GUI_PTREE_LINE_STYLE ": %s\n",
2670           gui_ptree_line_style_text[prefs.gui_ptree_line_style]);
2671
2672   fprintf(pf, "\n# Protocol-tree expander style.\n");
2673   fprintf(pf, "# One of: NONE, SQUARE, TRIANGLE, CIRCULAR\n");
2674   fprintf(pf, PRS_GUI_PTREE_EXPANDER_STYLE ": %s\n",
2675                   gui_ptree_expander_style_text[prefs.gui_ptree_expander_style]);
2676
2677   fprintf(pf, "\n# Hex dump highlight style.\n");
2678   fprintf(pf, "# One of: BOLD, INVERSE\n");
2679   fprintf(pf, PRS_GUI_HEX_DUMP_HIGHLIGHT_STYLE ": %s\n",
2680                   gui_hex_dump_highlight_style_text[prefs.gui_hex_dump_highlight_style]);
2681
2682   fprintf(pf, "\n# Main Toolbar style.\n");
2683   fprintf(pf, "# One of: ICONS, TEXT, BOTH\n");
2684   fprintf(pf, PRS_GUI_TOOLBAR_MAIN_STYLE ": %s\n",
2685                   gui_toolbar_style_text[prefs.gui_toolbar_main_style]);
2686
2687   fprintf(pf, "\n# Save window position at exit?\n");
2688   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2689   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_POSITION ": %s\n",
2690                   prefs.gui_geometry_save_position == TRUE ? "TRUE" : "FALSE");
2691
2692   fprintf(pf, "\n# Save window size at exit?\n");
2693   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2694   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_SIZE ": %s\n",
2695                   prefs.gui_geometry_save_size == TRUE ? "TRUE" : "FALSE");
2696
2697   fprintf(pf, "\n# Save window maximized state at exit?\n");
2698   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2699   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_MAXIMIZED ": %s\n",
2700                   prefs.gui_geometry_save_maximized == TRUE ? "TRUE" : "FALSE");
2701
2702   fprintf(pf, "\n# Save packet list column widths?\n");
2703   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2704   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_COLUMN_WIDTH ": %s\n",
2705                   prefs.gui_geometry_save_column_width == TRUE ? "TRUE" : "FALSE");
2706
2707   fprintf(pf, "\n# Open a console window (WIN32 only)?\n");
2708   fprintf(pf, "# One of: NEVER, AUTOMATIC, ALWAYS\n");
2709   fprintf(pf, PRS_GUI_CONSOLE_OPEN ": %s\n",
2710                   gui_console_open_text[prefs.gui_console_open]);
2711
2712   fprintf(pf, "\n# The max. number of items in the open recent files list.\n");
2713   fprintf(pf, "# A decimal number.\n");
2714   fprintf(pf, PRS_GUI_RECENT_COUNT_MAX ": %d\n",
2715                   prefs.gui_recent_files_count_max);
2716
2717   fprintf(pf, "\n# Where to start the File Open dialog box.\n");
2718   fprintf(pf, "# One of: LAST_OPENED, SPECIFIED\n");
2719   fprintf(pf, PRS_GUI_FILEOPEN_STYLE ": %s\n",
2720                   gui_fileopen_style_text[prefs.gui_fileopen_style]);
2721
2722   if (prefs.gui_fileopen_dir != NULL) {
2723     fprintf(pf, "\n# Directory to start in when opening File Open dialog.\n");
2724     fprintf(pf, PRS_GUI_FILEOPEN_DIR ": %s\n",
2725                   prefs.gui_fileopen_dir);
2726   }
2727
2728   fprintf(pf, "\n# The preview timeout in the File Open dialog.\n");
2729   fprintf(pf, "# A decimal number (in seconds).\n");
2730   fprintf(pf, PRS_GUI_FILEOPEN_PREVIEW ": %d\n",
2731                   prefs.gui_fileopen_preview);
2732
2733   fprintf(pf, "\n# Ask to save unsaved capture files?\n");
2734   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2735   fprintf(pf, PRS_GUI_ASK_UNSAVED ": %s\n",
2736                   prefs.gui_ask_unsaved == TRUE ? "TRUE" : "FALSE");
2737
2738   fprintf(pf, "\n# Wrap to beginning/end of file during search?\n");
2739   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2740   fprintf(pf, PRS_GUI_FIND_WRAP ": %s\n",
2741                   prefs.gui_find_wrap == TRUE ? "TRUE" : "FALSE");
2742
2743   fprintf(pf, "\n# Settings dialogs use a save button?\n");
2744   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2745   fprintf(pf, PRS_GUI_USE_PREF_SAVE ": %s\n",
2746                   prefs.gui_use_pref_save == TRUE ? "TRUE" : "FALSE");
2747
2748   fprintf(pf, "\n# The path to the webbrowser.\n");
2749   fprintf(pf, "# Ex: mozilla %%s\n");
2750   fprintf(pf, PRS_GUI_WEBBROWSER ": %s\n", prefs.gui_webbrowser);
2751
2752   fprintf(pf, "\n# Custom window title. (Prepended to existing titles.)\n");
2753   fprintf(pf, PRS_GUI_WINDOW_TITLE ": %s\n",
2754               prefs.gui_window_title);
2755
2756   fprintf (pf, "\n######## User Interface: Layout ########\n");
2757
2758   fprintf(pf, "\n# Layout type (1-6).\n");
2759   fprintf(pf, PRS_GUI_LAYOUT_TYPE ": %d\n",
2760                   prefs.gui_layout_type);
2761
2762   fprintf(pf, "\n# Layout content of the panes (1-3).\n");
2763   fprintf(pf, "# One of: NONE, PLIST, PDETAILS, PBYTES\n");
2764   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_1 ": %s\n",
2765                   gui_layout_content_text[prefs.gui_layout_content_1]);
2766   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_2 ": %s\n",
2767                   gui_layout_content_text[prefs.gui_layout_content_2]);
2768   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_3 ": %s\n",
2769                   gui_layout_content_text[prefs.gui_layout_content_3]);
2770
2771   fprintf (pf, "\n######## User Interface: Columns ########\n");
2772
2773   clp = prefs.col_list;
2774   col_l = NULL;
2775   while (clp) {
2776     cfmt = (fmt_data *) clp->data;
2777     col_l = g_list_append(col_l, cfmt->title);
2778     if ((strcmp(cfmt->fmt, cust_format) == 0) && (cfmt->custom_field)) {
2779       gchar *fmt = g_strdup_printf("%s:%s", cfmt->fmt, cfmt->custom_field);
2780       col_l = g_list_append(col_l, fmt);
2781     } else {
2782       col_l = g_list_append(col_l, cfmt->fmt);
2783     }
2784     clp = clp->next;
2785   }
2786   fprintf (pf, "\n# Packet list column format.\n");
2787   fprintf (pf, "# Each pair of strings consists of a column title and its format.\n");
2788   fprintf (pf, "%s: %s\n", PRS_COL_FMT, put_string_list(col_l));
2789   /* This frees the list of strings, but not the strings to which it
2790      refers; that's what we want, as we haven't copied those strings,
2791      we just referred to them.  */
2792   g_list_free(col_l);
2793
2794   fprintf (pf, "\n######## User Interface: Font ########\n");
2795
2796   fprintf(pf, "\n# Font name for packet list, protocol tree, and hex dump panes.\n");
2797   fprintf(pf, PRS_GUI_FONT_NAME_2 ": %s\n", prefs.gui_font_name);
2798
2799   fprintf (pf, "\n######## User Interface: Colors ########\n");
2800
2801   fprintf (pf, "\n# Color preferences for a marked frame.\n");
2802   fprintf (pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
2803   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_MARKED_FG,
2804     (prefs.gui_marked_fg.red * 255 / 65535),
2805     (prefs.gui_marked_fg.green * 255 / 65535),
2806     (prefs.gui_marked_fg.blue * 255 / 65535));
2807   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_MARKED_BG,
2808     (prefs.gui_marked_bg.red * 255 / 65535),
2809     (prefs.gui_marked_bg.green * 255 / 65535),
2810     (prefs.gui_marked_bg.blue * 255 / 65535));
2811
2812   /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
2813    * file until the colors can be changed in the GUI. Currently this is not really
2814    * possible since the STOCK-icons for these colors are hardcoded.
2815    *
2816    * XXX Find a way to change the colors of the STOCK-icons on the fly and then
2817    *     add these 10 colors to the list of colors that can be changed through
2818    *     the preferences.
2819    *
2820   fprintf (pf, "%s: %s\n", PRS_GUI_COLORIZED_FG, prefs.gui_colorized_fg);
2821   fprintf (pf, "%s: %s\n", PRS_GUI_COLORIZED_BG, prefs.gui_colorized_bg);
2822   */
2823
2824   fprintf (pf, "\n# TCP stream window color preferences.\n");
2825   fprintf (pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
2826   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_CL_FG,
2827     (prefs.st_client_fg.red * 255 / 65535),
2828     (prefs.st_client_fg.green * 255 / 65535),
2829     (prefs.st_client_fg.blue * 255 / 65535));
2830   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_CL_BG,
2831     (prefs.st_client_bg.red * 255 / 65535),
2832     (prefs.st_client_bg.green * 255 / 65535),
2833     (prefs.st_client_bg.blue * 255 / 65535));
2834   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_SR_FG,
2835     (prefs.st_server_fg.red * 255 / 65535),
2836     (prefs.st_server_fg.green * 255 / 65535),
2837     (prefs.st_server_fg.blue * 255 / 65535));
2838   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_SR_BG,
2839     (prefs.st_server_bg.red * 255 / 65535),
2840     (prefs.st_server_bg.green * 255 / 65535),
2841     (prefs.st_server_bg.blue * 255 / 65535));
2842
2843   fprintf(pf, "\n######## Console: logging level ########\n");
2844   fprintf(pf, "# (debugging only, not in the Preferences dialog)\n");
2845   fprintf(pf, "# A bitmask of glib log levels:\n"
2846           "# G_LOG_LEVEL_ERROR    = 4\n"
2847           "# G_LOG_LEVEL_CRITICAL = 8\n"
2848           "# G_LOG_LEVEL_WARNING  = 16\n"
2849           "# G_LOG_LEVEL_MESSAGE  = 32\n"
2850           "# G_LOG_LEVEL_INFO     = 64\n"
2851           "# G_LOG_LEVEL_DEBUG    = 128\n");
2852
2853   fprintf(pf, PRS_CONSOLE_LOG_LEVEL ": %u\n",
2854           prefs.console_log_level);
2855
2856   fprintf(pf, "\n####### Capture ########\n");
2857
2858   if (prefs.capture_device != NULL) {
2859     fprintf(pf, "\n# Default capture device\n");
2860     fprintf(pf, PRS_CAP_DEVICE ": %s\n", prefs.capture_device);
2861   }
2862
2863   if (prefs.capture_devices_linktypes != NULL) {
2864     fprintf(pf, "\n# Interface link-layer header types.\n");
2865     fprintf(pf, "# A decimal number for the DLT.\n");
2866     fprintf(pf, "# Ex: en0(1),en1(143),...\n");
2867     fprintf(pf, PRS_CAP_DEVICES_LINKTYPES ": %s\n", prefs.capture_devices_linktypes);
2868   }
2869
2870   if (prefs.capture_devices_descr != NULL) {
2871     fprintf(pf, "\n# Interface descriptions.\n");
2872     fprintf(pf, "# Ex: eth0(eth0 descr),eth1(eth1 descr),...\n");
2873     fprintf(pf, PRS_CAP_DEVICES_DESCR ": %s\n", prefs.capture_devices_descr);
2874   }
2875
2876   if (prefs.capture_devices_hide != NULL) {
2877     fprintf(pf, "\n# Hide interface?\n");
2878     fprintf(pf, "# Ex: eth0,eth3,...\n");
2879     fprintf(pf, PRS_CAP_DEVICES_HIDE ": %s\n", prefs.capture_devices_hide);
2880   }
2881
2882   fprintf(pf, "\n# Capture in promiscuous mode?\n");
2883   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2884   fprintf(pf, PRS_CAP_PROM_MODE ": %s\n",
2885                   prefs.capture_prom_mode == TRUE ? "TRUE" : "FALSE");
2886
2887   fprintf(pf, "\n# Update packet list in real time during capture?\n");
2888   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2889   fprintf(pf, PRS_CAP_REAL_TIME ": %s\n",
2890                   prefs.capture_real_time == TRUE ? "TRUE" : "FALSE");
2891
2892   fprintf(pf, "\n# Scroll packet list during capture?\n");
2893   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2894   fprintf(pf, PRS_CAP_AUTO_SCROLL ": %s\n",
2895                   prefs.capture_auto_scroll == TRUE ? "TRUE" : "FALSE");
2896
2897   fprintf(pf, "\n# Show capture info dialog while capturing?\n");
2898   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2899   fprintf(pf, PRS_CAP_SHOW_INFO ": %s\n",
2900                   prefs.capture_show_info == TRUE ? "TRUE" : "FALSE");
2901
2902   fprintf (pf, "\n######## Printing ########\n");
2903
2904   fprintf (pf, "\n# Can be one of \"text\" or \"postscript\".\n"
2905     "print.format: %s\n", pr_formats[prefs.pr_format]);
2906
2907   fprintf (pf, "\n# Can be one of \"command\" or \"file\".\n"
2908     "print.destination: %s\n", pr_dests[prefs.pr_dest]);
2909
2910   fprintf (pf, "\n# This is the file that gets written to when the "
2911     "destination is set to \"file\"\n"
2912     "%s: %s\n", PRS_PRINT_FILE, prefs.pr_file);
2913
2914   fprintf (pf, "\n# Output gets piped to this command when the destination "
2915     "is set to \"command\"\n"
2916     "%s: %s\n", PRS_PRINT_CMD, prefs.pr_cmd);
2917
2918   fprintf(pf, "\n####### Name Resolution ########\n");
2919
2920   fprintf(pf, "\n# Resolve addresses to names?\n");
2921   fprintf(pf, "# TRUE or FALSE (case-insensitive), or a list of address types to resolve.\n");
2922   fprintf(pf, PRS_NAME_RESOLVE ": %s\n",
2923                   name_resolve_to_string(prefs.name_resolve));
2924
2925   fprintf(pf, "\n# Name resolution concurrency.\n");
2926   fprintf(pf, "# A decimal number.\n");
2927   fprintf(pf, PRS_NAME_RESOLVE_CONCURRENCY ": %d\n",
2928                   prefs.name_resolve_concurrency);
2929
2930   fprintf(pf, "\n####### Taps/Statistics ########\n");
2931
2932   fprintf(pf, "\n# Tap update interval in ms.\n");
2933   fprintf(pf, "# An integer value greater between 100 and 10000.\n");
2934   fprintf(pf, PRS_TAP_UPDATE_INTERVAL ": %d\n",
2935           prefs.tap_update_interval);
2936   fprintf(pf, "\n# Maximum visible channels in RTP Player window.\n");
2937   fprintf(pf, "# An integer value greater than 0.\n");
2938   fprintf(pf, PRS_RTP_PLAYER_MAX_VISIBLE ": %d\n",
2939                   prefs.rtp_player_max_visible);
2940
2941   fprintf(pf, "\n####### Protocols ########\n");
2942
2943   fprintf(pf, "\n# Display hidden items in packet details pane?\n");
2944   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2945   fprintf(pf, PRS_DISPLAY_HIDDEN_PROTO_ITEMS ": %s\n",
2946                   prefs.display_hidden_proto_items == TRUE ? "TRUE" : "FALSE");
2947
2948   pe_tree_foreach(prefs_modules, write_module_prefs, pf);
2949
2950   fclose(pf);
2951
2952   /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
2953      an error indication, or maybe write to a new preferences file and
2954      rename that file on top of the old one only if there are not I/O
2955      errors. */
2956   return 0;
2957 }
2958
2959 /* Copy a set of preferences. */
2960 void
2961 copy_prefs(e_prefs *dest, e_prefs *src)
2962 {
2963   fmt_data *src_cfmt, *dest_cfmt;
2964   GList *entry;
2965
2966   dest->pr_format = src->pr_format;
2967   dest->pr_dest = src->pr_dest;
2968   dest->pr_file = g_strdup(src->pr_file);
2969   dest->pr_cmd = g_strdup(src->pr_cmd);
2970   dest->col_list = NULL;
2971   for (entry = src->col_list; entry != NULL; entry = g_list_next(entry)) {
2972     src_cfmt = entry->data;
2973     dest_cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
2974     dest_cfmt->title = g_strdup(src_cfmt->title);
2975     dest_cfmt->fmt = g_strdup(src_cfmt->fmt);
2976     if (src_cfmt->custom_field) {
2977       dest_cfmt->custom_field = g_strdup(src_cfmt->custom_field);
2978     } else {
2979       dest_cfmt->custom_field = NULL;
2980     }
2981     dest->col_list = g_list_append(dest->col_list, dest_cfmt);
2982   }
2983   dest->num_cols = src->num_cols;
2984   dest->st_client_fg = src->st_client_fg;
2985   dest->st_client_bg = src->st_client_bg;
2986   dest->st_server_fg = src->st_server_fg;
2987   dest->st_server_bg = src->st_server_bg;
2988   dest->gui_scrollbar_on_right = src->gui_scrollbar_on_right;
2989   dest->gui_plist_sel_browse = src->gui_plist_sel_browse;
2990   dest->gui_ptree_sel_browse = src->gui_ptree_sel_browse;
2991   dest->gui_altern_colors = src->gui_altern_colors;
2992   dest->filter_toolbar_show_in_statusbar = src->filter_toolbar_show_in_statusbar;
2993   dest->gui_ptree_line_style = src->gui_ptree_line_style;
2994   dest->gui_ptree_expander_style = src->gui_ptree_expander_style;
2995   dest->gui_hex_dump_highlight_style = src->gui_hex_dump_highlight_style;
2996   dest->gui_toolbar_main_style = src->gui_toolbar_main_style;
2997   dest->gui_fileopen_dir = g_strdup(src->gui_fileopen_dir);
2998   dest->gui_console_open = src->gui_console_open;
2999   dest->gui_fileopen_style = src->gui_fileopen_style;
3000   dest->gui_fileopen_preview = src->gui_fileopen_preview;
3001   dest->gui_ask_unsaved = src->gui_ask_unsaved;
3002   dest->gui_find_wrap = src->gui_find_wrap;
3003   dest->gui_use_pref_save = src->gui_use_pref_save;
3004   dest->gui_layout_type = src->gui_layout_type;
3005   dest->gui_layout_content_1 = src->gui_layout_content_1;
3006   dest->gui_layout_content_2 = src->gui_layout_content_2;
3007   dest->gui_layout_content_3 = src->gui_layout_content_3;
3008   dest->gui_font_name = g_strdup(src->gui_font_name);
3009   dest->gui_marked_fg = src->gui_marked_fg;
3010   dest->gui_marked_bg = src->gui_marked_bg;
3011   dest->gui_geometry_save_position = src->gui_geometry_save_position;
3012   dest->gui_geometry_save_size = src->gui_geometry_save_size;
3013   dest->gui_geometry_save_maximized = src->gui_geometry_save_maximized;
3014   dest->gui_geometry_save_column_width = src->gui_geometry_save_column_width;
3015   dest->gui_webbrowser = g_strdup(src->gui_webbrowser);
3016   dest->gui_window_title = g_strdup(src->gui_window_title);
3017   dest->console_log_level = src->console_log_level;
3018 /*  values for the capture dialog box */
3019   dest->capture_device = g_strdup(src->capture_device);
3020   dest->capture_devices_linktypes = g_strdup(src->capture_devices_linktypes);
3021   dest->capture_devices_descr = g_strdup(src->capture_devices_descr);
3022   dest->capture_devices_hide = g_strdup(src->capture_devices_hide);
3023   dest->capture_prom_mode = src->capture_prom_mode;
3024   dest->capture_real_time = src->capture_real_time;
3025   dest->capture_auto_scroll = src->capture_auto_scroll;
3026   dest->capture_show_info = src->capture_show_info;
3027   dest->name_resolve = src->name_resolve;
3028   dest->name_resolve_concurrency = src->name_resolve_concurrency;
3029   dest->display_hidden_proto_items = src->display_hidden_proto_items;
3030
3031 }
3032
3033 /* Free a set of preferences. */
3034 void
3035 free_prefs(e_prefs *pr)
3036 {
3037   if (pr->pr_file != NULL) {
3038     g_free(pr->pr_file);
3039     pr->pr_file = NULL;
3040   }
3041   if (pr->pr_cmd != NULL) {
3042     g_free(pr->pr_cmd);
3043     pr->pr_cmd = NULL;
3044   }
3045   free_col_info(pr);
3046   if (pr->gui_font_name != NULL) {
3047     g_free(pr->gui_font_name);
3048     pr->gui_font_name = NULL;
3049   }
3050   if (pr->gui_fileopen_dir != NULL) {
3051     g_free(pr->gui_fileopen_dir);
3052     pr->gui_fileopen_dir = NULL;
3053   }
3054   g_free(pr->gui_webbrowser);
3055   pr->gui_webbrowser = NULL;
3056   if (pr->gui_window_title != NULL) {
3057     g_free(pr->gui_window_title);
3058     pr->gui_window_title = NULL;
3059   }
3060   if (pr->capture_device != NULL) {
3061     g_free(pr->capture_device);
3062     pr->capture_device = NULL;
3063   }
3064   if (pr->capture_devices_linktypes != NULL) {
3065     g_free(pr->capture_devices_linktypes);
3066     pr->capture_devices_linktypes = NULL;
3067   }
3068   if (pr->capture_devices_descr != NULL) {
3069     g_free(pr->capture_devices_descr);
3070     pr->capture_devices_descr = NULL;
3071   }
3072   if (pr->capture_devices_hide != NULL) {
3073     g_free(pr->capture_devices_hide);
3074     pr->capture_devices_hide = NULL;
3075   }
3076 }
3077
3078 static void
3079 free_col_info(e_prefs *pr)
3080 {
3081   fmt_data *cfmt;
3082
3083   while (pr->col_list != NULL) {
3084     cfmt = pr->col_list->data;
3085     g_free(cfmt->title);
3086     g_free(cfmt->fmt);
3087     if (cfmt->custom_field) {
3088       g_free(cfmt->custom_field);
3089     }
3090     g_free(cfmt);
3091     pr->col_list = g_list_remove_link(pr->col_list, pr->col_list);
3092   }
3093   g_list_free(pr->col_list);
3094   pr->col_list = NULL;
3095 }
3096
3097