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