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