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