Preferences for x411 moved to p1.
[obnox/wireshark/wip.git] / epan / prefs.c
1 /* prefs.c
2  * Routines for handling preferences
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <errno.h>
33
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include <glib.h>
39
40 #include <stdio.h>
41 #include <epan/filesystem.h>
42 #include <epan/address.h>
43 #include <epan/addr_resolv.h>
44 #include <epan/oids.h>
45 #include <epan/packet.h>
46 #include <epan/prefs.h>
47 #include <epan/proto.h>
48 #include <epan/strutil.h>
49 #include <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", "x411" to "p1"
2421          * and "nsip" to "gprs_ns".
2422          *
2423          * The vlan dissector was integrated into the Ethernet dissector.
2424          *
2425          * The SynOptics Network Management Protocol (SONMP) is now known by
2426          * its modern name, the Nortel Discovery Protocol (NDP).
2427          *
2428          */
2429         if (module == NULL) {
2430           if (strcmp(pref_name, "Diameter") == 0)
2431             module = prefs_find_module("diameter");
2432           else if (strcmp(pref_name, "bxxp") == 0)
2433             module = prefs_find_module("beep");
2434           else if (strcmp(pref_name, "gtpv0") == 0 ||
2435                    strcmp(pref_name, "gtpv1") == 0)
2436             module = prefs_find_module("gtp");
2437           else if (strcmp(pref_name, "smpp-gsm-sms") == 0)
2438             module = prefs_find_module("gsm-sms-ud");
2439           else if (strcmp(pref_name, "dcp") == 0)
2440             module = prefs_find_module("dccp");
2441           else if (strcmp(pref_name, "x.25") == 0)
2442             module = prefs_find_module("x25");
2443           else if (strcmp(pref_name, "x411") == 0)
2444             module = prefs_find_module("p1");
2445           else if (strcmp(pref_name, "vlan") == 0)
2446             module = prefs_find_module("eth");
2447           else if (strcmp(pref_name, "nsip") == 0)
2448             module = prefs_find_module("gprs-ns");
2449           else if (strcmp(pref_name, "sonmp") == 0)
2450             module = prefs_find_module("ndp");
2451           else if (strcmp(pref_name, "etheric") == 0 ||
2452                    strcmp(pref_name, "isup_thin") == 0)
2453             /* This protocols was removed 7. July 2009 */
2454             return PREFS_SET_OBSOLETE;
2455         }
2456         *dotp = '.';            /* put the preference string back */
2457         dotp++;                 /* skip past separator to preference name */
2458         last_dotp = dotp;
2459     }
2460
2461     pref = prefs_find_preference(module, dotp);
2462
2463     if (pref == NULL) {
2464       if (strcmp(module->name, "mgcp") == 0) {
2465         /*
2466          * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
2467          * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
2468          * were used in earlier versions of Wireshark; if we didn't find the
2469          * preference, it was an MGCP preference, and its name was
2470          * "display raw text toggle" or "display dissect tree", look for
2471          * "display_raw_text" or "display_dissect_tree" instead.
2472          *
2473          * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
2474          * the gateway and callagent ports were given those names; we interpret
2475          * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
2476          * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
2477          * they were registered by the MCCP dissector and thus that's the
2478          * order in which they were written to the preferences file.  (If
2479          * we're not reading the preferences file, but are handling stuff
2480          * from a "-o" command-line option, we have no clue which the user
2481          * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
2482          * or "mgcp.{tcp,udp}.callagent_port" instead.)
2483          */
2484         if (strcmp(dotp, "display raw text toggle") == 0)
2485           pref = prefs_find_preference(module, "display_raw_text");
2486         else if (strcmp(dotp, "display dissect tree") == 0)
2487           pref = prefs_find_preference(module, "display_dissect_tree");
2488         else if (strcmp(dotp, "tcp.port") == 0) {
2489           mgcp_tcp_port_count++;
2490           if (mgcp_tcp_port_count == 1) {
2491             /* It's the first one */
2492             pref = prefs_find_preference(module, "tcp.gateway_port");
2493           } else if (mgcp_tcp_port_count == 2) {
2494             /* It's the second one */
2495             pref = prefs_find_preference(module, "tcp.callagent_port");
2496           }
2497           /* Otherwise it's from the command line, and we don't bother
2498              mapping it. */
2499         } else if (strcmp(dotp, "udp.port") == 0) {
2500           mgcp_udp_port_count++;
2501           if (mgcp_udp_port_count == 1) {
2502             /* It's the first one */
2503             pref = prefs_find_preference(module, "udp.gateway_port");
2504           } else if (mgcp_udp_port_count == 2) {
2505             /* It's the second one */
2506             pref = prefs_find_preference(module, "udp.callagent_port");
2507           }
2508           /* Otherwise it's from the command line, and we don't bother
2509              mapping it. */
2510         }
2511       } else if (strcmp(module->name, "smb") == 0) {
2512         /* Handle old names for SMB preferences. */
2513         if (strcmp(dotp, "smb.trans.reassembly") == 0)
2514           pref = prefs_find_preference(module, "trans_reassembly");
2515         else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
2516           pref = prefs_find_preference(module, "dcerpc_reassembly");
2517       } else if (strcmp(module->name, "ndmp") == 0) {
2518         /* Handle old names for NDMP preferences. */
2519         if (strcmp(dotp, "ndmp.desegment") == 0)
2520           pref = prefs_find_preference(module, "desegment");
2521       } else if (strcmp(module->name, "diameter") == 0) {
2522         /* Handle old names for Diameter preferences. */
2523         if (strcmp(dotp, "diameter.desegment") == 0)
2524           pref = prefs_find_preference(module, "desegment");
2525       } else if (strcmp(module->name, "pcli") == 0) {
2526         /* Handle old names for PCLI preferences. */
2527         if (strcmp(dotp, "pcli.udp_port") == 0)
2528           pref = prefs_find_preference(module, "udp_port");
2529       } else if (strcmp(module->name, "artnet") == 0) {
2530         /* Handle old names for ARTNET preferences. */
2531         if (strcmp(dotp, "artnet.udp_port") == 0)
2532           pref = prefs_find_preference(module, "udp_port");
2533       } else if (strcmp(module->name, "mapi") == 0) {
2534         /* Handle old names for MAPI preferences. */
2535         if (strcmp(dotp, "mapi_decrypt") == 0)
2536           pref = prefs_find_preference(module, "decrypt");
2537       } else if (strcmp(module->name, "fc") == 0) {
2538         /* Handle old names for Fibre Channel preferences. */
2539         if (strcmp(dotp, "reassemble_fc") == 0)
2540           pref = prefs_find_preference(module, "reassemble");
2541         else if (strcmp(dotp, "fc_max_frame_size") == 0)
2542           pref = prefs_find_preference(module, "max_frame_size");
2543       } else if (strcmp(module->name, "fcip") == 0) {
2544         /* Handle old names for Fibre Channel-over-IP preferences. */
2545         if (strcmp(dotp, "desegment_fcip_messages") == 0)
2546           pref = prefs_find_preference(module, "desegment");
2547         else if (strcmp(dotp, "fcip_port") == 0)
2548           pref = prefs_find_preference(module, "target_port");
2549       } else if (strcmp(module->name, "gtp") == 0) {
2550         /* Handle old names for GTP preferences. */
2551         if (strcmp(dotp, "gtpv0_port") == 0)
2552           pref = prefs_find_preference(module, "v0_port");
2553         else if (strcmp(dotp, "gtpv1c_port") == 0)
2554           pref = prefs_find_preference(module, "v1c_port");
2555         else if (strcmp(dotp, "gtpv1u_port") == 0)
2556           pref = prefs_find_preference(module, "v1u_port");
2557         else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
2558           pref = prefs_find_preference(module, "dissect_tpdu");
2559         else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
2560           pref = prefs_find_preference(module, "v0_dissect_cdr_as");
2561         else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
2562           pref = prefs_find_preference(module, "v0_check_etsi");
2563         else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
2564           pref = prefs_find_preference(module, "v1_check_etsi");
2565       } else if (strcmp(module->name, "ip") == 0) {
2566         /* Handle old names for IP preferences. */
2567         if (strcmp(dotp, "ip_summary_in_tree") == 0)
2568           pref = prefs_find_preference(module, "summary_in_tree");
2569       } else if (strcmp(module->name, "iscsi") == 0) {
2570         /* Handle old names for iSCSI preferences. */
2571         if (strcmp(dotp, "iscsi_port") == 0)
2572           pref = prefs_find_preference(module, "target_port");
2573       } else if (strcmp(module->name, "lmp") == 0) {
2574         /* Handle old names for LMP preferences. */
2575         if (strcmp(dotp, "lmp_version") == 0)
2576           pref = prefs_find_preference(module, "version");
2577       } else if (strcmp(module->name, "mtp3") == 0) {
2578         /* Handle old names for MTP3 preferences. */
2579         if (strcmp(dotp, "mtp3_standard") == 0)
2580           pref = prefs_find_preference(module, "standard");
2581         else if (strcmp(dotp, "net_addr_format") == 0)
2582           pref = prefs_find_preference(module, "addr_format");
2583       } else if (strcmp(module->name, "nlm") == 0) {
2584         /* Handle old names for NLM preferences. */
2585         if (strcmp(dotp, "nlm_msg_res_matching") == 0)
2586           pref = prefs_find_preference(module, "msg_res_matching");
2587       } else if (strcmp(module->name, "ppp") == 0) {
2588         /* Handle old names for PPP preferences. */
2589         if (strcmp(dotp, "ppp_fcs") == 0)
2590           pref = prefs_find_preference(module, "fcs_type");
2591         else if (strcmp(dotp, "ppp_vj") == 0)
2592           pref = prefs_find_preference(module, "decompress_vj");
2593       } else if (strcmp(module->name, "rsvp") == 0) {
2594         /* Handle old names for RSVP preferences. */
2595         if (strcmp(dotp, "rsvp_process_bundle") == 0)
2596           pref = prefs_find_preference(module, "process_bundle");
2597       } else if (strcmp(module->name, "tcp") == 0) {
2598         /* Handle old names for TCP preferences. */
2599         if (strcmp(dotp, "tcp_summary_in_tree") == 0)
2600           pref = prefs_find_preference(module, "summary_in_tree");
2601         else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
2602           pref = prefs_find_preference(module, "analyze_sequence_numbers");
2603         else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
2604           pref = prefs_find_preference(module, "relative_sequence_numbers");
2605       } else if (strcmp(module->name, "udp") == 0) {
2606         /* Handle old names for UDP preferences. */
2607         if (strcmp(dotp, "udp_summary_in_tree") == 0)
2608           pref = prefs_find_preference(module, "summary_in_tree");
2609       } else if (strcmp(module->name, "ndps") == 0) {
2610         /* Handle old names for NDPS preferences. */
2611         if (strcmp(dotp, "desegment_ndps") == 0)
2612           pref = prefs_find_preference(module, "desegment_tcp");
2613       } else if (strcmp(module->name, "http") == 0) {
2614         /* Handle old names for HTTP preferences. */
2615         if (strcmp(dotp, "desegment_http_headers") == 0)
2616           pref = prefs_find_preference(module, "desegment_headers");
2617         else if (strcmp(dotp, "desegment_http_body") == 0)
2618           pref = prefs_find_preference(module, "desegment_body");
2619       } else if (strcmp(module->name, "smpp") == 0) {
2620         /* Handle preferences that moved from SMPP. */
2621         module_t *new_module = prefs_find_module("gsm-sms-ud");
2622         if(new_module){
2623           if (strcmp(dotp, "port_number_udh_means_wsp") == 0)
2624             pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
2625           else if (strcmp(dotp, "try_dissect_1st_fragment") == 0)
2626             pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
2627         }
2628       } else if (strcmp(module->name, "asn1") == 0) {
2629         /* Handle old generic ASN.1 preferences (it's not really a
2630            rename, as the new preferences support multiple ports,
2631            but we might as well copy them over). */
2632         if (strcmp(dotp, "tcp_port") == 0)
2633           pref = prefs_find_preference(module, "tcp_ports");
2634         else if (strcmp(dotp, "udp_port") == 0)
2635           pref = prefs_find_preference(module, "udp_ports");
2636         else if (strcmp(dotp, "sctp_port") == 0)
2637           pref = prefs_find_preference(module, "sctp_ports");
2638       } else if (strcmp(module->name, "llcgprs") == 0) {
2639         if (strcmp(dotp, "ignore_cipher_bit") == 0)
2640           pref = prefs_find_preference(module, "autodetect_cipher_bit");
2641       } else if (strcmp(module->name, "erf") == 0) {
2642         if (strcmp(dotp, "erfeth") == 0) {
2643           /* Handle the old "erfeth" preference; map it to the new
2644              "ethfcs" preference, and map the values to those for
2645              the new preference. */
2646           pref = prefs_find_preference(module, "ethfcs");
2647           if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
2648             value = "TRUE";
2649           else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
2650             value = "FALSE";
2651           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2652             value = "TRUE";
2653         } else if (strcmp(dotp, "erfatm") == 0) {
2654           /* Handle the old "erfatm" preference; map it to the new
2655              "aal5_type" preference, and map the values to those for
2656              the new preference. */
2657           pref = prefs_find_preference(module, "aal5_type");
2658           if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
2659             value = "guess";
2660           else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
2661             value = "llc";
2662           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2663             value = "guess";
2664         } else if (strcmp(dotp, "erfhdlc") == 0) {
2665           /* Handle the old "erfhdlc" preference; map it to the new
2666              "hdlc_type" preference, and map the values to those for
2667              the new preference. */
2668           pref = prefs_find_preference(module, "hdlc_type");
2669           if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
2670             value = "chdlc";
2671           else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
2672             value = "ppp";
2673           else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
2674             value = "frelay";
2675           else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
2676             value = "mtp2";
2677           else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
2678             value = "guess";
2679         }
2680       }
2681     }
2682     if (pref == NULL)
2683       return PREFS_SET_NO_SUCH_PREF;    /* no such preference */
2684
2685     switch (pref->type) {
2686
2687     case PREF_UINT:
2688       uval = strtoul(value, &p, pref->info.base);
2689       if (p == value || *p != '\0')
2690         return PREFS_SET_SYNTAX_ERR;    /* number was bad */
2691       if (*pref->varp.uint != uval) {
2692         module->prefs_changed = TRUE;
2693         *pref->varp.uint = uval;
2694       }
2695       break;
2696
2697     case PREF_BOOL:
2698       /* XXX - give an error if it's neither "true" nor "false"? */
2699       if (g_ascii_strcasecmp(value, "true") == 0)
2700         bval = TRUE;
2701       else
2702         bval = FALSE;
2703       if (*pref->varp.boolp != bval) {
2704         module->prefs_changed = TRUE;
2705         *pref->varp.boolp = bval;
2706       }
2707       break;
2708
2709     case PREF_ENUM:
2710       /* XXX - give an error if it doesn't match? */
2711       enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
2712                                      *pref->varp.enump);
2713       if (*pref->varp.enump != enum_val) {
2714         module->prefs_changed = TRUE;
2715         *pref->varp.enump = enum_val;
2716       }
2717       break;
2718
2719     case PREF_STRING:
2720       if (strcmp(*pref->varp.string, value) != 0) {
2721         module->prefs_changed = TRUE;
2722         g_free((void *)*pref->varp.string);
2723         *pref->varp.string = g_strdup(value);
2724       }
2725       break;
2726
2727     case PREF_RANGE:
2728     {
2729       range_t *newrange;
2730
2731       if (range_convert_str_work(&newrange, value, pref->info.max_value,
2732                                  return_range_errors) != CVT_NO_ERROR) {
2733         return PREFS_SET_SYNTAX_ERR;    /* number was bad */
2734       }
2735
2736       if (!ranges_are_equal(*pref->varp.range, newrange)) {
2737         module->prefs_changed = TRUE;
2738         g_free(*pref->varp.range);
2739         *pref->varp.range = newrange;
2740       } else {
2741         g_free (newrange);
2742       }
2743       break;
2744     }
2745
2746     case PREF_STATIC_TEXT:
2747     case PREF_UAT:
2748     {
2749       break;
2750     }
2751
2752     case PREF_OBSOLETE:
2753       return PREFS_SET_OBSOLETE;        /* no such preference any more */
2754     }
2755   }
2756
2757   return PREFS_SET_OK;
2758 }
2759
2760 typedef struct {
2761         module_t *module;
2762         FILE    *pf;
2763 } write_pref_arg_t;
2764
2765 /*
2766  * Write out a single preference.
2767  */
2768 static void
2769 write_pref(gpointer data, gpointer user_data)
2770 {
2771         pref_t *pref = data;
2772         write_pref_arg_t *arg = user_data;
2773         const enum_val_t *enum_valp;
2774         const char *val_string;
2775         gchar **desc_lines;
2776         int i;
2777
2778         if (pref->type == PREF_OBSOLETE) {
2779                 /*
2780                  * This preference is no longer supported; it's not a
2781                  * real preference, so we don't write it out (i.e., we
2782                  * treat it as if it weren't found in the list of
2783                  * preferences, and we weren't called in the first place).
2784                  */
2785                 return;
2786         }
2787
2788         /*
2789          * Make multiple line descriptions appear as
2790          * multiple commented lines in prefs file.
2791          */
2792         if (pref->description &&
2793             (g_ascii_strncasecmp(pref->description,"", 2) != 0)) {
2794                 desc_lines = g_strsplit(pref->description,"\n",0);
2795                 for (i = 0; desc_lines[i] != NULL; ++i) {
2796                         fprintf(arg->pf, "\n# %s", desc_lines[i]);
2797                 }
2798                 fprintf(arg->pf, "\n");
2799                 g_strfreev(desc_lines);
2800         } else {
2801                 fprintf(arg->pf, "\n# No description\n");
2802         }
2803
2804         switch (pref->type) {
2805
2806         case PREF_UINT:
2807                 switch (pref->info.base) {
2808
2809                 case 10:
2810                         fprintf(arg->pf, "# A decimal number.\n");
2811                         if (pref->default_val.uint == *pref->varp.uint)
2812                             fprintf(arg->pf, "#");
2813                         fprintf(arg->pf, "%s.%s: %u\n", arg->module->name,
2814                             pref->name, *pref->varp.uint);
2815                         break;
2816
2817                 case 8:
2818                         fprintf(arg->pf, "# An octal number.\n");
2819                         if (pref->default_val.uint == *pref->varp.uint)
2820                             fprintf(arg->pf, "#");
2821                         fprintf(arg->pf, "%s.%s: %#o\n", arg->module->name,
2822                             pref->name, *pref->varp.uint);
2823                         break;
2824
2825                 case 16:
2826                         fprintf(arg->pf, "# A hexadecimal number.\n");
2827                         if (pref->default_val.uint == *pref->varp.uint)
2828                             fprintf(arg->pf, "#");
2829                         fprintf(arg->pf, "%s.%s: %#x\n", arg->module->name,
2830                             pref->name, *pref->varp.uint);
2831                         break;
2832                 }
2833                 break;
2834
2835         case PREF_BOOL:
2836                 fprintf(arg->pf, "# TRUE or FALSE (case-insensitive).\n");
2837                 if (pref->default_val.boolval == *pref->varp.boolp)
2838                     fprintf(arg->pf, "#");
2839                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2840                     *pref->varp.boolp ? "TRUE" : "FALSE");
2841                 break;
2842
2843         case PREF_ENUM:
2844                 /*
2845                  * For now, we save the "description" value, so that if we
2846                  * save the preferences older versions of Wireshark can at
2847                  * least read preferences that they supported; we support
2848                  * either the short name or the description when reading
2849                  * the preferences file or a "-o" option.
2850                  */
2851                 fprintf(arg->pf, "# One of: ");
2852                 enum_valp = pref->info.enum_info.enumvals;
2853                 val_string = NULL;
2854                 while (enum_valp->name != NULL) {
2855                         if (enum_valp->value == *pref->varp.enump)
2856                                 val_string = enum_valp->description;
2857                         fprintf(arg->pf, "%s", enum_valp->description);
2858                         enum_valp++;
2859                         if (enum_valp->name == NULL)
2860                                 fprintf(arg->pf, "\n");
2861                         else
2862                                 fprintf(arg->pf, ", ");
2863                 }
2864                 fprintf(arg->pf, "# (case-insensitive).\n");
2865                 if (pref->default_val.enumval == *pref->varp.enump)
2866                     fprintf(arg->pf, "#");
2867                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name,
2868                     pref->name, val_string);
2869                 break;
2870
2871         case PREF_STRING:
2872                 fprintf(arg->pf, "# A string.\n");
2873                 if (!(strcmp(pref->default_val.string, *pref->varp.string)))
2874                     fprintf(arg->pf, "#");
2875                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2876                     *pref->varp.string);
2877                 break;
2878
2879         case PREF_RANGE:
2880         {
2881                 char *range_string_p;
2882
2883                 range_string_p = range_convert_range(*pref->varp.range);
2884                 fprintf(arg->pf, "# A string denoting an positive integer range (e.g., \"1-20,30-40\").\n");
2885                 if ((ranges_are_equal(pref->default_val.range, *pref->varp.range)))
2886                     fprintf(arg->pf, "#");
2887                 fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
2888                         range_string_p);
2889                 break;
2890         }
2891
2892         case PREF_STATIC_TEXT:
2893         case PREF_UAT:
2894         {
2895                 /* Nothing to do */
2896                 break;
2897         }
2898
2899         case PREF_OBSOLETE:
2900                 g_assert_not_reached();
2901                 break;
2902         }
2903 }
2904
2905 static gboolean
2906 write_module_prefs(void *value, void *data)
2907 {
2908         write_pref_arg_t arg;
2909
2910         arg.module = value;
2911         arg.pf = data;
2912         g_list_foreach(arg.module->prefs, write_pref, &arg);
2913         return FALSE;
2914 }
2915
2916 /* Write out "prefs" to the user's preferences file, and return 0.
2917
2918    If the preferences file path is NULL, write to stdout.
2919
2920    If we got an error, stuff a pointer to the path of the preferences file
2921    into "*pf_path_return", and return the errno. */
2922 int
2923 write_prefs(char **pf_path_return)
2924 {
2925   char        *pf_path;
2926   FILE        *pf;
2927   GList       *clp, *col_l;
2928   fmt_data    *cfmt;
2929   const gchar *cust_format = col_format_to_string(COL_CUSTOM);
2930   GString     *cols_hidden = g_string_new ("");
2931
2932   /* Needed for "-G defaultprefs" */
2933   init_prefs();
2934
2935   /* To do:
2936    * - Split output lines longer than MAX_VAL_LEN
2937    * - Create a function for the preference directory check/creation
2938    *   so that duplication can be avoided with filter.c
2939    */
2940
2941   if (pf_path_return != NULL) {
2942     pf_path = get_persconffile_path(PF_NAME, TRUE, TRUE);
2943     if ((pf = ws_fopen(pf_path, "w")) == NULL) {
2944       *pf_path_return = pf_path;
2945       return errno;
2946     }
2947   } else {
2948     pf = stdout;
2949   }
2950
2951   fputs("# Configuration file for Wireshark " VERSION ".\n"
2952         "#\n"
2953         "# This file is regenerated each time preferences are saved within\n"
2954         "# Wireshark.  Making manual changes should be safe, however.\n"
2955         "# Protocol preferences that have been commented out have not been\n"
2956         "# changed from their default value.\n", pf);
2957
2958   fprintf (pf, "\n######## User Interface ########\n");
2959
2960   fprintf(pf, "\n# Vertical scrollbars should be on right side?\n");
2961   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2962   fprintf(pf, PRS_GUI_SCROLLBAR_ON_RIGHT ": %s\n",
2963           prefs.gui_scrollbar_on_right == TRUE ? "TRUE" : "FALSE");
2964
2965   fprintf(pf, "\n# Packet-list selection bar can be used to browse w/o selecting?\n");
2966   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2967   fprintf(pf, PRS_GUI_PLIST_SEL_BROWSE ": %s\n",
2968           prefs.gui_plist_sel_browse == TRUE ? "TRUE" : "FALSE");
2969
2970   fprintf(pf, "\n# Protocol-tree selection bar can be used to browse w/o selecting?\n");
2971   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2972   fprintf(pf, PRS_GUI_PTREE_SEL_BROWSE ": %s\n",
2973           prefs.gui_ptree_sel_browse == TRUE ? "TRUE" : "FALSE");
2974
2975   fprintf(pf, "\n# Alternating colors in TreeViews?\n");
2976   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2977   fprintf(pf, PRS_GUI_ALTERN_COLORS ": %s\n",
2978           prefs.gui_altern_colors == TRUE ? "TRUE" : "FALSE");
2979
2980   fprintf(pf, "\n# Place filter toolbar inside the statusbar?\n");
2981   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
2982   fprintf(pf, PRS_GUI_FILTER_TOOLBAR_IN_STATUSBAR ": %s\n",
2983          prefs.filter_toolbar_show_in_statusbar == TRUE ? "TRUE" : "FALSE");
2984
2985   fprintf(pf, "\n# Protocol-tree line style.\n");
2986   fprintf(pf, "# One of: NONE, SOLID, DOTTED, TABBED\n");
2987   fprintf(pf, PRS_GUI_PTREE_LINE_STYLE ": %s\n",
2988           gui_ptree_line_style_text[prefs.gui_ptree_line_style]);
2989
2990   fprintf(pf, "\n# Protocol-tree expander style.\n");
2991   fprintf(pf, "# One of: NONE, SQUARE, TRIANGLE, CIRCULAR\n");
2992   fprintf(pf, PRS_GUI_PTREE_EXPANDER_STYLE ": %s\n",
2993           gui_ptree_expander_style_text[prefs.gui_ptree_expander_style]);
2994
2995   fprintf(pf, "\n# Hex dump highlight style.\n");
2996   fprintf(pf, "# One of: BOLD, INVERSE\n");
2997   fprintf(pf, PRS_GUI_HEX_DUMP_HIGHLIGHT_STYLE ": %s\n",
2998           gui_hex_dump_highlight_style_text[prefs.gui_hex_dump_highlight_style]);
2999
3000   fprintf(pf, "\n# Main Toolbar style.\n");
3001   fprintf(pf, "# One of: ICONS, TEXT, BOTH\n");
3002   fprintf(pf, PRS_GUI_TOOLBAR_MAIN_STYLE ": %s\n",
3003           gui_toolbar_style_text[prefs.gui_toolbar_main_style]);
3004
3005   fprintf(pf, "\n# Filter Toolbar style.\n");
3006   fprintf(pf, "# One of: ICONS, TEXT, BOTH\n");
3007   fprintf(pf, PRS_GUI_TOOLBAR_FILTER_STYLE ": %s\n",
3008           gui_toolbar_style_text[prefs.gui_toolbar_filter_style]);
3009
3010   fprintf(pf, "\n# Save window position at exit?\n");
3011   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3012   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_POSITION ": %s\n",
3013           prefs.gui_geometry_save_position == TRUE ? "TRUE" : "FALSE");
3014
3015   fprintf(pf, "\n# Save window size at exit?\n");
3016   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3017   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_SIZE ": %s\n",
3018           prefs.gui_geometry_save_size == TRUE ? "TRUE" : "FALSE");
3019
3020   fprintf(pf, "\n# Save window maximized state at exit?\n");
3021   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3022   fprintf(pf, PRS_GUI_GEOMETRY_SAVE_MAXIMIZED ": %s\n",
3023           prefs.gui_geometry_save_maximized == TRUE ? "TRUE" : "FALSE");
3024
3025   fprintf(pf, "\n# Use Mac OS X style (Mac OS X with native GTK only)?\n");
3026   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3027   fprintf(pf, PRS_GUI_MACOSX_STYLE ": %s\n",
3028           prefs.gui_macosx_style == TRUE ? "TRUE" : "FALSE");
3029
3030   fprintf(pf, "\n# Open a console window (WIN32 only)?\n");
3031   fprintf(pf, "# One of: NEVER, AUTOMATIC, ALWAYS\n");
3032   fprintf(pf, PRS_GUI_CONSOLE_OPEN ": %s\n",
3033           gui_console_open_text[prefs.gui_console_open]);
3034
3035   fprintf(pf, "\n# The max. number of entries in the display filter list.\n");
3036   fprintf(pf, "# A decimal number.\n");
3037   fprintf(pf, PRS_GUI_RECENT_DF_ENTRIES_MAX ": %d\n",
3038           prefs.gui_recent_df_entries_max);
3039
3040   fprintf(pf, "\n# The max. number of items in the open recent files list.\n");
3041   fprintf(pf, "# A decimal number.\n");
3042   fprintf(pf, PRS_GUI_RECENT_COUNT_MAX ": %d\n",
3043           prefs.gui_recent_files_count_max);
3044
3045   fprintf(pf, "\n# Where to start the File Open dialog box.\n");
3046   fprintf(pf, "# One of: LAST_OPENED, SPECIFIED\n");
3047   fprintf(pf, PRS_GUI_FILEOPEN_STYLE ": %s\n",
3048           gui_fileopen_style_text[prefs.gui_fileopen_style]);
3049
3050   if (prefs.gui_fileopen_dir != NULL) {
3051     fprintf(pf, "\n# Directory to start in when opening File Open dialog.\n");
3052     fprintf(pf, PRS_GUI_FILEOPEN_DIR ": %s\n",
3053             prefs.gui_fileopen_dir);
3054   }
3055
3056   fprintf(pf, "\n# The preview timeout in the File Open dialog.\n");
3057   fprintf(pf, "# A decimal number (in seconds).\n");
3058   fprintf(pf, PRS_GUI_FILEOPEN_PREVIEW ": %d\n",
3059           prefs.gui_fileopen_preview);
3060
3061   fprintf(pf, "\n# Ask to save unsaved capture files?\n");
3062   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3063   fprintf(pf, PRS_GUI_ASK_UNSAVED ": %s\n",
3064           prefs.gui_ask_unsaved == TRUE ? "TRUE" : "FALSE");
3065
3066   fprintf(pf, "\n# Wrap to beginning/end of file during search?\n");
3067   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3068   fprintf(pf, PRS_GUI_FIND_WRAP ": %s\n",
3069           prefs.gui_find_wrap == TRUE ? "TRUE" : "FALSE");
3070
3071   fprintf(pf, "\n# Settings dialogs use a save button?\n");
3072   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3073   fprintf(pf, PRS_GUI_USE_PREF_SAVE ": %s\n",
3074           prefs.gui_use_pref_save == TRUE ? "TRUE" : "FALSE");
3075
3076   fprintf(pf, "\n# The path to the webbrowser.\n");
3077   fprintf(pf, "# Ex: mozilla %%s\n");
3078   fprintf(pf, PRS_GUI_WEBBROWSER ": %s\n", prefs.gui_webbrowser);
3079
3080   fprintf(pf, "\n# Custom window title. (Appended to existing titles.)\n");
3081   fprintf(pf, PRS_GUI_WINDOW_TITLE ": %s\n",
3082           prefs.gui_window_title);
3083
3084   fprintf(pf, "\n# Custom start page title.\n");
3085   fprintf(pf, PRS_GUI_START_TITLE ": %s\n",
3086           prefs.gui_start_title);
3087
3088   fprintf(pf, "\n# Show version in the start page and main screen's title bar.\n");
3089   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3090   fprintf(pf, PRS_GUI_VERSION_IN_START_PAGE ": %s\n",
3091           prefs.gui_version_in_start_page == TRUE ? "TRUE" : "FALSE");
3092
3093   fprintf (pf, "\n######## User Interface: Layout ########\n");
3094
3095   fprintf(pf, "\n# Layout type (1-6).\n");
3096   fprintf(pf, PRS_GUI_LAYOUT_TYPE ": %d\n",
3097           prefs.gui_layout_type);
3098
3099   fprintf(pf, "\n# Layout content of the panes (1-3).\n");
3100   fprintf(pf, "# One of: NONE, PLIST, PDETAILS, PBYTES\n");
3101   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_1 ": %s\n",
3102           gui_layout_content_text[prefs.gui_layout_content_1]);
3103   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_2 ": %s\n",
3104           gui_layout_content_text[prefs.gui_layout_content_2]);
3105   fprintf(pf, PRS_GUI_LAYOUT_CONTENT_3 ": %s\n",
3106           gui_layout_content_text[prefs.gui_layout_content_3]);
3107
3108   fprintf (pf, "\n######## User Interface: Columns ########\n");
3109
3110   clp = prefs.col_list;
3111   col_l = NULL;
3112   while (clp) {
3113     gchar *prefs_fmt;
3114     cfmt = (fmt_data *) clp->data;
3115     col_l = g_list_append(col_l, g_strdup(cfmt->title));
3116     if ((strcmp(cfmt->fmt, cust_format) == 0) && (cfmt->custom_field)) {
3117       prefs_fmt = g_strdup_printf("%s:%s:%d:%c", cfmt->fmt, cfmt->custom_field,
3118                                   cfmt->custom_occurrence, cfmt->resolved ? 'R' : 'U');
3119       col_l = g_list_append(col_l, prefs_fmt);
3120     } else {
3121       prefs_fmt = cfmt->fmt;
3122       col_l = g_list_append(col_l, g_strdup(cfmt->fmt));
3123     }
3124     if (!cfmt->visible) {
3125       if (cols_hidden->len) {
3126         g_string_append (cols_hidden, ",");
3127       }
3128       g_string_append (cols_hidden, prefs_fmt);
3129     }
3130     clp = clp->next;
3131   }
3132   fprintf (pf, "\n# Packet list hidden columns.\n");
3133   fprintf (pf, "# List all columns to hide in the packet list.\n");
3134   fprintf (pf, "%s: %s\n", PRS_COL_HIDDEN, cols_hidden->str);
3135   /* This frees the list of strings, but not the strings to which it
3136      refers; they are free'ed in put_string_list(). */
3137   g_string_free (cols_hidden, TRUE);
3138
3139   fprintf (pf, "\n# Packet list column format.\n");
3140   fprintf (pf, "# Each pair of strings consists of a column title and its format.\n");
3141   fprintf (pf, "%s: %s\n", PRS_COL_FMT, put_string_list(col_l));
3142   /* This frees the list of strings, but not the strings to which it
3143      refers; they are free'ed in put_string_list(). */
3144   g_list_free(col_l);
3145
3146   fprintf (pf, "\n######## User Interface: Font ########\n");
3147
3148   fprintf(pf, "\n# Font name for packet list, protocol tree, and hex dump panes.\n");
3149   fprintf(pf, PRS_GUI_FONT_NAME_2 ": %s\n", prefs.gui_font_name);
3150
3151   fprintf (pf, "\n######## User Interface: Colors ########\n");
3152
3153   fprintf (pf, "\n# Color preferences for a marked frame.\n");
3154   fprintf (pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
3155   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_MARKED_FG,
3156            (prefs.gui_marked_fg.red * 255 / 65535),
3157            (prefs.gui_marked_fg.green * 255 / 65535),
3158            (prefs.gui_marked_fg.blue * 255 / 65535));
3159   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_MARKED_BG,
3160            (prefs.gui_marked_bg.red * 255 / 65535),
3161            (prefs.gui_marked_bg.green * 255 / 65535),
3162            (prefs.gui_marked_bg.blue * 255 / 65535));
3163
3164   fprintf (pf, "\n# Color preferences for a ignored frame.\n");
3165   fprintf (pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
3166   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_IGNORED_FG,
3167            (prefs.gui_ignored_fg.red * 255 / 65535),
3168            (prefs.gui_ignored_fg.green * 255 / 65535),
3169            (prefs.gui_ignored_fg.blue * 255 / 65535));
3170   fprintf (pf, "%s: %02x%02x%02x\n", PRS_GUI_IGNORED_BG,
3171            (prefs.gui_ignored_bg.red * 255 / 65535),
3172            (prefs.gui_ignored_bg.green * 255 / 65535),
3173            (prefs.gui_ignored_bg.blue * 255 / 65535));
3174
3175   /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
3176    * file until the colors can be changed in the GUI. Currently this is not really
3177    * possible since the STOCK-icons for these colors are hardcoded.
3178    *
3179    * XXX Find a way to change the colors of the STOCK-icons on the fly and then
3180    *     add these 10 colors to the list of colors that can be changed through
3181    *     the preferences.
3182    *
3183   fprintf (pf, "%s: %s\n", PRS_GUI_COLORIZED_FG, prefs.gui_colorized_fg);
3184   fprintf (pf, "%s: %s\n", PRS_GUI_COLORIZED_BG, prefs.gui_colorized_bg);
3185   */
3186
3187   fprintf (pf, "\n# TCP stream window color preferences.\n");
3188   fprintf (pf, "# Each value is a six digit hexadecimal color value in the form rrggbb.\n");
3189   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_CL_FG,
3190            (prefs.st_client_fg.red * 255 / 65535),
3191            (prefs.st_client_fg.green * 255 / 65535),
3192            (prefs.st_client_fg.blue * 255 / 65535));
3193   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_CL_BG,
3194            (prefs.st_client_bg.red * 255 / 65535),
3195            (prefs.st_client_bg.green * 255 / 65535),
3196            (prefs.st_client_bg.blue * 255 / 65535));
3197   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_SR_FG,
3198            (prefs.st_server_fg.red * 255 / 65535),
3199            (prefs.st_server_fg.green * 255 / 65535),
3200            (prefs.st_server_fg.blue * 255 / 65535));
3201   fprintf (pf, "%s: %02x%02x%02x\n", PRS_STREAM_SR_BG,
3202            (prefs.st_server_bg.red * 255 / 65535),
3203            (prefs.st_server_bg.green * 255 / 65535),
3204            (prefs.st_server_bg.blue * 255 / 65535));
3205
3206   fprintf(pf, "\n######## Console: logging level ########\n");
3207   fprintf(pf, "# (debugging only, not in the Preferences dialog)\n");
3208   fprintf(pf, "# A bitmask of glib log levels:\n"
3209           "# G_LOG_LEVEL_ERROR    = 4\n"
3210           "# G_LOG_LEVEL_CRITICAL = 8\n"
3211           "# G_LOG_LEVEL_WARNING  = 16\n"
3212           "# G_LOG_LEVEL_MESSAGE  = 32\n"
3213           "# G_LOG_LEVEL_INFO     = 64\n"
3214           "# G_LOG_LEVEL_DEBUG    = 128\n");
3215
3216   fprintf(pf, PRS_CONSOLE_LOG_LEVEL ": %u\n",
3217           prefs.console_log_level);
3218
3219   fprintf(pf, "\n####### Capture ########\n");
3220
3221   if (prefs.capture_device != NULL) {
3222     fprintf(pf, "\n# Default capture device\n");
3223     fprintf(pf, PRS_CAP_DEVICE ": %s\n", prefs.capture_device);
3224   }
3225
3226   if (prefs.capture_devices_linktypes != NULL) {
3227     fprintf(pf, "\n# Interface link-layer header types.\n");
3228     fprintf(pf, "# A decimal number for the DLT.\n");
3229     fprintf(pf, "# Ex: en0(1),en1(143),...\n");
3230     fprintf(pf, PRS_CAP_DEVICES_LINKTYPES ": %s\n", prefs.capture_devices_linktypes);
3231   }
3232
3233   if (prefs.capture_devices_descr != NULL) {
3234     fprintf(pf, "\n# Interface descriptions.\n");
3235     fprintf(pf, "# Ex: eth0(eth0 descr),eth1(eth1 descr),...\n");
3236     fprintf(pf, PRS_CAP_DEVICES_DESCR ": %s\n", prefs.capture_devices_descr);
3237   }
3238
3239   if (prefs.capture_devices_hide != NULL) {
3240     fprintf(pf, "\n# Hide interface?\n");
3241     fprintf(pf, "# Ex: eth0,eth3,...\n");
3242     fprintf(pf, PRS_CAP_DEVICES_HIDE ": %s\n", prefs.capture_devices_hide);
3243   }
3244
3245   if (prefs.capture_devices_monitor_mode != NULL) {
3246     fprintf(pf, "\n# By default, capture in monitor mode on interface?\n");
3247     fprintf(pf, "# Ex: eth0,eth3,...\n");
3248     fprintf(pf, PRS_CAP_DEVICES_MONITOR_MODE ": %s\n", prefs.capture_devices_monitor_mode);
3249   }
3250
3251   fprintf(pf, "\n# Capture in promiscuous mode?\n");
3252   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3253   fprintf(pf, PRS_CAP_PROM_MODE ": %s\n",
3254           prefs.capture_prom_mode == TRUE ? "TRUE" : "FALSE");
3255
3256   fprintf(pf, "\n# Capture in Pcap-NG format?\n");
3257   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3258   fprintf(pf, PRS_CAP_PCAP_NG ": %s\n",
3259           prefs.capture_pcap_ng == TRUE ? "TRUE" : "FALSE");
3260
3261   fprintf(pf, "\n# Update packet list in real time during capture?\n");
3262   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3263   fprintf(pf, PRS_CAP_REAL_TIME ": %s\n",
3264           prefs.capture_real_time == TRUE ? "TRUE" : "FALSE");
3265
3266   fprintf(pf, "\n# Scroll packet list during capture?\n");
3267   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3268   fprintf(pf, PRS_CAP_AUTO_SCROLL ": %s\n",
3269           prefs.capture_auto_scroll == TRUE ? "TRUE" : "FALSE");
3270
3271   fprintf(pf, "\n# Show capture info dialog while capturing?\n");
3272   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3273   fprintf(pf, PRS_CAP_SHOW_INFO ": %s\n",
3274           prefs.capture_show_info == TRUE ? "TRUE" : "FALSE");
3275
3276   fprintf (pf, "\n######## Printing ########\n");
3277
3278   fprintf (pf, "\n# Can be one of \"text\" or \"postscript\".\n"
3279            "print.format: %s\n", pr_formats[prefs.pr_format]);
3280
3281   fprintf (pf, "\n# Can be one of \"command\" or \"file\".\n"
3282            "print.destination: %s\n", pr_dests[prefs.pr_dest]);
3283
3284   fprintf (pf, "\n# This is the file that gets written to when the "
3285            "destination is set to \"file\"\n"
3286            "%s: %s\n", PRS_PRINT_FILE, prefs.pr_file);
3287
3288   fprintf (pf, "\n# Output gets piped to this command when the destination "
3289            "is set to \"command\"\n"
3290            "%s: %s\n", PRS_PRINT_CMD, prefs.pr_cmd);
3291
3292   fprintf(pf, "\n####### Name Resolution ########\n");
3293
3294   fprintf(pf, "\n# Resolve addresses to names?\n");
3295   fprintf(pf, "# TRUE or FALSE (case-insensitive), or a list of address types to resolve.\n");
3296   fprintf(pf, PRS_NAME_RESOLVE ": %s\n",
3297           name_resolve_to_string(prefs.name_resolve));
3298
3299   fprintf(pf, "\n# Name resolution concurrency.\n");
3300   fprintf(pf, "# A decimal number.\n");
3301   fprintf(pf, PRS_NAME_RESOLVE_CONCURRENCY ": %d\n",
3302           prefs.name_resolve_concurrency);
3303
3304   fprintf(pf, "\n# Load SMI modules?\n");
3305   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3306   fprintf(pf, PRS_NAME_RESOLVE_LOAD_SMI_MODULES ": %s\n",
3307           prefs.load_smi_modules == TRUE ? "TRUE" : "FALSE");
3308
3309   fprintf(pf, "\n# Suppress SMI errors?\n");
3310   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3311   fprintf(pf, PRS_NAME_RESOLVE_SUPPRESS_SMI_ERRORS ": %s\n",
3312           prefs.suppress_smi_errors == TRUE ? "TRUE" : "FALSE");
3313
3314   fprintf(pf, "\n####### Taps/Statistics ########\n");
3315
3316   fprintf(pf, "\n# Tap update interval in ms.\n");
3317   fprintf(pf, "# An integer value greater between 100 and 10000.\n");
3318   fprintf(pf, PRS_TAP_UPDATE_INTERVAL ": %d\n",
3319           prefs.tap_update_interval);
3320   fprintf(pf, "\n# Maximum visible channels in RTP Player window.\n");
3321   fprintf(pf, "# An integer value greater than 0.\n");
3322   fprintf(pf, PRS_RTP_PLAYER_MAX_VISIBLE ": %d\n",
3323           prefs.rtp_player_max_visible);
3324
3325   fprintf(pf, "\n####### Protocols ########\n");
3326
3327   fprintf(pf, "\n# Display hidden items in packet details pane?\n");
3328   fprintf(pf, "# TRUE or FALSE (case-insensitive).\n");
3329   fprintf(pf, PRS_DISPLAY_HIDDEN_PROTO_ITEMS ": %s\n",
3330           prefs.display_hidden_proto_items == TRUE ? "TRUE" : "FALSE");
3331
3332   pe_tree_foreach(prefs_modules, write_module_prefs, pf);
3333
3334   fclose(pf);
3335
3336   /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
3337      an error indication, or maybe write to a new preferences file and
3338      rename that file on top of the old one only if there are not I/O
3339      errors. */
3340   return 0;
3341 }
3342
3343 /* Copy a set of preferences. */
3344 void
3345 copy_prefs(e_prefs *dest, e_prefs *src)
3346 {
3347   fmt_data *src_cfmt, *dest_cfmt;
3348   GList *entry;
3349
3350   dest->pr_format = src->pr_format;
3351   dest->pr_dest = src->pr_dest;
3352   dest->pr_file = g_strdup(src->pr_file);
3353   dest->pr_cmd = g_strdup(src->pr_cmd);
3354   dest->col_list = NULL;
3355   for (entry = src->col_list; entry != NULL; entry = g_list_next(entry)) {
3356     src_cfmt = entry->data;
3357     dest_cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
3358     dest_cfmt->title = g_strdup(src_cfmt->title);
3359     dest_cfmt->fmt = g_strdup(src_cfmt->fmt);
3360     if (src_cfmt->custom_field) {
3361       dest_cfmt->custom_field = g_strdup(src_cfmt->custom_field);
3362       dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
3363     } else {
3364       dest_cfmt->custom_field = NULL;
3365       dest_cfmt->custom_occurrence = 0;
3366     }
3367     dest_cfmt->visible = src_cfmt->visible;
3368     dest_cfmt->resolved = src_cfmt->resolved;
3369     dest->col_list = g_list_append(dest->col_list, dest_cfmt);
3370   }
3371   dest->num_cols = src->num_cols;
3372   dest->st_client_fg = src->st_client_fg;
3373   dest->st_client_bg = src->st_client_bg;
3374   dest->st_server_fg = src->st_server_fg;
3375   dest->st_server_bg = src->st_server_bg;
3376   dest->gui_scrollbar_on_right = src->gui_scrollbar_on_right;
3377   dest->gui_plist_sel_browse = src->gui_plist_sel_browse;
3378   dest->gui_ptree_sel_browse = src->gui_ptree_sel_browse;
3379   dest->gui_altern_colors = src->gui_altern_colors;
3380   dest->filter_toolbar_show_in_statusbar = src->filter_toolbar_show_in_statusbar;
3381   dest->gui_ptree_line_style = src->gui_ptree_line_style;
3382   dest->gui_ptree_expander_style = src->gui_ptree_expander_style;
3383   dest->gui_hex_dump_highlight_style = src->gui_hex_dump_highlight_style;
3384   dest->gui_toolbar_main_style = src->gui_toolbar_main_style;
3385   dest->gui_fileopen_dir = g_strdup(src->gui_fileopen_dir);
3386   dest->gui_console_open = src->gui_console_open;
3387   dest->gui_fileopen_style = src->gui_fileopen_style;
3388   dest->gui_fileopen_preview = src->gui_fileopen_preview;
3389   dest->gui_ask_unsaved = src->gui_ask_unsaved;
3390   dest->gui_find_wrap = src->gui_find_wrap;
3391   dest->gui_use_pref_save = src->gui_use_pref_save;
3392   dest->gui_layout_type = src->gui_layout_type;
3393   dest->gui_layout_content_1 = src->gui_layout_content_1;
3394   dest->gui_layout_content_2 = src->gui_layout_content_2;
3395   dest->gui_layout_content_3 = src->gui_layout_content_3;
3396   dest->gui_font_name = g_strdup(src->gui_font_name);
3397   dest->gui_marked_fg = src->gui_marked_fg;
3398   dest->gui_marked_bg = src->gui_marked_bg;
3399   dest->gui_ignored_fg = src->gui_ignored_fg;
3400   dest->gui_ignored_bg = src->gui_ignored_bg;
3401   dest->gui_geometry_save_position = src->gui_geometry_save_position;
3402   dest->gui_geometry_save_size = src->gui_geometry_save_size;
3403   dest->gui_geometry_save_maximized = src->gui_geometry_save_maximized;
3404   dest->gui_macosx_style = src->gui_macosx_style;
3405   dest->gui_webbrowser = g_strdup(src->gui_webbrowser);
3406   dest->gui_window_title = g_strdup(src->gui_window_title);
3407   dest->gui_start_title = g_strdup(src->gui_start_title);
3408   dest->gui_version_in_start_page = src->gui_version_in_start_page;
3409   dest->console_log_level = src->console_log_level;
3410 /*  values for the capture dialog box */
3411   dest->capture_device = g_strdup(src->capture_device);
3412   dest->capture_devices_linktypes = g_strdup(src->capture_devices_linktypes);
3413   dest->capture_devices_descr = g_strdup(src->capture_devices_descr);
3414   dest->capture_devices_hide = g_strdup(src->capture_devices_hide);
3415   dest->capture_devices_monitor_mode = g_strdup(src->capture_devices_monitor_mode);
3416   dest->capture_prom_mode = src->capture_prom_mode;
3417   dest->capture_pcap_ng = src->capture_pcap_ng;
3418   dest->capture_real_time = src->capture_real_time;
3419   dest->capture_auto_scroll = src->capture_auto_scroll;
3420   dest->capture_show_info = src->capture_show_info;
3421   dest->name_resolve = src->name_resolve;
3422   dest->name_resolve_concurrency = src->name_resolve_concurrency;
3423   dest->display_hidden_proto_items = src->display_hidden_proto_items;
3424
3425 }
3426
3427 /* Free a set of preferences. */
3428 void
3429 free_prefs(e_prefs *pr)
3430 {
3431   if (pr->pr_file != NULL) {
3432     g_free(pr->pr_file);
3433     pr->pr_file = NULL;
3434   }
3435   if (pr->pr_cmd != NULL) {
3436     g_free(pr->pr_cmd);
3437     pr->pr_cmd = NULL;
3438   }
3439   free_col_info(pr);
3440   if (pr->gui_font_name != NULL) {
3441     g_free(pr->gui_font_name);
3442     pr->gui_font_name = NULL;
3443   }
3444   if (pr->gui_fileopen_dir != NULL) {
3445     g_free(pr->gui_fileopen_dir);
3446     pr->gui_fileopen_dir = NULL;
3447   }
3448   g_free(pr->gui_webbrowser);
3449   pr->gui_webbrowser = NULL;
3450   if (pr->gui_window_title != NULL) {
3451     g_free(pr->gui_window_title);
3452     pr->gui_window_title = NULL;
3453   }
3454   if (pr->gui_start_title != NULL) {
3455     g_free(pr->gui_start_title);
3456     pr->gui_start_title = NULL;
3457   }
3458   if (pr->capture_device != NULL) {
3459     g_free(pr->capture_device);
3460     pr->capture_device = NULL;
3461   }
3462   if (pr->capture_devices_linktypes != NULL) {
3463     g_free(pr->capture_devices_linktypes);
3464     pr->capture_devices_linktypes = NULL;
3465   }
3466   if (pr->capture_devices_descr != NULL) {
3467     g_free(pr->capture_devices_descr);
3468     pr->capture_devices_descr = NULL;
3469   }
3470   if (pr->capture_devices_hide != NULL) {
3471     g_free(pr->capture_devices_hide);
3472     pr->capture_devices_hide = NULL;
3473   }
3474   if (pr->capture_devices_monitor_mode != NULL) {
3475     g_free(pr->capture_devices_monitor_mode);
3476     pr->capture_devices_monitor_mode = NULL;
3477   }
3478 }
3479
3480 static void
3481 free_col_info(e_prefs *pr)
3482 {
3483   fmt_data *cfmt;
3484
3485   while (pr->col_list != NULL) {
3486     cfmt = pr->col_list->data;
3487
3488     g_free(cfmt->title);
3489     g_free(cfmt->fmt);
3490     g_free(cfmt->custom_field);
3491     g_free(cfmt);
3492     pr->col_list = g_list_remove_link(pr->col_list, pr->col_list);
3493   }
3494   g_list_free(pr->col_list);
3495   pr->col_list = NULL;
3496 }