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