MSWSP: parse_CColumnGroupArray() etc.
[wireshark-wip.git] / epan / disabled_protos.c
blob56b26226927c11d806fd6d510bb292f999322dbd
1 /* disabled_protos.c
2 * Code for reading and writing the disabled protocols file.
4 * $Id$
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "config.h"
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <errno.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
36 #include <glib.h>
38 #include <epan/filesystem.h>
39 #include <epan/proto.h>
41 #include "disabled_protos.h"
42 #include <wsutil/file_util.h>
44 #define GLOBAL_PROTOCOLS_FILE_NAME "disabled_protos"
45 #define PROTOCOLS_FILE_NAME "disabled_protos"
48 * List of disabled protocols
50 static GList *global_disabled_protos = NULL;
51 static GList *disabled_protos = NULL;
53 #define INIT_BUF_SIZE 128
55 static void
56 discard_existing_list (GList **flp)
58 GList *fl_ent;
59 protocol_def *prot;
61 if (*flp != NULL) {
62 fl_ent = g_list_first(*flp);
63 while (fl_ent != NULL) {
64 prot = (protocol_def *) fl_ent->data;
65 g_free(prot->name);
66 g_free(prot);
67 fl_ent = fl_ent->next;
69 g_list_free(*flp);
70 *flp = NULL;
75 * Read in a list of disabled protocols.
77 * On success, "*pref_path_return" is set to NULL.
78 * On error, "*pref_path_return" is set to point to the pathname of
79 * the file we tried to read - it should be freed by our caller -
80 * and "*open_errno_return" is set to the error if an open failed
81 * or "*read_errno_return" is set to the error if a read failed.
84 static int read_disabled_protos_list_file(const char *ff_path, FILE *ff,
85 GList **flp);
87 void
88 read_disabled_protos_list(char **gpath_return, int *gopen_errno_return,
89 int *gread_errno_return,
90 char **path_return, int *open_errno_return,
91 int *read_errno_return)
93 int err;
94 char *gff_path, *ff_path;
95 FILE *ff;
97 /* Construct the pathname of the global disabled protocols file. */
98 gff_path = get_datafile_path(GLOBAL_PROTOCOLS_FILE_NAME);
100 /* If we already have a list of protocols, discard it. */
101 discard_existing_list (&global_disabled_protos);
103 /* Read the global disabled protocols file, if it exists. */
104 *gpath_return = NULL;
105 if ((ff = ws_fopen(gff_path, "r")) != NULL) {
106 /* We succeeded in opening it; read it. */
107 err = read_disabled_protos_list_file(gff_path, ff,
108 &global_disabled_protos);
109 if (err != 0) {
110 /* We had an error reading the file; return the errno and the
111 pathname, so our caller can report the error. */
112 *gopen_errno_return = 0;
113 *gread_errno_return = err;
114 *gpath_return = gff_path;
115 } else
116 g_free(gff_path);
117 fclose(ff);
118 } else {
119 /* We failed to open it. If we failed for some reason other than
120 "it doesn't exist", return the errno and the pathname, so our
121 caller can report the error. */
122 if (errno != ENOENT) {
123 *gopen_errno_return = errno;
124 *gread_errno_return = 0;
125 *gpath_return = gff_path;
126 } else
127 g_free(gff_path);
130 /* Construct the pathname of the user's disabled protocols file. */
131 ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE);
133 /* If we already have a list of protocols, discard it. */
134 discard_existing_list (&disabled_protos);
136 /* Read the user's disabled protocols file, if it exists. */
137 *path_return = NULL;
138 if ((ff = ws_fopen(ff_path, "r")) != NULL) {
139 /* We succeeded in opening it; read it. */
140 err = read_disabled_protos_list_file(ff_path, ff, &disabled_protos);
141 if (err != 0) {
142 /* We had an error reading the file; return the errno and the
143 pathname, so our caller can report the error. */
144 *open_errno_return = 0;
145 *read_errno_return = err;
146 *path_return = ff_path;
147 } else
148 g_free(ff_path);
149 fclose(ff);
150 } else {
151 /* We failed to open it. If we failed for some reason other than
152 "it doesn't exist", return the errno and the pathname, so our
153 caller can report the error. */
154 if (errno != ENOENT) {
155 *open_errno_return = errno;
156 *read_errno_return = 0;
157 *path_return = ff_path;
158 } else
159 g_free(ff_path);
163 static int
164 read_disabled_protos_list_file(const char *ff_path, FILE *ff,
165 GList **flp)
167 protocol_def *prot;
168 int c;
169 char *prot_name;
170 int prot_name_len;
171 int prot_name_index;
172 int line = 1;
175 /* Allocate the protocol name buffer. */
176 prot_name_len = INIT_BUF_SIZE;
177 prot_name = (char *)g_malloc(prot_name_len + 1);
179 for (line = 1; ; line++) {
180 /* Lines in a disabled protocol file contain the "filter name" of
181 a protocol to be disabled. */
183 /* Skip over leading white space, if any. */
184 while ((c = getc(ff)) != EOF && isspace(c)) {
185 if (c == '\n') {
186 /* Blank line. */
187 continue;
191 if (c == EOF) {
192 if (ferror(ff))
193 goto error; /* I/O error */
194 else
195 break; /* Nothing more to read */
197 ungetc(c, ff); /* Unread the non-white-space character. */
199 /* Get the name of the protocol. */
200 prot_name_index = 0;
201 for (;;) {
202 c = getc(ff);
203 if (c == EOF)
204 break; /* End of file, or I/O error */
205 if (isspace(c))
206 break; /* Trailing white space, or end of line. */
207 if (c == '#')
208 break; /* Start of comment, running to end of line. */
209 /* Add this character to the protocol name string. */
210 if (prot_name_index >= prot_name_len) {
211 /* protocol name buffer isn't long enough; double its length. */
212 prot_name_len *= 2;
213 prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
215 prot_name[prot_name_index] = c;
216 prot_name_index++;
219 if (isspace(c) && c != '\n') {
220 /* Skip over trailing white space. */
221 while ((c = getc(ff)) != EOF && c != '\n' && isspace(c))
223 if (c != EOF && c != '\n' && c != '#') {
224 /* Non-white-space after the protocol name; warn about it,
225 in case we come up with a reason to use it. */
226 g_warning("'%s' line %d has extra stuff after the protocol name.",
227 ff_path, line);
230 if (c != EOF && c != '\n') {
231 /* Skip to end of line. */
232 while ((c = getc(ff)) != EOF && c != '\n')
236 if (c == EOF) {
237 if (ferror(ff))
238 goto error; /* I/O error */
239 else {
240 /* EOF, not error; no newline seen before EOF */
241 g_warning("'%s' line %d doesn't have a newline.", ff_path,
242 line);
244 break; /* nothing more to read */
247 /* Null-terminate the protocol name. */
248 if (prot_name_index >= prot_name_len) {
249 /* protocol name buffer isn't long enough; double its length. */
250 prot_name_len *= 2;
251 prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
253 prot_name[prot_name_index] = '\0';
255 /* Add the new protocol to the list of disabled protocols */
256 prot = (protocol_def *) g_malloc(sizeof(protocol_def));
257 prot->name = g_strdup(prot_name);
258 *flp = g_list_append(*flp, prot);
260 g_free(prot_name);
261 return 0;
263 error:
264 return errno;
268 * Disable protocols as per the stored configuration
270 void
271 set_disabled_protos_list(void)
273 gint i;
274 GList *fl_ent;
275 protocol_def *prot;
278 * assume all protocols are enabled by default
280 if (disabled_protos == NULL)
281 goto skip;
283 fl_ent = g_list_first(disabled_protos);
285 while (fl_ent != NULL) {
286 prot = (protocol_def *) fl_ent->data;
287 i = proto_get_id_by_filter_name(prot->name);
288 if (i == -1) {
289 /* XXX - complain here? */
290 } else {
291 if (proto_can_toggle_protocol(i))
292 proto_set_decoding(i, FALSE);
295 fl_ent = fl_ent->next;
298 skip:
299 if (global_disabled_protos == NULL)
300 return;
302 fl_ent = g_list_first(global_disabled_protos);
304 while (fl_ent != NULL) {
305 prot = (protocol_def *) fl_ent->data;
306 i = proto_get_id_by_filter_name(prot->name);
307 if (i == -1) {
308 /* XXX - complain here? */
309 } else {
310 if (proto_can_toggle_protocol(i)) {
311 proto_set_decoding(i, FALSE);
312 proto_set_cant_toggle(i);
316 fl_ent = fl_ent->next;
321 * Write out a list of disabled protocols.
323 * On success, "*pref_path_return" is set to NULL.
324 * On error, "*pref_path_return" is set to point to the pathname of
325 * the file we tried to read - it should be freed by our caller -
326 * and "*errno_return" is set to the error.
328 void
329 save_disabled_protos_list(char **pref_path_return, int *errno_return)
331 gchar *ff_path, *ff_path_new;
332 FILE *ff;
333 gint i;
334 protocol_t *protocol;
335 void *cookie;
337 *pref_path_return = NULL; /* assume no error */
339 ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE);
341 /* Write to "XXX.new", and rename if that succeeds.
342 That means we don't trash the file if we fail to write it out
343 completely. */
344 ff_path_new = g_strdup_printf("%s.new", ff_path);
346 if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
347 *pref_path_return = ff_path;
348 *errno_return = errno;
349 g_free(ff_path_new);
350 return;
353 /* Iterate over all the protocols */
355 for (i = proto_get_first_protocol(&cookie); i != -1;
356 i = proto_get_next_protocol(&cookie)) {
358 if (!proto_can_toggle_protocol(i)) {
359 continue;
362 protocol = find_protocol_by_id(i);
363 if (proto_is_protocol_enabled(protocol)) {
364 continue;
367 /* Write out the protocol name. */
368 fprintf(ff, "%s\n", proto_get_protocol_filter_name(i));
371 if (fclose(ff) == EOF) {
372 *pref_path_return = ff_path;
373 *errno_return = errno;
374 ws_unlink(ff_path_new);
375 g_free(ff_path_new);
376 return;
379 #ifdef _WIN32
380 /* ANSI C doesn't say whether "rename()" removes the target if it
381 exists; the Win32 call to rename files doesn't do so, which I
382 infer is the reason why the MSVC++ "rename()" doesn't do so.
383 We must therefore remove the target file first, on Windows.
385 XXX - ws_rename() should be ws_stdio_rename() on Windows,
386 and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
387 so it should remove the target if it exists, so this stuff
388 shouldn't be necessary. Perhaps it dates back to when we were
389 calling rename(), with that being a wrapper around Microsoft's
390 _rename(), which didn't remove the target. */
391 if (ws_remove(ff_path) < 0 && errno != ENOENT) {
392 /* It failed for some reason other than "it's not there"; if
393 it's not there, we don't need to remove it, so we just
394 drive on. */
395 *pref_path_return = ff_path;
396 *errno_return = errno;
397 ws_unlink(ff_path_new);
398 g_free(ff_path_new);
399 return;
401 #endif
403 if (ws_rename(ff_path_new, ff_path) < 0) {
404 *pref_path_return = ff_path;
405 *errno_return = errno;
406 ws_unlink(ff_path_new);
407 g_free(ff_path_new);
408 return;
410 g_free(ff_path_new);
411 g_free(ff_path);