Support empty column titles.
[metze/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    6
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", "Info",        "%i"};
1124
1125   if (prefs_initialized)
1126     return;
1127
1128   uat_load_all();
1129
1130   prefs.pr_format  = PR_FMT_TEXT;
1131   prefs.pr_dest    = PR_DEST_CMD;
1132   prefs.pr_file    = g_strdup("wireshark.out");
1133   prefs.pr_cmd     = g_strdup("lpr");
1134   prefs.col_list = NULL;
1135   for (i = 0; i < DEF_NUM_COLS; i++) {
1136     cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
1137     cfmt->title = g_strdup(col_fmt[i * 2]);
1138     cfmt->fmt   = g_strdup(col_fmt[(i * 2) + 1]);
1139     cfmt->visible = TRUE;
1140     cfmt->resolved = TRUE;
1141     cfmt->custom_field = NULL;
1142     cfmt->custom_occurrence = 0;
1143     prefs.col_list = g_list_append(prefs.col_list, cfmt);
1144   }
1145   prefs.num_cols  = DEF_NUM_COLS;
1146   prefs.st_client_fg.pixel =     0;
1147   prefs.st_client_fg.red   = 32767;
1148   prefs.st_client_fg.green =     0;
1149   prefs.st_client_fg.blue  =     0;
1150   prefs.st_client_bg.pixel =     0;
1151   prefs.st_client_bg.red   = 64507;
1152   prefs.st_client_bg.green = 60909;
1153   prefs.st_client_bg.blue  = 60909;
1154   prefs.st_server_fg.pixel =     0;
1155   prefs.st_server_fg.red   =     0;
1156   prefs.st_server_fg.green =     0;
1157   prefs.st_server_fg.blue  = 32767;
1158   prefs.st_server_bg.pixel =     0;
1159   prefs.st_server_bg.red   = 60909;
1160   prefs.st_server_bg.green = 60909;
1161   prefs.st_server_bg.blue  = 64507;
1162   prefs.gui_scrollbar_on_right = TRUE;
1163   prefs.gui_plist_sel_browse = FALSE;
1164   prefs.gui_ptree_sel_browse = FALSE;
1165   prefs.gui_altern_colors = FALSE;
1166   prefs.gui_ptree_line_style = 0;
1167   prefs.gui_ptree_expander_style = 1;
1168   prefs.gui_hex_dump_highlight_style = 1;
1169   prefs.filter_toolbar_show_in_statusbar = FALSE;
1170   prefs.gui_toolbar_main_style = TB_STYLE_ICONS;
1171   prefs.gui_toolbar_filter_style = TB_STYLE_TEXT;
1172 #ifdef _WIN32
1173   prefs.gui_font_name = g_strdup("Lucida Console 10");
1174 #else
1175   /*
1176    * XXX - for now, we make the initial font name a pattern that matches
1177    * only ISO 8859/1 fonts, so that we don't match 2-byte fonts such
1178    * as ISO 10646 fonts.
1179    *
1180    * Users in locales using other one-byte fonts will have to choose
1181    * a different font from the preferences dialog - or put the font
1182    * selection in the global preferences file to make that font the
1183    * default for all users who don't explicitly specify a different
1184    * font.
1185    *
1186    * Making this a font set rather than a font has two problems:
1187    *
1188    *    1) as far as I know, you can't select font sets with the
1189    *       font selection dialog;
1190    *
1191    *  2) if you use a font set, the text to be drawn must be a
1192    *       multi-byte string in the appropriate locale, but
1193    *       Wireshark does *NOT* guarantee that's the case - in
1194    *       the hex-dump window, each character in the text portion
1195    *       of the display must be a *single* byte, and in the
1196    *       packet-list and protocol-tree windows, text extracted
1197    *       from the packet is not necessarily in the right format.
1198    *
1199    * "Doing this right" may, for the packet-list and protocol-tree
1200    * windows, require that dissectors know what the locale is
1201    * *AND* know what locale and text representation is used in
1202    * the packets they're dissecting, and may be impossible in
1203    * the hex-dump window (except by punting and displaying only
1204    * ASCII characters).
1205    *
1206    * GTK+ 2.0 may simplify part of the problem, as it will, as I
1207    * understand it, use UTF-8-encoded Unicode as its internal
1208    * character set; however, we'd still have to know whatever
1209    * character set and encoding is used in the packet (which
1210    * may differ for different protocols, e.g. SMB might use
1211    * PC code pages for some strings and Unicode for others, whilst
1212    * NFS might use some UNIX character set encoding, e.g. ISO 8859/x,
1213    * or one of the EUC character sets for Asian languages, or one
1214    * of the other multi-byte character sets, or UTF-8, or...).
1215    *
1216    * I.e., as far as I can tell, "internationalizing" the packet-list,
1217    * protocol-tree, and hex-dump windows involves a lot more than, say,
1218    * just using font sets rather than fonts.
1219    */
1220   /* XXX - the above comment was about the GTK1 font stuff, just remove this comment now */
1221   /* XXX- is this the correct default font name for GTK2 none win32? */
1222   prefs.gui_font_name = g_strdup("Monospace 10");
1223 #endif
1224   prefs.gui_marked_fg.pixel        =     65535;
1225   prefs.gui_marked_fg.red          =     65535;
1226   prefs.gui_marked_fg.green        =     65535;
1227   prefs.gui_marked_fg.blue         =     65535;
1228   prefs.gui_marked_bg.pixel        =         0;
1229   prefs.gui_marked_bg.red          =         0;
1230   prefs.gui_marked_bg.green        =         0;
1231   prefs.gui_marked_bg.blue         =         0;
1232   prefs.gui_ignored_fg.pixel       =     32767;
1233   prefs.gui_ignored_fg.red         =     32767;
1234   prefs.gui_ignored_fg.green       =     32767;
1235   prefs.gui_ignored_fg.blue        =     32767;
1236   prefs.gui_ignored_bg.pixel       =     65535;
1237   prefs.gui_ignored_bg.red         =     65535;
1238   prefs.gui_ignored_bg.green       =     65535;
1239   prefs.gui_ignored_bg.blue        =     65535;
1240   prefs.gui_colorized_fg           = g_strdup("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000");
1241   prefs.gui_colorized_bg           = g_strdup("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0");
1242   prefs.gui_geometry_save_position =         FALSE;
1243   prefs.gui_geometry_save_size     =         TRUE;
1244   prefs.gui_geometry_save_maximized=         TRUE;
1245   prefs.gui_macosx_style           = TRUE;
1246   prefs.gui_console_open           = console_open_never;
1247   prefs.gui_fileopen_style         = FO_STYLE_LAST_OPENED;
1248   prefs.gui_recent_df_entries_max  = 10;
1249   prefs.gui_recent_files_count_max = 10;
1250   prefs.gui_fileopen_dir           = g_strdup(get_persdatafile_dir());
1251   prefs.gui_fileopen_preview       = 3;
1252   prefs.gui_ask_unsaved            = TRUE;
1253   prefs.gui_find_wrap              = TRUE;
1254   prefs.gui_use_pref_save          = FALSE;
1255   prefs.gui_webbrowser             = g_strdup(HTML_VIEWER " %s");
1256   prefs.gui_window_title           = g_strdup("");
1257   prefs.gui_start_title            = g_strdup("The World's Most Popular Network Protocol Analyzer");
1258   prefs.gui_version_in_start_page  = FALSE;
1259   prefs.gui_layout_type            = layout_type_5;
1260   prefs.gui_layout_content_1       = layout_pane_content_plist;
1261   prefs.gui_layout_content_2       = layout_pane_content_pdetails;
1262   prefs.gui_layout_content_3       = layout_pane_content_pbytes;
1263   prefs.console_log_level          =
1264       G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR;
1265
1266 /* set the default values for the capture dialog box */
1267   prefs.capture_device                = NULL;
1268   prefs.capture_devices_linktypes     = NULL;
1269   prefs.capture_devices_descr         = NULL;
1270   prefs.capture_devices_hide          = NULL;
1271   prefs.capture_devices_monitor_mode  = NULL;
1272   prefs.capture_prom_mode             = TRUE;
1273   prefs.capture_pcap_ng               = FALSE;
1274   prefs.capture_real_time             = TRUE;
1275   prefs.capture_auto_scroll           = TRUE;
1276   prefs.capture_show_info             = FALSE;
1277
1278 /* set the default values for the name resolution dialog box */
1279   prefs.name_resolve             = RESOLV_ALL ^ RESOLV_NETWORK;
1280   prefs.name_resolve_concurrency = 500;
1281   prefs.load_smi_modules         = FALSE;
1282   prefs.suppress_smi_errors      = FALSE;
1283
1284 /* set the default values for the tap/statistics dialog box */
1285   prefs.tap_update_interval    = TAP_UPDATE_DEFAULT_INTERVAL;
1286   prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
1287
1288   prefs.display_hidden_proto_items = FALSE;
1289
1290   prefs_initialized = TRUE;
1291 }
1292
1293 /* Reset preferences */
1294 void
1295 prefs_reset(void)
1296 {
1297   prefs_initialized = FALSE;
1298
1299   g_free(prefs.pr_file);
1300   g_free(prefs.pr_cmd);
1301   free_col_info(&prefs);
1302   g_free(prefs.gui_font_name);
1303   g_free(prefs.gui_colorized_fg);
1304   g_free(prefs.gui_colorized_bg);
1305   g_free(prefs.gui_fileopen_dir);
1306   g_free(prefs.gui_webbrowser);
1307   g_free(prefs.gui_window_title);
1308   g_free(prefs.gui_start_title);
1309   g_free(prefs.capture_device);
1310   g_free(prefs.capture_devices_linktypes);
1311   g_free(prefs.capture_devices_descr);
1312   g_free(prefs.capture_devices_hide);
1313   g_free(prefs.capture_devices_monitor_mode);
1314
1315   uat_unload_all();
1316   oids_cleanup();
1317   init_prefs();
1318 }
1319
1320 /* Read the preferences file, fill in "prefs", and return a pointer to it.
1321
1322    If we got an error (other than "it doesn't exist") trying to read
1323    the global preferences file, stuff the errno into "*gpf_errno_return"
1324    and a pointer to the path of the file into "*gpf_path_return", and
1325    return NULL.
1326
1327    If we got an error (other than "it doesn't exist") trying to read
1328    the user's preferences file, stuff the errno into "*pf_errno_return"
1329    and a pointer to the path of the file into "*pf_path_return", and
1330    return NULL. */
1331 e_prefs *
1332 read_prefs(int *gpf_errno_return, int *gpf_read_errno_return,
1333            char **gpf_path_return, int *pf_errno_return,
1334            int *pf_read_errno_return, char **pf_path_return)
1335 {
1336   int         err;
1337   char        *pf_path;
1338   FILE        *pf;
1339
1340   /* clean up libsmi structures before reading prefs */
1341   if (prefs.load_smi_modules) {
1342     oids_cleanup();
1343   }
1344
1345   init_prefs();
1346
1347   /*
1348    * If we don't already have the pathname of the global preferences
1349    * file, construct it.  Then, in either case, try to open the file.
1350    */
1351   if (gpf_path == NULL) {
1352     /*
1353      * We don't have the path; try the new path first, and, if that
1354      * file doesn't exist, try the old path.
1355      */
1356     gpf_path = get_datafile_path(PF_NAME);
1357     if ((pf = ws_fopen(gpf_path, "r")) == NULL && errno == ENOENT) {
1358       /*
1359        * It doesn't exist by the new name; try the old name.
1360        */
1361       g_free(gpf_path);
1362       gpf_path = get_datafile_path(OLD_GPF_NAME);
1363       pf = ws_fopen(gpf_path, "r");
1364     }
1365   } else {
1366     /*
1367      * We have the path; try it.
1368      */
1369     pf = ws_fopen(gpf_path, "r");
1370   }
1371
1372   /*
1373    * If we were able to open the file, read it.
1374    * XXX - if it failed for a reason other than "it doesn't exist",
1375    * report the error.
1376    */
1377   *gpf_path_return = NULL;
1378   if (pf != NULL) {
1379     /*
1380      * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
1381      * seen.
1382      */
1383     mgcp_tcp_port_count = 0;
1384     mgcp_udp_port_count = 0;
1385
1386     /* We succeeded in opening it; read it. */
1387     err = read_prefs_file(gpf_path, pf, set_pref, NULL);
1388     if (err != 0) {
1389       /* We had an error reading the file; return the errno and the
1390          pathname, so our caller can report the error. */
1391       *gpf_errno_return = 0;
1392       *gpf_read_errno_return = err;
1393       *gpf_path_return = gpf_path;
1394     }
1395     fclose(pf);
1396   } else {
1397     /* We failed to open it.  If we failed for some reason other than
1398        "it doesn't exist", return the errno and the pathname, so our
1399        caller can report the error. */
1400     if (errno != ENOENT) {
1401       *gpf_errno_return = errno;
1402       *gpf_read_errno_return = 0;
1403       *gpf_path_return = gpf_path;
1404     }
1405   }
1406
1407   /* Construct the pathname of the user's preferences file. */
1408   pf_path = get_persconffile_path(PF_NAME, TRUE, FALSE);
1409
1410   /* Read the user's preferences file, if it exists. */
1411   *pf_path_return = NULL;
1412   if ((pf = ws_fopen(pf_path, "r")) != NULL) {
1413     /*
1414      * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
1415      * seen.
1416      */
1417     mgcp_tcp_port_count = 0;
1418     mgcp_udp_port_count = 0;
1419
1420     /* We succeeded in opening it; read it. */
1421     err = read_prefs_file(pf_path, pf, set_pref, NULL);
1422     if (err != 0) {
1423       /* We had an error reading the file; return the errno and the
1424          pathname, so our caller can report the error. */
1425       *pf_errno_return = 0;
1426       *pf_read_errno_return = err;
1427       *pf_path_return = pf_path;
1428     } else
1429       g_free(pf_path);
1430     fclose(pf);
1431   } else {
1432     /* We failed to open it.  If we failed for some reason other than
1433        "it doesn't exist", return the errno and the pathname, so our
1434        caller can report the error. */
1435     if (errno != ENOENT) {
1436       *pf_errno_return = errno;
1437       *pf_read_errno_return = 0;
1438       *pf_path_return = pf_path;
1439     } else
1440       g_free(pf_path);
1441   }
1442
1443   /* load SMI modules if needed */
1444   if (prefs.load_smi_modules) {
1445     oids_init();
1446   }
1447
1448   return &prefs;
1449 }
1450
1451 /* read the preferences file (or similiar) and call the callback
1452  * function to set each key/value pair found */
1453 int
1454 read_prefs_file(const char *pf_path, FILE *pf,
1455                 pref_set_pair_cb pref_set_pair_fct, void *private_data)
1456 {
1457   enum { START, IN_VAR, PRE_VAL, IN_VAL, IN_SKIP };
1458   int       got_c, state = START;
1459   GString  *cur_val;
1460   GString  *cur_var;
1461   gboolean  got_val = FALSE;
1462   gint      fline = 1, pline = 1;
1463   gchar     hint[] = "(applying your preferences once should remove this warning)";
1464
1465   cur_val = g_string_new("");
1466   cur_var = g_string_new("");
1467
1468   while ((got_c = getc(pf)) != EOF) {
1469     if (got_c == '\n') {
1470       state = START;
1471       fline++;
1472       continue;
1473     }
1474
1475     switch (state) {
1476       case START:
1477         if (isalnum(got_c)) {
1478           if (cur_var->len > 0) {
1479             if (got_val) {
1480               /*  Convert the string to a range.  Since we're reading the
1481                *  preferences file, silently lower values in excess of the
1482                *  range's maximum.
1483                */
1484               switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, FALSE)) {
1485
1486               case PREFS_SET_OK:
1487                 break;
1488
1489               case PREFS_SET_SYNTAX_ERR:
1490                 g_warning ("%s line %d: Syntax error in preference %s %s", pf_path, pline, cur_var->str, hint);
1491                 break;
1492
1493               case PREFS_SET_NO_SUCH_PREF:
1494                 g_warning ("%s line %d: No such preference \"%s\" %s", pf_path,
1495                                 pline, cur_var->str, hint);
1496                 break;
1497
1498               case PREFS_SET_OBSOLETE:
1499                 /* We silently ignore attempts to set these; it's
1500                    probably not the user's fault that it's in there -
1501                    they may have saved preferences with a release that
1502                    supported them. */
1503                 break;
1504               }
1505             } else {
1506               g_warning ("%s line %d: Incomplete preference %s", pf_path, pline, hint);
1507             }
1508           }
1509           state      = IN_VAR;
1510           got_val    = FALSE;
1511           g_string_truncate(cur_var, 0);
1512           g_string_append_c(cur_var, (gchar) got_c);
1513           pline = fline;
1514         } else if (isspace(got_c) && cur_var->len > 0 && got_val) {
1515           state = PRE_VAL;
1516         } else if (got_c == '#') {
1517           state = IN_SKIP;
1518         } else {
1519           g_warning ("%s line %d: Malformed line %s", pf_path, fline, hint);
1520         }
1521         break;
1522       case IN_VAR:
1523         if (got_c != ':') {
1524           g_string_append_c(cur_var, (gchar) got_c);
1525         } else {
1526           state   = PRE_VAL;
1527           g_string_truncate(cur_val, 0);
1528           got_val = TRUE;
1529         }
1530         break;
1531       case PRE_VAL:
1532         if (!isspace(got_c)) {
1533           state = IN_VAL;
1534           g_string_append_c(cur_val, (gchar) got_c);
1535         }
1536         break;
1537       case IN_VAL:
1538         g_string_append_c(cur_val, (gchar) got_c);
1539         break;
1540     }
1541   }
1542   if (cur_var->len > 0) {
1543     if (got_val) {
1544       /*  Convert the string to a range.  Since we're reading the
1545        *  preferences file, silently lower values in excess of the
1546        *  range's maximum.
1547        */
1548       switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, FALSE)) {
1549
1550       case PREFS_SET_OK:
1551         break;
1552
1553       case PREFS_SET_SYNTAX_ERR:
1554         g_warning ("%s line %d: Syntax error in preference %s %s", pf_path, pline, cur_var->str, hint);
1555         break;
1556
1557       case PREFS_SET_NO_SUCH_PREF:
1558         g_warning ("%s line %d: No such preference \"%s\" %s", pf_path,
1559                         pline, cur_var->str, hint);
1560         break;
1561
1562       case PREFS_SET_OBSOLETE:
1563         /* We silently ignore attempts to set these; it's probably not
1564            the user's fault that it's in there - they may have saved
1565            preferences with a release that supported it. */
1566         break;
1567       }
1568     } else {
1569       g_warning ("%s line %d: Incomplete preference %s", pf_path, pline, hint);
1570     }
1571   }
1572
1573   g_string_free(cur_val, TRUE);
1574   g_string_free(cur_var, TRUE);
1575
1576   if (ferror(pf))
1577     return errno;
1578   else
1579     return 0;
1580 }
1581
1582 /*
1583  * If we were handed a preference starting with "uat:", try to turn it into
1584  * a valid uat entry.
1585  */
1586 static gboolean
1587 prefs_set_uat_pref(char *uat_entry) {
1588         gchar *p, *colonp;
1589         uat_t *uat;
1590         gchar *err;
1591
1592         colonp = strchr(uat_entry, ':');
1593         if (colonp == NULL)
1594                 return FALSE;
1595
1596         p = colonp;
1597         *p++ = '\0';
1598
1599         /*
1600          * Skip over any white space (there probably won't be any, but
1601          * as we allow it in the preferences file, we might as well
1602          * allow it here).
1603          */
1604         while (isspace((guchar)*p))
1605                 p++;
1606         if (*p == '\0') {
1607                 /*
1608                  * Put the colon back, so if our caller uses, in an
1609                  * error message, the string they passed us, the message
1610                  * looks correct.
1611                  */
1612                 *colonp = ':';
1613                 return FALSE;
1614         }
1615
1616         uat = uat_find(uat_entry);
1617         *colonp = ':';
1618         if (uat == NULL) {
1619                 return FALSE;
1620         }
1621
1622         if (uat_load_str(uat, p, &err)) {
1623                 return TRUE;
1624         }
1625         return FALSE;
1626 }
1627
1628 /*
1629  * Given a string of the form "<pref name>:<pref value>", as might appear
1630  * as an argument to a "-o" option, parse it and set the preference in
1631  * question.  Return an indication of whether it succeeded or failed
1632  * in some fashion.
1633  */
1634 prefs_set_pref_e
1635 prefs_set_pref(char *prefarg)
1636 {
1637         gchar *p, *colonp;
1638         prefs_set_pref_e ret;
1639
1640         /*
1641          * Set the counters of "mgcp.{tcp,udp}.port" entries we've
1642          * seen to values that keep us from trying to interpret tham
1643          * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
1644          * as, from the command line, we have no way of guessing which
1645          * the user had in mind.
1646          */
1647         mgcp_tcp_port_count = -1;
1648         mgcp_udp_port_count = -1;
1649
1650         colonp = strchr(prefarg, ':');
1651         if (colonp == NULL)
1652                 return PREFS_SET_SYNTAX_ERR;
1653
1654         p = colonp;
1655         *p++ = '\0';
1656
1657         /*
1658          * Skip over any white space (there probably won't be any, but
1659          * as we allow it in the preferences file, we might as well
1660          * allow it here).
1661          */
1662         while (isspace((guchar)*p))
1663                 p++;
1664         if (*p == '\0') {
1665                 /*
1666                  * Put the colon back, so if our caller uses, in an
1667                  * error message, the string they passed us, the message
1668                  * looks correct.
1669                  */
1670                 *colonp = ':';
1671                 return PREFS_SET_SYNTAX_ERR;
1672         }
1673         if (strcmp(prefarg, "uat")) {
1674                 ret = set_pref(prefarg, p, NULL, TRUE);
1675         } else {
1676                 ret = prefs_set_uat_pref(p) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
1677         }
1678         *colonp = ':';  /* put the colon back */
1679         return ret;
1680 }
1681
1682 /*
1683  * Returns TRUE if the given device is hidden
1684  */
1685 gboolean
1686 prefs_is_capture_device_hidden(const char *name)
1687 {
1688         gchar *tok, *devices;
1689         size_t len;
1690
1691         if (prefs.capture_devices_hide && name) {
1692                 devices = g_strdup (prefs.capture_devices_hide);
1693                 len = strlen (name);
1694                 for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
1695                         if (strlen (tok) == len && strcmp (name, tok) == 0) {
1696                                 g_free (devices);
1697                                 return TRUE;
1698                         }
1699                 }
1700                 g_free (devices);
1701         }
1702
1703         return FALSE;
1704 }
1705
1706 /*
1707  * Returns TRUE if the given column is hidden
1708  */
1709 static gboolean
1710 prefs_is_column_hidden(const gchar *cols_hidden, const char *fmt)
1711 {
1712         gchar *tok, *cols;
1713         size_t len;
1714
1715         if (cols_hidden && fmt) {
1716                 cols = g_strdup (cols_hidden);
1717                 len = strlen (fmt);
1718                 for (tok = strtok (cols, ","); tok; tok = strtok(NULL, ",")) {
1719                         tok = g_strstrip (tok);
1720                         if (strlen (tok) == len && strcmp (fmt, tok) == 0) {
1721                                 g_free (cols);
1722                                 return TRUE;
1723                         }
1724                 }
1725                 g_free (cols);
1726         }
1727
1728         return FALSE;
1729 }
1730
1731 /*
1732  * Returns TRUE if the given device should capture in monitor mode by default
1733  */
1734 gboolean
1735 prefs_capture_device_monitor_mode(const char *name)
1736 {
1737         gchar *tok, *devices;
1738         size_t len;
1739
1740         if (prefs.capture_devices_monitor_mode && name) {
1741                 devices = g_strdup (prefs.capture_devices_monitor_mode);
1742                 len = strlen (name);
1743                 for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
1744                         if (strlen (tok) == len && strcmp (name, tok) == 0) {
1745                                 g_free (devices);
1746                                 return TRUE;
1747                         }
1748                 }
1749                 g_free (devices);
1750         }
1751
1752         return FALSE;
1753 }
1754
1755 #define PRS_PRINT_FMT                    "print.format"
1756 #define PRS_PRINT_DEST                   "print.destination"
1757 #define PRS_PRINT_FILE                   "print.file"
1758 #define PRS_PRINT_CMD                    "print.command"
1759 #define PRS_COL_HIDDEN                   "column.hidden"
1760 #define PRS_COL_FMT                      "column.format"
1761 #define PRS_STREAM_CL_FG                 "stream.client.fg"
1762 #define PRS_STREAM_CL_BG                 "stream.client.bg"
1763 #define PRS_STREAM_SR_FG                 "stream.server.fg"
1764 #define PRS_STREAM_SR_BG                 "stream.server.bg"
1765 #define PRS_GUI_SCROLLBAR_ON_RIGHT       "gui.scrollbar_on_right"
1766 #define PRS_GUI_PLIST_SEL_BROWSE         "gui.packet_list_sel_browse"
1767 #define PRS_GUI_PTREE_SEL_BROWSE         "gui.protocol_tree_sel_browse"
1768 #define PRS_GUI_ALTERN_COLORS            "gui.tree_view_altern_colors"
1769 #define PRS_GUI_FILTER_TOOLBAR_IN_STATUSBAR "gui.filter_toolbar_show_in_statusbar"
1770 #define PRS_GUI_PTREE_LINE_STYLE         "gui.protocol_tree_line_style"
1771 #define PRS_GUI_PTREE_EXPANDER_STYLE     "gui.protocol_tree_expander_style"
1772 #define PRS_GUI_HEX_DUMP_HIGHLIGHT_STYLE "gui.hex_dump_highlight_style"
1773 #define PRS_GUI_FONT_NAME_1              "gui.font_name"
1774 #define PRS_GUI_FONT_NAME_2              "gui.gtk2.font_name"
1775 #define PRS_GUI_MARKED_FG                "gui.marked_frame.fg"
1776 #define PRS_GUI_MARKED_BG                "gui.marked_frame.bg"
1777 #define PRS_GUI_IGNORED_FG               "gui.ignored_frame.fg"
1778 #define PRS_GUI_IGNORED_BG               "gui.ignored_frame.bg"
1779 #define PRS_GUI_COLORIZED_FG             "gui.colorized_frame.fg"
1780 #define PRS_GUI_COLORIZED_BG             "gui.colorized_frame.bg"
1781 #define PRS_GUI_CONSOLE_OPEN             "gui.console_open"
1782 #define PRS_GUI_FILEOPEN_STYLE           "gui.fileopen.style"
1783 #define PRS_GUI_RECENT_COUNT_MAX         "gui.recent_files_count.max"
1784 #define PRS_GUI_RECENT_DF_ENTRIES_MAX    "gui.recent_display_filter_entries.max"
1785 #define PRS_GUI_FILEOPEN_DIR             "gui.fileopen.dir"
1786 #define PRS_GUI_FILEOPEN_REMEMBERED_DIR  "gui.fileopen.remembered_dir"
1787 #define PRS_GUI_FILEOPEN_PREVIEW         "gui.fileopen.preview"
1788 #define PRS_GUI_ASK_UNSAVED              "gui.ask_unsaved"
1789 #define PRS_GUI_FIND_WRAP                "gui.find_wrap"
1790 #define PRS_GUI_USE_PREF_SAVE            "gui.use_pref_save"
1791 #define PRS_GUI_GEOMETRY_SAVE_POSITION   "gui.geometry.save.position"
1792 #define PRS_GUI_GEOMETRY_SAVE_SIZE       "gui.geometry.save.size"
1793 #define PRS_GUI_GEOMETRY_SAVE_MAXIMIZED  "gui.geometry.save.maximized"
1794 #define PRS_GUI_MACOSX_STYLE             "gui.macosx_style"
1795 #define PRS_GUI_GEOMETRY_MAIN_X          "gui.geometry.main.x"
1796 #define PRS_GUI_GEOMETRY_MAIN_Y          "gui.geometry.main.y"
1797 #define PRS_GUI_GEOMETRY_MAIN_WIDTH      "gui.geometry.main.width"
1798 #define PRS_GUI_GEOMETRY_MAIN_HEIGHT     "gui.geometry.main.height"
1799 #define PRS_GUI_TOOLBAR_MAIN_SHOW        "gui.toolbar_main_show"
1800 #define PRS_GUI_TOOLBAR_MAIN_STYLE       "gui.toolbar_main_style"
1801 #define PRS_GUI_TOOLBAR_FILTER_STYLE     "gui.toolbar_filter_style"
1802 #define PRS_GUI_WEBBROWSER               "gui.webbrowser"
1803 #define PRS_GUI_WINDOW_TITLE             "gui.window_title"
1804 #define PRS_GUI_START_TITLE              "gui.start_title"
1805 #define PRS_GUI_VERSION_IN_START_PAGE    "gui.version_in_start_page"
1806 #define PRS_GUI_LAYOUT_TYPE              "gui.layout_type"
1807 #define PRS_GUI_LAYOUT_CONTENT_1         "gui.layout_content_1"
1808 #define PRS_GUI_LAYOUT_CONTENT_2         "gui.layout_content_2"
1809 #define PRS_GUI_LAYOUT_CONTENT_3         "gui.layout_content_3"
1810 #define PRS_CONSOLE_LOG_LEVEL            "console.log.level"
1811
1812 /*
1813  * This applies to more than just captures, so it's not "capture.name_resolve";
1814  * "capture.name_resolve" is supported on input for backwards compatibility.
1815  *
1816  * It's not a preference for a particular part of Wireshark, it's used all
1817  * over the place, so its name doesn't have two components.
1818  */
1819 #define PRS_NAME_RESOLVE "name_resolve"
1820 #define PRS_NAME_RESOLVE_CONCURRENCY "name_resolve_concurrency"
1821 #define PRS_NAME_RESOLVE_LOAD_SMI_MODULES "name_resolve_load_smi_modules"
1822 #define PRS_NAME_RESOLVE_SUPPRESS_SMI_ERRORS "name_resolve_suppress_smi_errors"
1823 #define PRS_CAP_NAME_RESOLVE "capture.name_resolve"
1824
1825 /*  values for the capture dialog box */
1826 #define PRS_CAP_DEVICE               "capture.device"
1827 #define PRS_CAP_DEVICES_LINKTYPES    "capture.devices_linktypes"
1828 #define PRS_CAP_DEVICES_DESCR        "capture.devices_descr"
1829 #define PRS_CAP_DEVICES_HIDE         "capture.devices_hide"
1830 #define PRS_CAP_DEVICES_MONITOR_MODE "capture.devices_monitor_mode"
1831 #define PRS_CAP_PROM_MODE            "capture.prom_mode"
1832 #define PRS_CAP_PCAP_NG              "capture.pcap_ng"
1833 #define PRS_CAP_REAL_TIME            "capture.real_time_update"
1834 #define PRS_CAP_AUTO_SCROLL          "capture.auto_scroll"
1835 #define PRS_CAP_SHOW_INFO            "capture.show_info"
1836
1837 #define RED_COMPONENT(x)   (guint16) (((((x) >> 16) & 0xff) * 65535 / 255))
1838 #define GREEN_COMPONENT(x) (guint16) (((((x) >>  8) & 0xff) * 65535 / 255))
1839 #define BLUE_COMPONENT(x)  (guint16) ( (((x)        & 0xff) * 65535 / 255))
1840
1841 /*  values for the rtp player preferences dialog box */
1842 #define PRS_TAP_UPDATE_INTERVAL           "taps.update_interval"
1843 #define PRS_RTP_PLAYER_MAX_VISIBLE        "taps.rtp_player_max_visible"
1844
1845 #define PRS_DISPLAY_HIDDEN_PROTO_ITEMS          "packet_list.display_hidden_proto_items"
1846
1847 static const gchar *pr_formats[] = { "text", "postscript" };
1848 static const gchar *pr_dests[]   = { "command", "file" };
1849
1850 typedef struct {
1851   char    letter;
1852   guint32 value;
1853 } name_resolve_opt_t;
1854
1855 static name_resolve_opt_t name_resolve_opt[] = {
1856   { 'm', RESOLV_MAC },
1857   { 'n', RESOLV_NETWORK },
1858   { 't', RESOLV_TRANSPORT },
1859   { 'C', RESOLV_CONCURRENT },
1860 };
1861
1862 #define N_NAME_RESOLVE_OPT      (sizeof name_resolve_opt / sizeof name_resolve_opt[0])
1863
1864 static const char *
1865 name_resolve_to_string(guint32 name_resolve)
1866 {
1867   static char string[N_NAME_RESOLVE_OPT+1];
1868   char *p;
1869   unsigned int i;
1870   gboolean all_opts_set = TRUE;
1871
1872   if (name_resolve == RESOLV_NONE)
1873     return "FALSE";
1874   p = &string[0];
1875   for (i = 0; i < N_NAME_RESOLVE_OPT; i++) {
1876     if (name_resolve & name_resolve_opt[i].value)
1877       *p++ =  name_resolve_opt[i].letter;
1878     else
1879       all_opts_set = FALSE;
1880   }
1881   *p = '\0';
1882   if (all_opts_set)
1883     return "TRUE";
1884   return string;
1885 }
1886
1887 char
1888 string_to_name_resolve(char *string, guint32 *name_resolve)
1889 {
1890   char c;
1891   unsigned int i;
1892
1893   *name_resolve = 0;
1894   while ((c = *string++) != '\0') {
1895     for (i = 0; i < N_NAME_RESOLVE_OPT; i++) {
1896       if (c == name_resolve_opt[i].letter) {
1897         *name_resolve |= name_resolve_opt[i].value;
1898         break;
1899       }
1900     }
1901     if (i == N_NAME_RESOLVE_OPT) {
1902       /*
1903        * Unrecognized letter.
1904        */
1905       return c;
1906     }
1907   }
1908   return '\0';
1909 }
1910
1911 static void
1912 try_convert_to_custom_column(gpointer *el_data)
1913 {
1914     /* Array of columns that have been migrated to custom columns */
1915     struct {
1916         gint el;
1917         gchar *col_expr;
1918     } migrated_columns[] = {
1919         { COL_COS_VALUE, "vlan.priority" },
1920         { COL_CIRCUIT_ID, "iax2.call" },
1921         { COL_BSSGP_TLLI, "bssgp.tlli" },
1922         { COL_HPUX_SUBSYS, "nettl.subsys" },
1923         { COL_HPUX_DEVID, "nettl.devid" },
1924         { COL_FR_DLCI, "fr.dlci" },
1925         { COL_REL_CONV_TIME, "tcp.time_relative" },
1926         { COL_DELTA_CONV_TIME, "tcp.time_delta" },
1927         { COL_OXID, "fc.ox_id" },
1928         { COL_RXID, "fc.rx_id" },
1929         { COL_SRCIDX, "mdshdr.srcidx" },
1930         { COL_DSTIDX, "mdshdr.dstidx" },
1931         { COL_DCE_CTX, "dcerpc.cn_ctx_id" }
1932     };
1933
1934     guint haystack_idx;
1935     const gchar *haystack_fmt;
1936
1937     gchar **fmt = (gchar **) el_data;
1938
1939     for (haystack_idx = 0;
1940          haystack_idx < G_N_ELEMENTS(migrated_columns);
1941          ++haystack_idx) {
1942
1943         haystack_fmt = col_format_to_string(migrated_columns[haystack_idx].el);
1944         if (strcmp(haystack_fmt, *fmt) == 0) {
1945             gchar *cust_col = g_strdup_printf("%%Cus:%s:0",
1946                                 migrated_columns[haystack_idx].col_expr);
1947
1948             g_free(*fmt);
1949             *fmt = cust_col;
1950         }
1951     }
1952 }
1953
1954 static prefs_set_pref_e
1955 set_pref(gchar *pref_name, gchar *value, void *private_data _U_,
1956          gboolean return_range_errors)
1957 {
1958   GList    *col_l, *col_l_elt;
1959   gint      llen;
1960   fmt_data *cfmt;
1961   unsigned long int cval;
1962   guint    uval;
1963   gboolean bval;
1964   gint     enum_val;
1965   char     *p;
1966   gchar    *dotp, *last_dotp;
1967   module_t *module;
1968   pref_t   *pref;
1969   gboolean had_a_dot;
1970   gchar    **cust_format_info;
1971   const gchar *cust_format = col_format_to_string(COL_CUSTOM);
1972   size_t cust_format_len = strlen(cust_format);
1973
1974   if (strcmp(pref_name, PRS_PRINT_FMT) == 0) {
1975     if (strcmp(value, pr_formats[PR_FMT_TEXT]) == 0) {
1976       prefs.pr_format = PR_FMT_TEXT;
1977     } else if (strcmp(value, pr_formats[PR_FMT_PS]) == 0) {
1978       prefs.pr_format = PR_FMT_PS;
1979     } else {
1980       return PREFS_SET_SYNTAX_ERR;
1981     }
1982   } else if (strcmp(pref_name, PRS_PRINT_DEST) == 0) {
1983     if (strcmp(value, pr_dests[PR_DEST_CMD]) == 0) {
1984       prefs.pr_dest = PR_DEST_CMD;
1985     } else if (strcmp(value, pr_dests[PR_DEST_FILE]) == 0) {
1986       prefs.pr_dest = PR_DEST_FILE;
1987     } else {
1988       return PREFS_SET_SYNTAX_ERR;
1989     }
1990   } else if (strcmp(pref_name, PRS_PRINT_FILE) == 0) {
1991     g_free(prefs.pr_file);
1992     prefs.pr_file = g_strdup(value);
1993   } else if (strcmp(pref_name, PRS_PRINT_CMD) == 0) {
1994     g_free(prefs.pr_cmd);
1995     prefs.pr_cmd = g_strdup(value);
1996   } else if (strcmp(pref_name, PRS_COL_HIDDEN) == 0) {
1997     cols_hidden_list = g_strdup (value);
1998   } else if (strcmp(pref_name, PRS_COL_FMT) == 0) {
1999     col_l = prefs_get_string_list(value);
2000     if (col_l == NULL)
2001       return PREFS_SET_SYNTAX_ERR;
2002     if ((g_list_length(col_l) % 2) != 0) {
2003       /* A title didn't have a matching format.  */
2004       prefs_clear_string_list(col_l);
2005       return PREFS_SET_SYNTAX_ERR;
2006     }
2007     /* Check to make sure all column formats are valid.  */
2008     col_l_elt = g_list_first(col_l);
2009     while(col_l_elt) {
2010       /* Go past the title.  */
2011       col_l_elt = col_l_elt->next;
2012
2013       /* Check the format.  */
2014       if (strncmp(col_l_elt->data, cust_format, cust_format_len) != 0) {
2015         if (get_column_format_from_str(col_l_elt->data) == -1) {
2016           /* It's not a valid column format.  */
2017           prefs_clear_string_list(col_l);
2018           return PREFS_SET_SYNTAX_ERR;
2019         }
2020
2021         /* Some predefined columns have been migrated to use custom colums.
2022          * We'll convert these silently here */
2023         try_convert_to_custom_column(&col_l_elt->data);
2024       }
2025
2026       /* Go past the format.  */
2027       col_l_elt = col_l_elt->next;
2028     }
2029     free_col_info(&prefs);
2030     prefs.col_list = NULL;
2031     llen             = g_list_length(col_l);
2032     prefs.num_cols   = llen / 2;
2033     col_l_elt = g_list_first(col_l);
2034     while(col_l_elt) {
2035       gchar *prefs_fmt;
2036       cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
2037       cfmt->title    = g_strdup(col_l_elt->data);
2038       col_l_elt      = col_l_elt->next;
2039       if (strncmp(col_l_elt->data, cust_format, cust_format_len) == 0) {
2040         cfmt->fmt      = g_strdup(cust_format);
2041         prefs_fmt      = g_strdup(col_l_elt->data);
2042         cust_format_info = g_strsplit(&prefs_fmt[cust_format_len+1],":",3); /* add 1 for ':' */
2043         cfmt->custom_field = g_strdup(cust_format_info[0]);
2044         if (cfmt->custom_field && cust_format_info[1]) {
2045             cfmt->custom_occurrence = (int)strtol(cust_format_info[1],NULL,10);
2046         } else {
2047             cfmt->custom_occurrence = 0;
2048         }
2049         if (cfmt->custom_field && cust_format_info[1] && cust_format_info[2]) {
2050             cfmt->resolved = (cust_format_info[2][0] == 'U') ? FALSE : TRUE;
2051         } else {
2052             cfmt->resolved = TRUE;
2053         }
2054         g_strfreev(cust_format_info);
2055       } else {
2056         cfmt->fmt      = g_strdup(col_l_elt->data);
2057         prefs_fmt      = g_strdup(cfmt->fmt);
2058         cfmt->custom_field = NULL;
2059         cfmt->custom_occurrence = 0;
2060         cfmt->resolved  = TRUE;
2061       }
2062       cfmt->visible   = prefs_is_column_hidden (cols_hidden_list, prefs_fmt) ? FALSE : TRUE;
2063       g_free (prefs_fmt);
2064       col_l_elt      = col_l_elt->next;
2065       prefs.col_list = g_list_append(prefs.col_list, cfmt);
2066     }
2067     prefs_clear_string_list(col_l);
2068     g_free (cols_hidden_list);
2069     cols_hidden_list = NULL;
2070   } else if (strcmp(pref_name, PRS_STREAM_CL_FG) == 0) {
2071     cval = strtoul(value, NULL, 16);
2072     prefs.st_client_fg.pixel = 0;
2073     prefs.st_client_fg.red   = RED_COMPONENT(cval);
2074     prefs.st_client_fg.green = GREEN_COMPONENT(cval);
2075     prefs.st_client_fg.blue  = BLUE_COMPONENT(cval);
2076   } else if (strcmp(pref_name, PRS_STREAM_CL_BG) == 0) {
2077     cval = strtoul(value, NULL, 16);
2078     prefs.st_client_bg.pixel = 0;
2079     prefs.st_client_bg.red   = RED_COMPONENT(cval);
2080     prefs.st_client_bg.green = GREEN_COMPONENT(cval);
2081     prefs.st_client_bg.blue  = BLUE_COMPONENT(cval);
2082   } else if (strcmp(pref_name, PRS_STREAM_SR_FG) == 0) {
2083     cval = strtoul(value, NULL, 16);
2084     prefs.st_server_fg.pixel = 0;
2085     prefs.st_server_fg.red   = RED_COMPONENT(cval);
2086     prefs.st_server_fg.green = GREEN_COMPONENT(cval);
2087     prefs.st_server_fg.blue  = BLUE_COMPONENT(cval);
2088   } else if (strcmp(pref_name, PRS_STREAM_SR_BG) == 0) {
2089     cval = strtoul(value, NULL, 16);
2090     prefs.st_server_bg.pixel = 0;
2091     prefs.st_server_bg.red   = RED_COMPONENT(cval);
2092     prefs.st_server_bg.green = GREEN_COMPONENT(cval);
2093     prefs.st_server_bg.blue  = BLUE_COMPONENT(cval);
2094   } else if (strcmp(pref_name, PRS_GUI_SCROLLBAR_ON_RIGHT) == 0) {
2095     if (g_ascii_strcasecmp(value, "true") == 0) {
2096             prefs.gui_scrollbar_on_right = TRUE;
2097     }
2098     else {
2099             prefs.gui_scrollbar_on_right = FALSE;
2100     }
2101   } else if (strcmp(pref_name, PRS_GUI_PLIST_SEL_BROWSE) == 0) {
2102     if (g_ascii_strcasecmp(value, "true") == 0) {
2103             prefs.gui_plist_sel_browse = TRUE;
2104     }
2105     else {
2106             prefs.gui_plist_sel_browse = FALSE;
2107     }
2108   } else if (strcmp(pref_name, PRS_GUI_PTREE_SEL_BROWSE) == 0) {
2109     if (g_ascii_strcasecmp(value, "true") == 0) {
2110             prefs.gui_ptree_sel_browse = TRUE;
2111     }
2112     else {
2113             prefs.gui_ptree_sel_browse = FALSE;
2114     }
2115   } else if (strcmp(pref_name, PRS_GUI_ALTERN_COLORS) == 0) {
2116     if (g_ascii_strcasecmp(value, "true") == 0) {
2117             prefs.gui_altern_colors = TRUE;
2118     }
2119     else {
2120             prefs.gui_altern_colors = FALSE;
2121     }
2122   } else if (strcmp(pref_name, PRS_GUI_PTREE_LINE_STYLE) == 0) {
2123     prefs.gui_ptree_line_style =
2124         find_index_from_string_array(value, gui_ptree_line_style_text, 0);
2125   } else if (strcmp(pref_name, PRS_GUI_PTREE_EXPANDER_STYLE) == 0) {
2126     prefs.gui_ptree_expander_style =
2127         find_index_from_string_array(value, gui_ptree_expander_style_text, 1);
2128   } else if (strcmp(pref_name, PRS_GUI_HEX_DUMP_HIGHLIGHT_STYLE) == 0) {
2129     prefs.gui_hex_dump_highlight_style =
2130         find_index_from_string_array(value, gui_hex_dump_highlight_style_text, 1);
2131   } else if (strcmp(pref_name, PRS_GUI_FILTER_TOOLBAR_IN_STATUSBAR) == 0) {
2132     if (g_ascii_strcasecmp(value, "true") == 0) {
2133             prefs.filter_toolbar_show_in_statusbar = TRUE;
2134     }
2135     else {
2136             prefs.filter_toolbar_show_in_statusbar = FALSE;
2137     }
2138   } else if (strcmp(pref_name, PRS_GUI_TOOLBAR_MAIN_SHOW) == 0) {
2139     /* obsoleted by recent setting */
2140   } else if (strcmp(pref_name, PRS_GUI_TOOLBAR_MAIN_STYLE) == 0) {
2141     /* see main_toolbar.c for details, "icons only" is default */
2142         prefs.gui_toolbar_main_style =
2143             find_index_from_string_array(value, gui_toolbar_style_text,
2144                                      TB_STYLE_ICONS);
2145   } else if (strcmp(pref_name, PRS_GUI_TOOLBAR_FILTER_STYLE) == 0) {
2146     /* see main_filter_toolbar.c for details, "name only" is default */
2147         prefs.gui_toolbar_filter_style =
2148             find_index_from_string_array(value, gui_toolbar_style_text,
2149                                      TB_STYLE_TEXT);
2150   } else if (strcmp(pref_name, PRS_GUI_FONT_NAME_1) == 0) {
2151     /* GTK1 font name obsolete */
2152   } else if (strcmp(pref_name, PRS_GUI_FONT_NAME_2) == 0) {
2153     g_free(prefs.gui_font_name);
2154     prefs.gui_font_name = g_strdup(value);
2155   } else if (strcmp(pref_name, PRS_GUI_MARKED_FG) == 0) {
2156     cval = strtoul(value, NULL, 16);
2157     prefs.gui_marked_fg.pixel = 0;
2158     prefs.gui_marked_fg.red   = RED_COMPONENT(cval);
2159     prefs.gui_marked_fg.green = GREEN_COMPONENT(cval);
2160     prefs.gui_marked_fg.blue  = BLUE_COMPONENT(cval);
2161   } else if (strcmp(pref_name, PRS_GUI_MARKED_BG) == 0) {
2162     cval = strtoul(value, NULL, 16);
2163     prefs.gui_marked_bg.pixel = 0;
2164     prefs.gui_marked_bg.red   = RED_COMPONENT(cval);
2165     prefs.gui_marked_bg.green = GREEN_COMPONENT(cval);
2166     prefs.gui_marked_bg.blue  = BLUE_COMPONENT(cval);
2167   } else if (strcmp(pref_name, PRS_GUI_IGNORED_FG) == 0) {
2168     cval = strtoul(value, NULL, 16);
2169     prefs.gui_ignored_fg.pixel = 0;
2170     prefs.gui_ignored_fg.red   = RED_COMPONENT(cval);
2171     prefs.gui_ignored_fg.green = GREEN_COMPONENT(cval);
2172     prefs.gui_ignored_fg.blue  = BLUE_COMPONENT(cval);
2173   } else if (strcmp(pref_name, PRS_GUI_IGNORED_BG) == 0) {
2174     cval = strtoul(value, NULL, 16);
2175     prefs.gui_ignored_bg.pixel = 0;
2176     prefs.gui_ignored_bg.red   = RED_COMPONENT(cval);
2177     prefs.gui_ignored_bg.green = GREEN_COMPONENT(cval);
2178     prefs.gui_ignored_bg.blue  = BLUE_COMPONENT(cval);
2179   } else if (strcmp(pref_name, PRS_GUI_COLORIZED_FG) == 0) {
2180     g_free(prefs.gui_colorized_fg);
2181     prefs.gui_colorized_fg = g_strdup(value);
2182   } else if (strcmp(pref_name, PRS_GUI_COLORIZED_BG) == 0) {
2183     g_free(prefs.gui_colorized_bg);
2184     prefs.gui_colorized_bg = g_strdup(value);
2185   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_SAVE_POSITION) == 0) {
2186     if (g_ascii_strcasecmp(value, "true") == 0) {
2187             prefs.gui_geometry_save_position = TRUE;
2188     }
2189     else {
2190             prefs.gui_geometry_save_position = FALSE;
2191     }
2192   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_SAVE_SIZE) == 0) {
2193     if (g_ascii_strcasecmp(value, "true") == 0) {
2194             prefs.gui_geometry_save_size = TRUE;
2195     }
2196     else {
2197             prefs.gui_geometry_save_size = FALSE;
2198     }
2199   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_SAVE_MAXIMIZED) == 0) {
2200     if (g_ascii_strcasecmp(value, "true") == 0) {
2201             prefs.gui_geometry_save_maximized = TRUE;
2202     }
2203     else {
2204             prefs.gui_geometry_save_maximized = FALSE;
2205     }
2206   } else if (strcmp(pref_name, PRS_GUI_MACOSX_STYLE) == 0) {
2207      if (g_ascii_strcasecmp(value, "true") == 0) {
2208             prefs.gui_macosx_style = TRUE;
2209     }
2210     else {
2211             prefs.gui_macosx_style = FALSE;
2212     }
2213   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_X) == 0) {         /* deprecated */
2214   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_Y) == 0) {         /* deprecated */
2215   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_WIDTH) == 0) {     /* deprecated */
2216   } else if (strcmp(pref_name, PRS_GUI_GEOMETRY_MAIN_HEIGHT) == 0) {    /* deprecated */
2217   } else if (strcmp(pref_name, PRS_GUI_CONSOLE_OPEN) == 0) {
2218     prefs.gui_console_open =
2219         find_index_from_string_array(value, gui_console_open_text,
2220                                      console_open_never);
2221   } else if (strcmp(pref_name, PRS_GUI_RECENT_COUNT_MAX) == 0) {
2222     prefs.gui_recent_files_count_max = strtoul(value, NULL, 10);
2223     if (prefs.gui_recent_files_count_max == 0) {
2224       /* We really should put up a dialog box here ... */
2225       prefs.gui_recent_files_count_max = 10;
2226     }
2227   } else if (strcmp(pref_name, PRS_GUI_RECENT_DF_ENTRIES_MAX) == 0) {
2228     prefs.gui_recent_df_entries_max = strtoul(value, NULL, 10);
2229     if (prefs.gui_recent_df_entries_max == 0) {
2230       /* We really should put up a dialog box here ... */
2231       prefs.gui_recent_df_entries_max = 10;
2232     }
2233   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_STYLE) == 0) {
2234     prefs.gui_fileopen_style =
2235         find_index_from_string_array(value, gui_fileopen_style_text,
2236                                      FO_STYLE_LAST_OPENED);
2237   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_DIR) == 0) {
2238     g_free(prefs.gui_fileopen_dir);
2239     prefs.gui_fileopen_dir = g_strdup(value);
2240   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_REMEMBERED_DIR) == 0) { /* deprecated */
2241   } else if (strcmp(pref_name, PRS_GUI_FILEOPEN_PREVIEW) == 0) {
2242     prefs.gui_fileopen_preview = strtoul(value, NULL, 10);
2243   } else if (strcmp(pref_name, PRS_GUI_ASK_UNSAVED) == 0) {
2244     if (g_ascii_strcasecmp(value, "true") == 0) {
2245             prefs.gui_ask_unsaved = TRUE;
2246     }
2247     else {
2248             prefs.gui_ask_unsaved = FALSE;
2249     }
2250   } else if (strcmp(pref_name, PRS_GUI_FIND_WRAP) == 0) {
2251     if (g_ascii_strcasecmp(value, "true") == 0) {
2252             prefs.gui_find_wrap = TRUE;
2253     }
2254     else {
2255             prefs.gui_find_wrap = FALSE;
2256     }
2257   } else if (strcmp(pref_name, PRS_GUI_USE_PREF_SAVE) == 0) {
2258     if (g_ascii_strcasecmp(value, "true") == 0) {
2259             prefs.gui_use_pref_save = TRUE;
2260     }
2261     else {
2262             prefs.gui_use_pref_save = FALSE;
2263     }
2264   } else if (strcmp(pref_name, PRS_GUI_WEBBROWSER) == 0) {
2265     g_free(prefs.gui_webbrowser);
2266     prefs.gui_webbrowser = g_strdup(value);
2267   } else if (strcmp(pref_name, PRS_GUI_WINDOW_TITLE) == 0) {
2268     g_free(prefs.gui_window_title);
2269     prefs.gui_window_title = g_strdup(value);
2270   } else if (strcmp(pref_name, PRS_GUI_START_TITLE) == 0) {
2271     g_free(prefs.gui_start_title);
2272     prefs.gui_start_title = g_strdup(value);
2273   } else if (strcmp(pref_name, PRS_GUI_VERSION_IN_START_PAGE) == 0) {
2274     if (g_ascii_strcasecmp(value, "true") == 0) {
2275             prefs.gui_version_in_start_page = TRUE;
2276     } else {
2277             prefs.gui_version_in_start_page = FALSE;
2278     }
2279   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_TYPE) == 0) {
2280     prefs.gui_layout_type = strtoul(value, NULL, 10);
2281     if (prefs.gui_layout_type == layout_unused ||
2282         prefs.gui_layout_type >= layout_type_max) {
2283       /* XXX - report an error?  It's not a syntax error - we'd need to
2284          add a way of reporting a *semantic* error. */
2285       prefs.gui_layout_type = layout_type_5;
2286     }
2287   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_CONTENT_1) == 0) {
2288     prefs.gui_layout_content_1 =
2289         find_index_from_string_array(value, gui_layout_content_text, 0);
2290   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_CONTENT_2) == 0) {
2291     prefs.gui_layout_content_2 =
2292         find_index_from_string_array(value, gui_layout_content_text, 0);
2293   } else if (strcmp(pref_name, PRS_GUI_LAYOUT_CONTENT_3) == 0) {
2294     prefs.gui_layout_content_3 =
2295         find_index_from_string_array(value, gui_layout_content_text, 0);
2296   } else if (strcmp(pref_name, PRS_CONSOLE_LOG_LEVEL) == 0) {
2297     prefs.console_log_level = strtoul(value, NULL, 10);
2298
2299 /* handle the capture options */
2300   } else if (strcmp(pref_name, PRS_CAP_DEVICE) == 0) {
2301     g_free(prefs.capture_device);
2302     prefs.capture_device = g_strdup(value);
2303   } else if (strcmp(pref_name, PRS_CAP_DEVICES_LINKTYPES) == 0) {
2304     g_free(prefs.capture_devices_linktypes);
2305     prefs.capture_devices_linktypes = g_strdup(value);
2306   } else if (strcmp(pref_name, PRS_CAP_DEVICES_DESCR) == 0) {
2307     g_free(prefs.capture_devices_descr);
2308     prefs.capture_devices_descr = g_strdup(value);
2309   } else if (strcmp(pref_name, PRS_CAP_DEVICES_HIDE) == 0) {
2310     g_free(prefs.capture_devices_hide);
2311     prefs.capture_devices_hide = g_strdup(value);
2312   } else if (strcmp(pref_name, PRS_CAP_DEVICES_MONITOR_MODE) == 0) {
2313     g_free(prefs.capture_devices_monitor_mode);
2314     prefs.capture_devices_monitor_mode = g_strdup(value);
2315   } else if (strcmp(pref_name, PRS_CAP_PROM_MODE) == 0) {
2316     prefs.capture_prom_mode = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2317   } else if (strcmp(pref_name, PRS_CAP_PCAP_NG) == 0) {
2318     prefs.capture_pcap_ng = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2319   } else if (strcmp(pref_name, PRS_CAP_REAL_TIME) == 0) {
2320     prefs.capture_real_time = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2321   } else if (strcmp(pref_name, PRS_CAP_AUTO_SCROLL) == 0) {
2322     prefs.capture_auto_scroll = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2323   } else if (strcmp(pref_name, PRS_CAP_SHOW_INFO) == 0) {
2324     prefs.capture_show_info = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2325
2326 /* handle the global options */
2327   } else if (strcmp(pref_name, PRS_NAME_RESOLVE) == 0 ||
2328              strcmp(pref_name, PRS_CAP_NAME_RESOLVE) == 0) {
2329     /*
2330      * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
2331      * RESOLV_ALL and RESOLV_NONE.
2332      *
2333      * Otherwise, we treat it as a list of name types we want to resolve.
2334      */
2335     if (g_ascii_strcasecmp(value, "true") == 0)
2336       prefs.name_resolve = RESOLV_ALL;
2337     else if (g_ascii_strcasecmp(value, "false") == 0)
2338       prefs.name_resolve = RESOLV_NONE;
2339     else {
2340       prefs.name_resolve = RESOLV_NONE; /* start out with none set */
2341       if (string_to_name_resolve(value, &prefs.name_resolve) != '\0')
2342         return PREFS_SET_SYNTAX_ERR;
2343     }
2344   } else if (strcmp(pref_name, PRS_NAME_RESOLVE_CONCURRENCY) == 0) {
2345     prefs.name_resolve_concurrency = strtol(value, NULL, 10);
2346   } else if (strcmp(pref_name, PRS_NAME_RESOLVE_LOAD_SMI_MODULES) == 0) {
2347     prefs.load_smi_modules = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2348   } else if (strcmp(pref_name, PRS_NAME_RESOLVE_SUPPRESS_SMI_ERRORS) == 0) {
2349     prefs.suppress_smi_errors = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2350   } else if ((strcmp(pref_name, PRS_RTP_PLAYER_MAX_VISIBLE) == 0) ||
2351              (strcmp(pref_name, "rtp_player.max_visible") == 0)) {
2352     /* ... also accepting old name for this preference */
2353     prefs.rtp_player_max_visible = strtol(value, NULL, 10);
2354   } else if (strcmp(pref_name, PRS_TAP_UPDATE_INTERVAL) == 0) {
2355     prefs.tap_update_interval = strtol(value, NULL, 10);
2356   } else if (strcmp(pref_name, PRS_DISPLAY_HIDDEN_PROTO_ITEMS) == 0) {
2357     prefs.display_hidden_proto_items = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE);
2358   } else {
2359     /* To which module does this preference belong? */
2360     module = NULL;
2361     last_dotp = pref_name;
2362     had_a_dot = FALSE;
2363     while (!module) {
2364         dotp = strchr(last_dotp, '.');
2365         if (dotp == NULL) {
2366             if (had_a_dot) {
2367               /* no such module */
2368               return PREFS_SET_NO_SUCH_PREF;
2369             }
2370             else {
2371               /* no ".", so no module/name separator */
2372               return PREFS_SET_SYNTAX_ERR;
2373             }
2374         }
2375         else {
2376             had_a_dot = TRUE;
2377         }
2378         *dotp = '\0';           /* separate module and preference name */
2379         module = prefs_find_module(pref_name);
2380
2381         /*
2382          * XXX - "Diameter" rather than "diameter" was used in earlier
2383          * versions of Wireshark; if we didn't find the module, and its name
2384          * was "Diameter", look for "diameter" instead.
2385          *
2386          * In addition, the BEEP protocol used to be the BXXP protocol,
2387          * so if we didn't find the module, and its name was "bxxp",
2388          * look for "beep" instead.
2389          *
2390          * Also, the preferences for GTP v0 and v1 were combined under
2391          * a single "gtp" heading, and the preferences for SMPP were
2392          * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
2393          * However, SMPP now has its own preferences, so we just map
2394          * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
2395          *
2396          * We also renamed "dcp" to "dccp", "x.25" to "x25" and "nsip" to "gprs_ns".
2397          *
2398          * The SynOptics Network Management Protocol (SONMP) is now known by
2399          * its modern name, the Nortel Discovery Protocol (NDP).
2400          *
2401          */
2402         if (module == NULL) {
2403           if (strcmp(pref_name, "Diameter") == 0)
2404             module = prefs_find_module("diameter");
2405           else if (strcmp(pref_name, "bxxp") == 0)
2406             module = prefs_find_module("beep");
2407           else if (strcmp(pref_name, "gtpv0") == 0 ||
2408                    strcmp(pref_name, "gtpv1") == 0)
2409             module = prefs_find_module("gtp");
2410           else if (strcmp(pref_name, "smpp-gsm-sms") == 0)
2411             module = prefs_find_module("gsm-sms-ud");
2412           else if (strcmp(pref_name, "dcp") == 0)
2413             module = prefs_find_module("dccp");
2414           else if (strcmp(pref_name, "x.25") == 0)
2415             module = prefs_find_module("x25");
2416           else if (strcmp(pref_name, "nsip") == 0)
2417             module = prefs_find_module("gprs-ns");
2418           else if (strcmp(pref_name, "sonmp") == 0)
2419             module = prefs_find_module("ndp");
2420           else if (strcmp(pref_name, "etheric") == 0 ||
2421                    strcmp(pref_name, "isup_thin") == 0)
2422             /* This protocols was removed 7. July 2009 */
2423             return PREFS_SET_OBSOLETE;
2424         }
2425         *dotp = '.';            /* put the preference string back */
2426         dotp++;                 /* skip past separator to preference name */
2427         last_dotp = dotp;
2428     }
2429
2430     pref = prefs_find_preference(module, dotp);
2431
2432     if (pref == NULL) {
2433       if (strcmp(module->name, "mgcp") == 0) {
2434         /*
2435          * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
2436          * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
2437          * were used in earlier versions of Wireshark; if we didn't find the
2438          * preference, it was an MGCP preference, and its name was
2439          * "display raw text toggle" or "display dissect tree", look for
2440          * "display_raw_text" or "display_dissect_tree" instead.
2441          *
2442          * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
2443          * the gateway and callagent ports were given those names; we interpret
2444          * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
2445          * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
2446          * they were registered by the MCCP dissector and thus that's the
2447          * order in which they were written to the preferences file.  (If
2448          * we're not reading the preferences file, but are handling stuff
2449          * from a "-o" command-line option, we have no clue which the user
2450          * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
2451          * or "mgcp.{tcp,udp}.callagent_port" instead.)
2452          */
2453         if (strcmp(dotp, "display raw text toggle") == 0)
2454           pref = prefs_find_preference(module, "display_raw_text");
2455         else if (strcmp(dotp, "display dissect tree") == 0)
2456           pref = prefs_find_preference(module, "display_dissect_tree");
2457         else if (strcmp(dotp, "tcp.port") == 0) {
2458           mgcp_tcp_port_count++;
2459           if (mgcp_tcp_port_count == 1) {
2460             /* It's the first one */
2461             pref = prefs_find_preference(module, "tcp.gateway_port");
2462           } else if (mgcp_tcp_port_count == 2) {
2463             /* It's the second one */
2464             pref = prefs_find_preference(module, "tcp.callagent_port");
2465           }
2466           /* Otherwise it's from the command line, and we don't bother
2467              mapping it. */
2468         } else if (strcmp(dotp, "udp.port") == 0) {
2469           mgcp_udp_port_count++;
2470           if (mgcp_udp_port_count == 1) {
2471             /* It's the first one */
2472             pref = prefs_find_preference(module, "udp.gateway_port");
2473           } else if (mgcp_udp_port_count == 2) {
2474             /* It's the second one */
2475             pref = prefs_find_preference(module, "udp.callagent_port");
2476           }
2477           /* Otherwise it's from the command line, and we don't bother
2478              mapping it. */
2479         }
2480       } else if (strcmp(module->name, "smb") == 0) {
2481         /* Handle old names for SMB preferences. */
2482         if (strcmp(dotp, "smb.trans.reassembly") == 0)
2483           pref = prefs_find_preference(module, "trans_reassembly");
2484         else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
2485           pref = prefs_find_preference(module, "dcerpc_reassembly");
2486       } else if (strcmp(module->name, "ndmp") == 0) {
2487         /* Handle old names for NDMP preferences. */
2488         if (strcmp(dotp, "ndmp.desegment") == 0)
2489           pref = prefs_find_preference(module, "desegment");
2490       } else if (strcmp(module->name, "diameter") == 0) {
2491         /* Handle old names for Diameter preferences. */
2492         if (strcmp(dotp, "diameter.desegment") == 0)
2493           pref = prefs_find_preference(module, "desegment");
2494       } else if (strcmp(module->name, "pcli") == 0) {
2495         /* Handle old names for PCLI preferences. */
2496         if (strcmp(dotp, "pcli.udp_port") == 0)
2497           pref = prefs_find_preference(module, "udp_port");
2498       } else if (strcmp(module->name, "artnet") == 0) {
2499         /* Handle old names for ARTNET preferences. */
2500         if (strcmp(dotp, "artnet.udp_port") == 0)
2501           pref = prefs_find_preference(module, "udp_port");
2502       } else if (strcmp(module->name, "mapi") == 0) {
2503         /* Handle old names for MAPI preferences. */
2504         if (strcmp(dotp, "mapi_decrypt") == 0)
2505           pref = prefs_find_preference(module, "decrypt");
2506       } else if (strcmp(module->name, "fc") == 0) {
2507         /* Handle old names for Fibre Channel preferences. */
2508         if (strcmp(dotp, "reassemble_fc") == 0)
2509           pref = prefs_find_preference(module, "reassemble");
2510         else if (strcmp(dotp, "fc_max_frame_size") == 0)
2511           pref = prefs_find_preference(module, "max_frame_size");
2512       } else if (strcmp(module->name, "fcip") == 0) {
2513         /* Handle old names for Fibre Channel-over-IP preferences. */
2514         if (strcmp(dotp, "desegment_fcip_messages") == 0)
2515           pref = prefs_find_preference(module, "desegment");
2516         else if (strcmp(dotp, "fcip_port") == 0)
2517           pref = prefs_find_preference(module, "target_port");
2518       } else if (strcmp(module->name, "gtp") == 0) {
2519         /* Handle old names for GTP preferences. */
2520         if (strcmp(dotp, "gtpv0_port") == 0)
2521           pref = prefs_find_preference(module, "v0_port");
2522         else if (strcmp(dotp, "gtpv1c_port") == 0)
2523           pref = prefs_find_preference(module, "v1c_port");
2524         else if (strcmp(dotp, "gtpv1u_port") == 0)
2525           pref = prefs_find_preference(module, "v1u_port");
2526         else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
2527           pref = prefs_find_preference(module, "dissect_tpdu");
2528         else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
2529           pref = prefs_find_preference(module, "v0_dissect_cdr_as");
2530         else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
2531           pref = prefs_find_preference(module, "v0_check_etsi");
2532         else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
2533           pref = prefs_find_preference(module, "v1_check_etsi");
2534       } else if (strcmp(module->name, "ip") == 0) {
2535         /* Handle old names for IP preferences. */
2536         if (strcmp(dotp, "ip_summary_in_tree") == 0)
2537           pref = prefs_find_preference(module, "summary_in_tree");
2538       } else if (strcmp(module->name, "iscsi") == 0) {
2539         /* Handle old names for iSCSI preferences. */
2540         if (strcmp(dotp, "iscsi_port") == 0)
2541           pref = prefs_find_preference(module, "target_port");
2542       } else if (strcmp(module->name, "lmp") == 0) {
2543         /* Handle old names for LMP preferences. */
2544         if (strcmp(dotp, "lmp_version") == 0)
2545           pref = prefs_find_preference(module, "version");
2546       } else if (strcmp(module->name, "mtp3") == 0) {
2547         /* Handle old names for MTP3 preferences. */
2548         if (strcmp(dotp, "mtp3_standard") == 0)
2549           pref = prefs_find_preference(module, "standard");
2550         else if (strcmp(dotp, "net_addr_format") == 0)
2551           pref = prefs_find_preference(module, "addr_format");
2552       } else if (strcmp(module->name, "nlm") == 0) {
2553         /* Handle old names for NLM preferences. */
2554         if (strcmp(dotp, "nlm_msg_res_matching") == 0)
2555           pref = prefs_find_preference(module, "msg_res_matching");
2556       } else if (strcmp(module->name, "ppp") == 0) {
2557         /* Handle old names for PPP preferences. */
2558         if (strcmp(dotp, "ppp_fcs") == 0)
2559           pref = prefs_find_preference(module, "fcs_type");
2560         else if (strcmp(dotp, "ppp_vj") == 0)
2561           pref = prefs_find_preference(module, "decompress_vj");
2562       } else if (strcmp(module->name, "rsvp") == 0) {
2563         /* Handle old names for RSVP preferences. */
2564         if (strcmp(dotp, "rsvp_process_bundle") == 0)
2565           pref = prefs_find_preference(module, "process_bundle");
2566       } else if (strcmp(module->name, "tcp") == 0) {
2567         /* Handle old names for TCP preferences. */
2568         if (strcmp(dotp, "tcp_summary_in_tree") == 0)
2569           pref = prefs_find_preference(module, "summary_in_tree");
2570         else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
2571           pref = prefs_find_preference(module, "analyze_sequence_numbers");
2572         else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
2573           pref = prefs_find_preference(module, "relative_sequence_numbers");
2574       } else if (strcmp(module->name, "udp") == 0) {
2575         /* Handle old names for UDP preferences. */
2576         if (strcmp(dotp, "udp_summary_in_tree") == 0)
2577           pref = prefs_find_preference(module, "summary_in_tree");
2578       } else if (strcmp(module->name, "ndps") == 0) {
2579         /* Handle old names for NDPS preferences. */
2580         if (strcmp(dotp, "desegment_ndps") == 0)
2581           pref = prefs_find_preference(module, "desegment_tcp");
2582       } else if (strcmp(module->name, "http") == 0) {
2583         /* Handle old names for HTTP preferences. */
2584         if (strcmp(dotp, "desegment_http_headers") == 0)
2585           pref = prefs_find_preference(module, "desegment_headers");
2586         else if (strcmp(dotp, "desegment_http_body") == 0)
2587           pref = prefs_find_preference(module, "desegment_body");
2588       } else if (strcmp(module->name, "smpp") == 0) {
2589         /* Handle preferences that moved from SMPP. */
2590         module_t *new_module = prefs_find_module("gsm-sms-ud");
2591         if(new_module){
2592           if (strcmp(dotp, "port_number_udh_means_wsp") == 0)
2593             pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
2594           else if (strcmp(dotp, "try_dissect_1st_fragment") == 0)
2595             pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
2596         }
2597       } else if (strcmp(module->name, "asn1") == 0) {
2598         /* Handle old generic ASN.1 preferences (it's not really a
2599            rename, as the new preferences support multiple ports,
2600            but we might as well copy them over). */
2601         if (strcmp(dotp, "tcp_port") == 0)
2602           pref = prefs_find_preference(module, "tcp_ports");
2603         else if (strcmp(dotp, "udp_port") == 0)
2604           pref = prefs_find_preference(module, "udp_ports");
2605         else if (strcmp(dotp, "sctp_port") == 0)
2606           pref = prefs_find_preference(module, "sctp_ports");
2607       } else if (strcmp(module->name, "llcgprs") == 0) {
2608         if (strcmp(dotp, "ignore_cipher_bit") == 0)
2609           pref = prefs_find_preference(module, "autodetect_cipher_bit");
2610       } else if (strcmp(module->name, "erf") == 0) {
2611         if (strcmp(dotp, "erfeth") == 0) {
2612           /* Handle the old "erfeth" preference; map it to the new
2613              "ethfcs" preference, and map the values to those for
2614              the new preference. */
2615           pref = prefs_find_preference(module, "ethfcs");
2616           if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
2617             value = "TRUE";
2618           else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
2619             value = "FALSE";
2620           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2621             value = "TRUE";
2622         } else if (strcmp(dotp, "erfatm") == 0) {
2623           /* Handle the old "erfatm" preference; map it to the new
2624              "aal5_type" preference, and map the values to those for
2625              the new preference. */
2626           pref = prefs_find_preference(module, "aal5_type");
2627           if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
2628             value = "guess";
2629           else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
2630             value = "llc";
2631           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2632             value = "guess";
2633         } else if (strcmp(dotp, "erfhdlc") == 0) {
2634           /* Handle the old "erfhdlc" preference; map it to the new
2635              "hdlc_type" preference, and map the values to those for
2636              the new preference. */
2637           pref = prefs_find_preference(module, "hdlc_type");
2638           if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
2639             value = "chdlc";
2640           else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
2641             value = "ppp";
2642           else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
2643             value = "frelay";
2644           else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
2645             value = "mtp2";
2646           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2647             value = "guess";
2648         }
2649       }
2650     }
2651     if (pref == NULL)
2652       return PREFS_SET_NO_SUCH_PREF;    /* no such preference */
2653
2654     switch (pref->type) {
2655
2656     case PREF_UINT:
2657       uval = strtoul(value, &p, pref->info.base);
2658       if (p == value || *p != '\0')
2659         return PREFS_SET_SYNTAX_ERR;    /* number was bad */
2660       if (*pref->varp.uint != uval) {
2661         module->prefs_changed = TRUE;
2662         *pref->varp.uint = uval;
2663       }
2664       break;
2665
2666     case PREF_BOOL:
2667       /* XXX - give an error if it's neither "true" nor "false"? */
2668       if (g_ascii_strcasecmp(value, "true") == 0)
2669         bval = TRUE;
2670       else
2671         bval = FALSE;
2672       if (*pref->varp.boolp != bval) {
2673         module->prefs_changed = TRUE;
2674         *pref->varp.boolp = bval;
2675       }
2676       break;
2677
2678     case PREF_ENUM:
2679       /* XXX - give an error if it doesn't match? */
2680       enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
2681                                      *pref->varp.enump);
2682       if (*pref->varp.enump != enum_val) {
2683         module->prefs_changed = TRUE;
2684         *pref->varp.enump = enum_val;
2685       }
2686       break;
2687
2688     case PREF_STRING:
2689       if (strcmp(*pref->varp.string, value) != 0) {
2690         module->prefs_changed = TRUE;
2691         g_free((void *)*pref->varp.string);
2692         *pref->varp.string = g_strdup(value);
2693       }
2694       break;
2695
2696     case PREF_RANGE:
2697     {
2698       range_t *newrange;
2699
2700       if (range_convert_str_work(&newrange, value, pref->info.max_value,
2701                                  return_range_errors) != CVT_NO_ERROR) {
2702         return PREFS_SET_SYNTAX_ERR;    /* number was bad */
2703       }
2704
2705       if (!ranges_are_equal(*pref->varp.range, newrange)) {
2706         module->prefs_changed = TRUE;
2707         g_free(*pref->varp.range);
2708         *pref->varp.range = newrange;
2709       } else {
2710         g_free (newrange);
2711       }
2712       break;
2713     }
2714
2715     case PREF_STATIC_TEXT:
2716     case PREF_UAT:
2717     {
2718       break;
2719     }
2720
2721     case PREF_OBSOLETE:
2722       return PREFS_SET_OBSOLETE;        /* no such preference any more */
2723     }
2724   }
2725
2726   return PREFS_SET_OK;
2727 }
2728
2729 typedef struct {
2730         module_t *module;
2731         FILE    *pf;
2732 } write_pref_arg_t;
2733
2734 /*
2735  * Write out a single preference.
2736  */
2737 static void
2738 write_pref(gpointer data, gpointer user_data)
2739 {
2740         pref_t *pref = data;
2741         write_pref_arg_t *arg = user_data;
2742         const enum_val_t *enum_valp;
2743         const char *val_string;
2744         gchar **desc_lines;
2745         int i;
2746
2747         if (pref->type == PREF_OBSOLETE) {
2748                 /*
2749                  * This preference is no longer supported; it's not a
2750                  * real preference, so we don't write it out (i.e., we
2751                  * treat it as if it weren't found in the list of
2752                  * preferences, and we weren't called in the first place).
2753                  */
2754                 return;
2755         }
2756
2757         /*
2758          * Make multiple line descriptions appear as
2759          * multiple commented lines in prefs file.
2760          */
2761         if (g_ascii_strncasecmp(pref->description,"", 2) != 0) {
2762                 desc_lines = g_strsplit(pref->description,"\n",0);
2763                 for (i = 0; desc_lines[i] != NULL; ++i) {
2764                         fprintf(arg->pf, "\n# %s", desc_lines[i]);
2765                 }
2766                 fprintf(arg->pf, "\n");
2767                 g_strfreev(desc_lines);
2768         } else {
2769                 fprintf(arg->pf, "\n# No description\n");
2770         }
2771
2772         switch (pref->type) {
2773
2774         case PREF_UINT:
2775                 switch (pref->info.base) {
2776
2777                 case 10:
2778                         fprintf(arg->pf, "# A decimal number.\n");
2779                         if (pref->default_val.uint == *pref->varp.uint)
2780                             fprintf(arg->pf, "#");
2781                         fprintf(arg->pf, "%s.%s: %u\n", arg->module->name,
2782                             pref->name, *pref->varp.uint);
2783                         break;
2784
2785                 case 8:
2786                         fprintf(arg->pf, "# An octal number.\n");
2787                         if (pref->default_val.uint == *pref->varp.uint)
2788                             fprintf(arg->pf, "#");
2789                         fprintf(arg->pf, "%s.%s: %#o\n", arg->module->name,
2790                             pref->name, *pref->varp.uint);
2791                         break;
2792
2793                 case 16:
2794                         fprintf(arg->pf, "# A hexadecimal number.\n");
2795                         if (pref->default_val.uint == *pref->varp.uint)
2796                             fprintf(arg->pf, "#");
2797                         fprintf(arg->pf, "%s.%s: %#x\n", arg->module->name,
2798                             pref->name, *pref->varp.uint);
2799                         break;
2800                 }
2801                 break;
2802
2803         case PREF_BOOL:
2804                 fprintf(arg->pf, "# TRUE or FALSE (case-insensitive).\n");
2805                 if (pref->default_val.boolval == *pref->varp.boolp)
2806                     fprintf(arg->pf, "#");
2807                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2808                     *pref->varp.boolp ? "TRUE" : "FALSE");
2809                 break;
2810
2811         case PREF_ENUM:
2812                 /*
2813                  * For now, we save the "description" value, so that if we
2814                  * save the preferences older versions of Wireshark can at
2815                  * least read preferences that they supported; we support
2816                  * either the short name or the description when reading
2817                  * the preferences file or a "-o" option.
2818                  */
2819                 fprintf(arg->pf, "# One of: ");
2820                 enum_valp = pref->info.enum_info.enumvals;
2821                 val_string = NULL;
2822                 while (enum_valp->name != NULL) {
2823                         if (enum_valp->value == *pref->varp.enump)
2824                                 val_string = enum_valp->description;
2825                         fprintf(arg->pf, "%s", enum_valp->description);
2826                         enum_valp++;
2827                         if (enum_valp->name == NULL)
2828                                 fprintf(arg->pf, "\n");
2829                         else
2830                                 fprintf(arg->pf, ", ");
2831                 }
2832                 fprintf(arg->pf, "# (case-insensitive).\n");
2833                 if (pref->default_val.enumval == *pref->varp.enump)
2834                     fprintf(arg->pf, "#");
2835                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name,
2836                     pref->name, val_string);
2837                 break;
2838
2839         case PREF_STRING:
2840                 fprintf(arg->pf, "# A string.\n");
2841                 if (!(strcmp(pref->default_val.string, *pref->varp.string)))
2842                     fprintf(arg->pf, "#");
2843                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2844                     *pref->varp.string);
2845                 break;
2846
2847         case PREF_RANGE:
2848         {
2849                 char *range_string_p;
2850
2851                 range_string_p = range_convert_range(*pref->varp.range);
2852                 fprintf(arg->pf, "# A string denoting an positive integer range (e.g., \"1-20,30-40\").\n");
2853                 if ((ranges_are_equal(pref->default_val.range, *pref->varp.range)))
2854                     fprintf(arg->pf, "#");
2855                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2856                         range_string_p);
2857                 break;
2858         }
2859
2860         case PREF_STATIC_TEXT:
2861         case PREF_UAT:
2862         {
2863                 /* Nothing to do */
2864                 break;
2865         }
2866
2867         case PREF_OBSOLETE:
2868                 g_assert_not_reached();
2869                 break;
2870         }
2871 }
2872
2873 static gboolean
2874 write_module_prefs(void *value, void *data)
2875 {
2876         write_pref_arg_t arg;
2877
2878         arg.module = value;
2879         arg.pf = data;
2880         g_list_foreach(arg.module->prefs, write_pref, &arg);
2881         return FALSE;
2882 }
2883
2884 /* Write out "prefs" to the user's preferences file, and return 0.
2885
2886    If the preferences file path is NULL, write to stdout.
2887
2888    If we got an error, stuff a pointer to the path of the preferences file
2889    into "*pf_path_return", and return the errno. */
2890 int
2891 write_prefs(char **pf_path_return)
2892 {
2893   char        *pf_path;
2894   FILE        *pf;
2895   GList       *clp, *col_l;
2896   fmt_data    *cfmt;
2897   const gchar *cust_format = col_format_to_string(COL_CUSTOM);
2898   GString     *cols_hidden = g_string_new ("");
2899
2900   /* Needed for "-G defaultprefs" */
2901   init_prefs();
2902
2903   /* To do:
2904    * - Split output lines longer than MAX_VAL_LEN
2905    * - Create a function for the preference directory check/creation
2906    *   so that duplication can be avoided with filter.c
2907    */
2908
2909   if (pf_path_return != NULL) {
2910     pf_path = get_persconffile_path(PF_NAME, TRUE, TRUE);
2911     if ((pf = ws_fopen(pf_path, "w")) == NULL) {
2912       *pf_path_return = pf_path;
2913       return errno;
2914     }
2915   } else {
2916     pf = stdout;
2917   }
2918
2919   fputs("# Configuration file for Wireshark " VERSION ".\n"
2920         "#\n"
2921         "# This file is regenerated each time preferences are saved within\n"
2922         "# Wireshark.  Making manual changes should be safe, however.\n"
2923         "# Protocol preferences that have been commented out have not been\n"
2924         "# changed from their default value.\n", pf);
2925
2926   fprintf (pf, "\n######## User Interface ########\n");
2927
2928   fprintf(pf, "\n# Vertical scrollbars should be on right side?\n");
2929   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2930   fprintf(pf, PRS_GUI_SCROLLBAR_ON_RIGHT ": %s\n",
2931           prefs.gui_scrollbar_on_right == TRUE ? "TRUE" : "FALSE");
2932
2933   fprintf(pf, "\n# Packet-list selection bar can be used to browse w/o selecting?\n");
2934   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2935   fprintf(pf, PRS_GUI_PLIST_SEL_BROWSE ": %s\n",
2936           prefs.gui_plist_sel_browse == TRUE ? "TRUE" : "FALSE");
2937
2938   fprintf(pf, "\n# Protocol-tree 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_PTREE_SEL_BROWSE ": %s\n",
2941           prefs.gui_ptree_sel_browse == TRUE ? "TRUE" : "FALSE");
2942
2943   fprintf(pf, "\n# Alternating colors in TreeViews?\n");
2944   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2945   fprintf(pf, PRS_GUI_ALTERN_COLORS ": %s\n",
2946           prefs.gui_altern_colors == TRUE ? "TRUE" : "FALSE");
2947
2948   fprintf(pf, "\n# Place filter toolbar inside the statusbar?\n");
2949   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2950   fprintf(pf, PRS_GUI_FILTER_TOOLBAR_IN_STATUSBAR ": %s\n",
2951          prefs.filter_toolbar_show_in_statusbar == TRUE ? "TRUE" : "FALSE");
2952
2953   fprintf(pf, "\n# Protocol-tree line style.\n");
2954   fprintf(pf, "# One of: NONE, SOLID, DOTTED, TABBED\n");
2955   fprintf(pf, PRS_GUI_PTREE_LINE_STYLE ": %s\n",
2956           gui_ptree_line_style_text[prefs.gui_ptree_line_style]);
2957
2958   fprintf(pf, "\n# Protocol-tree expander style.\n");
2959   fprintf(pf, "# One of: NONE, SQUARE, TRIANGLE, CIRCULAR\n");
2960   fprintf(pf, PRS_GUI_PTREE_EXPANDER_STYLE ": %s\n",
2961           gui_ptree_expander_style_text[prefs.gui_ptree_expander_style]);
2962
2963   fprintf(pf, "\n# Hex dump highlight style.\n");
2964   fprintf(pf, "# One of: BOLD, INVERSE\n");
2965   fprintf(pf, PRS_GUI_HEX_DUMP_HIGHLIGHT_STYLE ": %s\n",
2966           gui_hex_dump_highlight_style_text[prefs.gui_hex_dump_highlight_style]);
2967
2968   fprintf(pf, "\n# Main Toolbar style.\n");
2969   fprintf(pf, "# One of: ICONS, TEXT, BOTH\n");
2970   fprintf(pf, PRS_GUI_TOOLBAR_MAIN_STYLE ": %s\n",
2971           gui_toolbar_style_text[prefs.gui_toolbar_main_style]);
2972
2973   fprintf(pf, "\n# Filter Toolbar style.\n");
2974   fprintf(pf, "# One of: ICONS, TEXT, BOTH\n");
2975   fprintf(pf, PRS_GUI_TOOLBAR_FILTER_STYLE ": %s\n",
2976           gui_toolbar_style_text[prefs.gui_toolbar_filter_style]);
2977
2978   fprintf(pf, "\n# Save window position at exit?\n");
2979   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2980   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_POSITION ": %s\n",
2981           prefs.gui_geometry_save_position == TRUE ? "TRUE" : "FALSE");
2982
2983   fprintf(pf, "\n# Save window size at exit?\n");
2984   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2985   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_SIZE ": %s\n",
2986           prefs.gui_geometry_save_size == TRUE ? "TRUE" : "FALSE");
2987
2988   fprintf(pf, "\n# Save window maximized state at exit?\n");
2989   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2990   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_MAXIMIZED ": %s\n",
2991           prefs.gui_geometry_save_maximized == TRUE ? "TRUE" : "FALSE");
2992
2993   fprintf(pf, "\n# Use Mac OS X style (Mac OS X with native GTK only)?\n");
2994   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2995   fprintf(pf, PRS_GUI_MACOSX_STYLE ": %s\n",
2996           prefs.gui_macosx_style == TRUE ? "TRUE" : "FALSE");
2997
2998   fprintf(pf, "\n# Open a console window (WIN32 only)?\n");
2999   fprintf(pf, "# One of: NEVER, AUTOMATIC, ALWAYS\n");
3000   fprintf(pf, PRS_GUI_CONSOLE_OPEN ": %s\n",
3001           gui_console_open_text[prefs.gui_console_open]);
3002
3003   fprintf(pf, "\n# The max. number of entries in the display filter list.\n");
3004   fprintf(pf, "# A decimal number.\n");
3005   fprintf(pf, PRS_GUI_RECENT_DF_ENTRIES_MAX ": %d\n",
3006           prefs.gui_recent_df_entries_max);
3007
3008   fprintf(pf, "\n# The max. number of items in the open recent files list.\n");
3009   fprintf(pf, "# A decimal number.\n");
3010   fprintf(pf, PRS_GUI_RECENT_COUNT_MAX ": %d\n",
3011           prefs.gui_recent_files_count_max);
3012
3013   fprintf(pf, "\n# Where to start the File Open dialog box.\n");
3014   fprintf(pf, "# One of: LAST_OPENED, SPECIFIED\n");
3015   fprintf(pf, PRS_GUI_FILEOPEN_STYLE ": %s\n",
3016           gui_fileopen_style_text[prefs.gui_fileopen_style]);
3017
3018   if (prefs.gui_fileopen_dir != NULL) {
3019     fprintf(pf, "\n# Directory to start in when opening File Open dialog.\n");
3020     fprintf(pf, PRS_GUI_FILEOPEN_DIR ": %s\n",
3021             prefs.gui_fileopen_dir);
3022   }
3023
3024   fprintf(pf, "\n# The preview timeout in the File Open dialog.\n");
3025   fprintf(pf, "# A decimal number (in seconds).\n");
3026   fprintf(pf, PRS_GUI_FILEOPEN_PREVIEW ": %d\n",
3027           prefs.gui_fileopen_preview);
3028
3029   fprintf(pf, "\n# Ask to save unsaved capture files?\n");
3030   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3031   fprintf(pf, PRS_GUI_ASK_UNSAVED ": %s\n",
3032           prefs.gui_ask_unsaved == TRUE ? "TRUE" : "FALSE");
3033
3034   fprintf(pf, "\n# Wrap to beginning/end of file during search?\n");
3035   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3036   fprintf(pf, PRS_GUI_FIND_WRAP ": %s\n",
3037           prefs.gui_find_wrap == TRUE ? "TRUE" : "FALSE");
3038
3039   fprintf(pf, "\n# Settings dialogs use a save button?\n");
3040   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3041   fprintf(pf, PRS_GUI_USE_PREF_SAVE ": %s\n",
3042           prefs.gui_use_pref_save == TRUE ? "TRUE" : "FALSE");
3043
3044   fprintf(pf, "\n# The path to the webbrowser.\n");
3045   fprintf(pf, "# Ex: mozilla %%s\n");
3046   fprintf(pf, PRS_GUI_WEBBROWSER ": %s\n", prefs.gui_webbrowser);
3047
3048   fprintf(pf, "\n# Custom window title. (Appended to existing titles.)\n");
3049   fprintf(pf, PRS_GUI_WINDOW_TITLE ": %s\n",
3050           prefs.gui_window_title);
3051
3052   fprintf(pf, "\n# Custom start page title.\n");
3053   fprintf(pf, PRS_GUI_START_TITLE ": %s\n",
3054           prefs.gui_start_title);
3055
3056   fprintf(pf, "\n# Show version in the start page and main screen's title bar.\n");
3057   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3058   fprintf(pf, PRS_GUI_VERSION_IN_START_PAGE ": %s\n",
3059           prefs.gui_version_in_start_page == TRUE ? "TRUE" : "FALSE");
3060
3061   fprintf (pf, "\n######## User Interface: Layout ########\n");
3062
3063   fprintf(pf, "\n# Layout type (1-6).\n");
3064   fprintf(pf, PRS_GUI_LAYOUT_TYPE ": %d\n",
3065           prefs.gui_layout_type);
3066
3067   fprintf(pf, "\n# Layout content of the panes (1-3).\n");
3068   fprintf(pf, "# One of: NONE, PLIST, PDETAILS, PBYTES\n");
3069   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_1 ": %s\n",
3070           gui_layout_content_text[prefs.gui_layout_content_1]);
3071   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_2 ": %s\n",
3072           gui_layout_content_text[prefs.gui_layout_content_2]);
3073   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_3 ": %s\n",
3074           gui_layout_content_text[prefs.gui_layout_content_3]);
3075
3076   fprintf (pf, "\n######## User Interface: Columns ########\n");
3077
3078   clp = prefs.col_list;
3079   col_l = NULL;
3080   while (clp) {
3081     gchar *prefs_fmt;
3082     cfmt = (fmt_data *) clp->data;
3083     col_l = g_list_append(col_l, g_strdup(cfmt->title));
3084     if ((strcmp(cfmt->fmt, cust_format) == 0) && (cfmt->custom_field)) {
3085       prefs_fmt = g_strdup_printf("%s:%s:%d:%c", cfmt->fmt, cfmt->custom_field,
3086                                   cfmt->custom_occurrence, cfmt->resolved ? 'R' : 'U');
3087       col_l = g_list_append(col_l, prefs_fmt);
3088     } else {
3089       prefs_fmt = cfmt->fmt;
3090       col_l = g_list_append(col_l, g_strdup(cfmt->fmt));
3091     }
3092     if (!cfmt->visible) {
3093       if (cols_hidden->len) {
3094         g_string_append (cols_hidden, ",");
3095       }
3096       g_string_append (cols_hidden, prefs_fmt);
3097     }
3098     clp = clp->next;
3099   }
3100   fprintf (pf, "\n# Packet list hidden columns.\n");
3101   fprintf (pf, "# List all columns to hide in the packet list.\n");
3102   fprintf (pf, "%s: %s\n", PRS_COL_HIDDEN, cols_hidden->str);
3103   /* This frees the list of strings, but not the strings to which it
3104      refers; they are free'ed in put_string_list(). */
3105   g_string_free (cols_hidden, TRUE);
3106
3107   fprintf (pf, "\n# Packet list column format.\n");
3108   fprintf (pf, "# Each pair of strings consists of a column title and its format.\n");
3109   fprintf (pf, "%s: %s\n", PRS_COL_FMT, put_string_list(col_l));
3110   /* This frees the list of strings, but not the strings to which it
3111      refers; they are free'ed in put_string_list(). */
3112   g_list_free(col_l);
3113
3114   fprintf (pf, "\n######## User Interface: Font ########\n");
3115
3116   fprintf(pf, "\n# Font name for packet list, protocol tree, and hex dump panes.\n");
3117   fprintf(pf, PRS_GUI_FONT_NAME_2 ": %s\n", prefs.gui_font_name);
3118
3119   fprintf (pf, "\n######## User Interface: Colors ########\n");
3120
3121   fprintf (pf, "\n# Color preferences for a marked frame.\n");
3122   fprintf (pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
3123   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_MARKED_FG,
3124            (prefs.gui_marked_fg.red * 255 / 65535),
3125            (prefs.gui_marked_fg.green * 255 / 65535),
3126            (prefs.gui_marked_fg.blue * 255 / 65535));
3127   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_MARKED_BG,
3128            (prefs.gui_marked_bg.red * 255 / 65535),
3129            (prefs.gui_marked_bg.green * 255 / 65535),
3130            (prefs.gui_marked_bg.blue * 255 / 65535));
3131
3132   fprintf (pf, "\n# Color preferences for a ignored frame.\n");
3133   fprintf (pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
3134   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_IGNORED_FG,
3135            (prefs.gui_ignored_fg.red * 255 / 65535),
3136            (prefs.gui_ignored_fg.green * 255 / 65535),
3137            (prefs.gui_ignored_fg.blue * 255 / 65535));
3138   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_IGNORED_BG,
3139            (prefs.gui_ignored_bg.red * 255 / 65535),
3140            (prefs.gui_ignored_bg.green * 255 / 65535),
3141            (prefs.gui_ignored_bg.blue * 255 / 65535));
3142
3143   /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
3144    * file until the colors can be changed in the GUI. Currently this is not really
3145    * possible since the STOCK-icons for these colors are hardcoded.
3146    *
3147    * XXX Find a way to change the colors of the STOCK-icons on the fly and then
3148    *     add these 10 colors to the list of colors that can be changed through
3149    *     the preferences.
3150    *
3151   fprintf (pf, "%s: %s\n", PRS_GUI_COLORIZED_FG, prefs.gui_colorized_fg);
3152   fprintf (pf, "%s: %s\n", PRS_GUI_COLORIZED_BG, prefs.gui_colorized_bg);
3153   */
3154
3155   fprintf (pf, "\n# TCP stream window color preferences.\n");
3156   fprintf (pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
3157   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_CL_FG,
3158            (prefs.st_client_fg.red * 255 / 65535),
3159            (prefs.st_client_fg.green * 255 / 65535),
3160            (prefs.st_client_fg.blue * 255 / 65535));
3161   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_CL_BG,
3162            (prefs.st_client_bg.red * 255 / 65535),
3163            (prefs.st_client_bg.green * 255 / 65535),
3164            (prefs.st_client_bg.blue * 255 / 65535));
3165   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_SR_FG,
3166            (prefs.st_server_fg.red * 255 / 65535),
3167            (prefs.st_server_fg.green * 255 / 65535),
3168            (prefs.st_server_fg.blue * 255 / 65535));
3169   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_SR_BG,
3170            (prefs.st_server_bg.red * 255 / 65535),
3171            (prefs.st_server_bg.green * 255 / 65535),
3172            (prefs.st_server_bg.blue * 255 / 65535));
3173
3174   fprintf(pf, "\n######## Console: logging level ########\n");
3175   fprintf(pf, "# (debugging only, not in the Preferences dialog)\n");
3176   fprintf(pf, "# A bitmask of glib log levels:\n"
3177           "# G_LOG_LEVEL_ERROR    = 4\n"
3178           "# G_LOG_LEVEL_CRITICAL = 8\n"
3179           "# G_LOG_LEVEL_WARNING  = 16\n"
3180           "# G_LOG_LEVEL_MESSAGE  = 32\n"
3181           "# G_LOG_LEVEL_INFO     = 64\n"
3182           "# G_LOG_LEVEL_DEBUG    = 128\n");
3183
3184   fprintf(pf, PRS_CONSOLE_LOG_LEVEL ": %u\n",
3185           prefs.console_log_level);
3186
3187   fprintf(pf, "\n####### Capture ########\n");
3188
3189   if (prefs.capture_device != NULL) {
3190     fprintf(pf, "\n# Default capture device\n");
3191     fprintf(pf, PRS_CAP_DEVICE ": %s\n", prefs.capture_device);
3192   }
3193
3194   if (prefs.capture_devices_linktypes != NULL) {
3195     fprintf(pf, "\n# Interface link-layer header types.\n");
3196     fprintf(pf, "# A decimal number for the DLT.\n");
3197     fprintf(pf, "# Ex: en0(1),en1(143),...\n");
3198     fprintf(pf, PRS_CAP_DEVICES_LINKTYPES ": %s\n", prefs.capture_devices_linktypes);
3199   }
3200
3201   if (prefs.capture_devices_descr != NULL) {
3202     fprintf(pf, "\n# Interface descriptions.\n");
3203     fprintf(pf, "# Ex: eth0(eth0 descr),eth1(eth1 descr),...\n");
3204     fprintf(pf, PRS_CAP_DEVICES_DESCR ": %s\n", prefs.capture_devices_descr);
3205   }
3206
3207   if (prefs.capture_devices_hide != NULL) {
3208     fprintf(pf, "\n# Hide interface?\n");
3209     fprintf(pf, "# Ex: eth0,eth3,...\n");
3210     fprintf(pf, PRS_CAP_DEVICES_HIDE ": %s\n", prefs.capture_devices_hide);
3211   }
3212
3213   if (prefs.capture_devices_monitor_mode != NULL) {
3214     fprintf(pf, "\n# By default, capture in monitor mode on interface?\n");
3215     fprintf(pf, "# Ex: eth0,eth3,...\n");
3216     fprintf(pf, PRS_CAP_DEVICES_MONITOR_MODE ": %s\n", prefs.capture_devices_monitor_mode);
3217   }
3218
3219   fprintf(pf, "\n# Capture in promiscuous mode?\n");
3220   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3221   fprintf(pf, PRS_CAP_PROM_MODE ": %s\n",
3222           prefs.capture_prom_mode == TRUE ? "TRUE" : "FALSE");
3223
3224   fprintf(pf, "\n# Capture in Pcap-NG format?\n");
3225   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3226   fprintf(pf, PRS_CAP_PCAP_NG ": %s\n",
3227           prefs.capture_pcap_ng == TRUE ? "TRUE" : "FALSE");
3228
3229   fprintf(pf, "\n# Update packet list in real time during capture?\n");
3230   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3231   fprintf(pf, PRS_CAP_REAL_TIME ": %s\n",
3232           prefs.capture_real_time == TRUE ? "TRUE" : "FALSE");
3233
3234   fprintf(pf, "\n# Scroll packet list during capture?\n");
3235   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3236   fprintf(pf, PRS_CAP_AUTO_SCROLL ": %s\n",
3237           prefs.capture_auto_scroll == TRUE ? "TRUE" : "FALSE");
3238
3239   fprintf(pf, "\n# Show capture info dialog while capturing?\n");
3240   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3241   fprintf(pf, PRS_CAP_SHOW_INFO ": %s\n",
3242           prefs.capture_show_info == TRUE ? "TRUE" : "FALSE");
3243
3244   fprintf (pf, "\n######## Printing ########\n");
3245
3246   fprintf (pf, "\n# Can be one of \"text\" or \"postscript\".\n"
3247            "print.format: %s\n", pr_formats[prefs.pr_format]);
3248
3249   fprintf (pf, "\n# Can be one of \"command\" or \"file\".\n"
3250            "print.destination: %s\n", pr_dests[prefs.pr_dest]);
3251
3252   fprintf (pf, "\n# This is the file that gets written to when the "
3253            "destination is set to \"file\"\n"
3254            "%s: %s\n", PRS_PRINT_FILE, prefs.pr_file);
3255
3256   fprintf (pf, "\n# Output gets piped to this command when the destination "
3257            "is set to \"command\"\n"
3258            "%s: %s\n", PRS_PRINT_CMD, prefs.pr_cmd);
3259
3260   fprintf(pf, "\n####### Name Resolution ########\n");
3261
3262   fprintf(pf, "\n# Resolve addresses to names?\n");
3263   fprintf(pf, "# TRUE or FALSE (case-insensitive), or a list of address types to resolve.\n");
3264   fprintf(pf, PRS_NAME_RESOLVE ": %s\n",
3265           name_resolve_to_string(prefs.name_resolve));
3266
3267   fprintf(pf, "\n# Name resolution concurrency.\n");
3268   fprintf(pf, "# A decimal number.\n");
3269   fprintf(pf, PRS_NAME_RESOLVE_CONCURRENCY ": %d\n",
3270           prefs.name_resolve_concurrency);
3271
3272   fprintf(pf, "\n# Load SMI modules?\n");
3273   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3274   fprintf(pf, PRS_NAME_RESOLVE_LOAD_SMI_MODULES ": %s\n",
3275           prefs.load_smi_modules == TRUE ? "TRUE" : "FALSE");
3276
3277   fprintf(pf, "\n# Suppress SMI errors?\n");
3278   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3279   fprintf(pf, PRS_NAME_RESOLVE_SUPPRESS_SMI_ERRORS ": %s\n",
3280           prefs.suppress_smi_errors == TRUE ? "TRUE" : "FALSE");
3281
3282   fprintf(pf, "\n####### Taps/Statistics ########\n");
3283
3284   fprintf(pf, "\n# Tap update interval in ms.\n");
3285   fprintf(pf, "# An integer value greater between 100 and 10000.\n");
3286   fprintf(pf, PRS_TAP_UPDATE_INTERVAL ": %d\n",
3287           prefs.tap_update_interval);
3288   fprintf(pf, "\n# Maximum visible channels in RTP Player window.\n");
3289   fprintf(pf, "# An integer value greater than 0.\n");
3290   fprintf(pf, PRS_RTP_PLAYER_MAX_VISIBLE ": %d\n",
3291           prefs.rtp_player_max_visible);
3292
3293   fprintf(pf, "\n####### Protocols ########\n");
3294
3295   fprintf(pf, "\n# Display hidden items in packet details pane?\n");
3296   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3297   fprintf(pf, PRS_DISPLAY_HIDDEN_PROTO_ITEMS ": %s\n",
3298           prefs.display_hidden_proto_items == TRUE ? "TRUE" : "FALSE");
3299
3300   pe_tree_foreach(prefs_modules, write_module_prefs, pf);
3301
3302   fclose(pf);
3303
3304   /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
3305      an error indication, or maybe write to a new preferences file and
3306      rename that file on top of the old one only if there are not I/O
3307      errors. */
3308   return 0;
3309 }
3310
3311 /* Copy a set of preferences. */
3312 void
3313 copy_prefs(e_prefs *dest, e_prefs *src)
3314 {
3315   fmt_data *src_cfmt, *dest_cfmt;
3316   GList *entry;
3317
3318   dest->pr_format = src->pr_format;
3319   dest->pr_dest = src->pr_dest;
3320   dest->pr_file = g_strdup(src->pr_file);
3321   dest->pr_cmd = g_strdup(src->pr_cmd);
3322   dest->col_list = NULL;
3323   for (entry = src->col_list; entry != NULL; entry = g_list_next(entry)) {
3324     src_cfmt = entry->data;
3325     dest_cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
3326     dest_cfmt->title = g_strdup(src_cfmt->title);
3327     dest_cfmt->fmt = g_strdup(src_cfmt->fmt);
3328     if (src_cfmt->custom_field) {
3329       dest_cfmt->custom_field = g_strdup(src_cfmt->custom_field);
3330       dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
3331     } else {
3332       dest_cfmt->custom_field = NULL;
3333       dest_cfmt->custom_occurrence = 0;
3334     }
3335     dest_cfmt->visible = src_cfmt->visible;
3336     dest_cfmt->resolved = src_cfmt->resolved;
3337     dest->col_list = g_list_append(dest->col_list, dest_cfmt);
3338   }
3339   dest->num_cols = src->num_cols;
3340   dest->st_client_fg = src->st_client_fg;
3341   dest->st_client_bg = src->st_client_bg;
3342   dest->st_server_fg = src->st_server_fg;
3343   dest->st_server_bg = src->st_server_bg;
3344   dest->gui_scrollbar_on_right = src->gui_scrollbar_on_right;
3345   dest->gui_plist_sel_browse = src->gui_plist_sel_browse;
3346   dest->gui_ptree_sel_browse = src->gui_ptree_sel_browse;
3347   dest->gui_altern_colors = src->gui_altern_colors;
3348   dest->filter_toolbar_show_in_statusbar = src->filter_toolbar_show_in_statusbar;
3349   dest->gui_ptree_line_style = src->gui_ptree_line_style;
3350   dest->gui_ptree_expander_style = src->gui_ptree_expander_style;
3351   dest->gui_hex_dump_highlight_style = src->gui_hex_dump_highlight_style;
3352   dest->gui_toolbar_main_style = src->gui_toolbar_main_style;
3353   dest->gui_fileopen_dir = g_strdup(src->gui_fileopen_dir);
3354   dest->gui_console_open = src->gui_console_open;
3355   dest->gui_fileopen_style = src->gui_fileopen_style;
3356   dest->gui_fileopen_preview = src->gui_fileopen_preview;
3357   dest->gui_ask_unsaved = src->gui_ask_unsaved;
3358   dest->gui_find_wrap = src->gui_find_wrap;
3359   dest->gui_use_pref_save = src->gui_use_pref_save;
3360   dest->gui_layout_type = src->gui_layout_type;
3361   dest->gui_layout_content_1 = src->gui_layout_content_1;
3362   dest->gui_layout_content_2 = src->gui_layout_content_2;
3363   dest->gui_layout_content_3 = src->gui_layout_content_3;
3364   dest->gui_font_name = g_strdup(src->gui_font_name);
3365   dest->gui_marked_fg = src->gui_marked_fg;
3366   dest->gui_marked_bg = src->gui_marked_bg;
3367   dest->gui_ignored_fg = src->gui_ignored_fg;
3368   dest->gui_ignored_bg = src->gui_ignored_bg;
3369   dest->gui_geometry_save_position = src->gui_geometry_save_position;
3370   dest->gui_geometry_save_size = src->gui_geometry_save_size;
3371   dest->gui_geometry_save_maximized = src->gui_geometry_save_maximized;
3372   dest->gui_macosx_style = src->gui_macosx_style;
3373   dest->gui_webbrowser = g_strdup(src->gui_webbrowser);
3374   dest->gui_window_title = g_strdup(src->gui_window_title);
3375   dest->gui_start_title = g_strdup(src->gui_start_title);
3376   dest->gui_version_in_start_page = src->gui_version_in_start_page;
3377   dest->console_log_level = src->console_log_level;
3378 /*  values for the capture dialog box */
3379   dest->capture_device = g_strdup(src->capture_device);
3380   dest->capture_devices_linktypes = g_strdup(src->capture_devices_linktypes);
3381   dest->capture_devices_descr = g_strdup(src->capture_devices_descr);
3382   dest->capture_devices_hide = g_strdup(src->capture_devices_hide);
3383   dest->capture_devices_monitor_mode = g_strdup(src->capture_devices_monitor_mode);
3384   dest->capture_prom_mode = src->capture_prom_mode;
3385   dest->capture_pcap_ng = src->capture_pcap_ng;
3386   dest->capture_real_time = src->capture_real_time;
3387   dest->capture_auto_scroll = src->capture_auto_scroll;
3388   dest->capture_show_info = src->capture_show_info;
3389   dest->name_resolve = src->name_resolve;
3390   dest->name_resolve_concurrency = src->name_resolve_concurrency;
3391   dest->display_hidden_proto_items = src->display_hidden_proto_items;
3392
3393 }
3394
3395 /* Free a set of preferences. */
3396 void
3397 free_prefs(e_prefs *pr)
3398 {
3399   if (pr->pr_file != NULL) {
3400     g_free(pr->pr_file);
3401     pr->pr_file = NULL;
3402   }
3403   if (pr->pr_cmd != NULL) {
3404     g_free(pr->pr_cmd);
3405     pr->pr_cmd = NULL;
3406   }
3407   free_col_info(pr);
3408   if (pr->gui_font_name != NULL) {
3409     g_free(pr->gui_font_name);
3410     pr->gui_font_name = NULL;
3411   }
3412   if (pr->gui_fileopen_dir != NULL) {
3413     g_free(pr->gui_fileopen_dir);
3414     pr->gui_fileopen_dir = NULL;
3415   }
3416   g_free(pr->gui_webbrowser);
3417   pr->gui_webbrowser = NULL;
3418   if (pr->gui_window_title != NULL) {
3419     g_free(pr->gui_window_title);
3420     pr->gui_window_title = NULL;
3421   }
3422   if (pr->gui_start_title != NULL) {
3423     g_free(pr->gui_start_title);
3424     pr->gui_start_title = NULL;
3425   }
3426   if (pr->capture_device != NULL) {
3427     g_free(pr->capture_device);
3428     pr->capture_device = NULL;
3429   }
3430   if (pr->capture_devices_linktypes != NULL) {
3431     g_free(pr->capture_devices_linktypes);
3432     pr->capture_devices_linktypes = NULL;
3433   }
3434   if (pr->capture_devices_descr != NULL) {
3435     g_free(pr->capture_devices_descr);
3436     pr->capture_devices_descr = NULL;
3437   }
3438   if (pr->capture_devices_hide != NULL) {
3439     g_free(pr->capture_devices_hide);
3440     pr->capture_devices_hide = NULL;
3441   }
3442   if (pr->capture_devices_monitor_mode != NULL) {
3443     g_free(pr->capture_devices_monitor_mode);
3444     pr->capture_devices_monitor_mode = NULL;
3445   }
3446 }
3447
3448 static void
3449 free_col_info(e_prefs *pr)
3450 {
3451   fmt_data *cfmt;
3452
3453   while (pr->col_list != NULL) {
3454     cfmt = pr->col_list->data;
3455
3456     g_free(cfmt->title);
3457     g_free(cfmt->fmt);
3458     g_free(cfmt->custom_field);
3459     g_free(cfmt);
3460     pr->col_list = g_list_remove_link(pr->col_list, pr->col_list);
3461   }
3462   g_list_free(pr->col_list);
3463   pr->col_list = NULL;
3464 }