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