From Ryan Hoffman via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6122
[obnox/wireshark/wip.git] / disabled_protos.c
index bb3c68e840542ee98d2c29b7e7c9cab56665f424..fc6bfc2bc25c270fd9ed345fd8441ebbf25b84f8 100644 (file)
@@ -1,10 +1,10 @@
 /* disabled_protos.c
  * Code for reading and writing the disabled protocols file.
  *
- * $Id: disabled_protos.c,v 1.3 2003/11/16 23:17:15 guy Exp $
+ * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * This program is free software; you can redistribute it and/or
 #include <epan/proto.h>
 
 #include "disabled_protos.h"
+#include <wsutil/file_util.h>
 
-#define PROTOCOLS_FILE_NAME    "disabled_protos"
+#define GLOBAL_PROTOCOLS_FILE_NAME     "disabled_protos"
+#define PROTOCOLS_FILE_NAME            "disabled_protos"
 
 /*
  * List of disabled protocols
  */
+static GList *global_disabled_protos = NULL;
 static GList *disabled_protos = NULL;
 
 #define INIT_BUF_SIZE  128
 
+static void
+discard_existing_list (GList **flp)
+{
+  GList      *fl_ent;
+  protocol_def *prot;
+
+  if (*flp != NULL) {
+    fl_ent = g_list_first(*flp);
+    while (fl_ent != NULL) {
+      prot = (protocol_def *) fl_ent->data;
+      g_free(prot->name);
+      g_free(prot);
+      fl_ent = fl_ent->next;
+    }
+    g_list_free(*flp);
+    *flp = NULL;
+  }
+}
+
 /*
  * Read in a list of disabled protocols.
  *
@@ -61,77 +83,100 @@ static GList *disabled_protos = NULL;
  * or "*read_errno_return" is set to the error if a read failed.
  */
 
+static int read_disabled_protos_list_file(const char *ff_path, FILE *ff,
+                                         GList **flp);
+
 void
-read_disabled_protos_list(char **pref_path_return, int *open_errno_return,
+read_disabled_protos_list(char **gpath_return, int *gopen_errno_return,
+                         int *gread_errno_return,
+                         char **path_return, int *open_errno_return,
                           int *read_errno_return)
 {
-  char       *ff_path, *ff_name;
+  int         err;
+  char       *gff_path, *ff_path;
   FILE       *ff;
-  GList      **flp;
-  GList      *fl_ent;
-  protocol_def *prot;
-  int         c;
-  char       *prot_name;
-  int         prot_name_len;
-  int         prot_name_index;
-  int         line = 1;
 
-  *pref_path_return = NULL;    /* assume no error */
+  /* Construct the pathname of the global disabled protocols file. */
+  gff_path = get_datafile_path(GLOBAL_PROTOCOLS_FILE_NAME);
+
+  /* If we already have a list of protocols, discard it. */
+  discard_existing_list (&global_disabled_protos);
+
+  /* Read the global disabled protocols file, if it exists. */
+  *gpath_return = NULL;
+  if ((ff = ws_fopen(gff_path, "r")) != NULL) {
+    /* We succeeded in opening it; read it. */
+    err = read_disabled_protos_list_file(gff_path, ff,
+                                        &global_disabled_protos);
+    if (err != 0) {
+      /* We had an error reading the file; return the errno and the
+         pathname, so our caller can report the error. */
+      *gopen_errno_return = 0;
+      *gread_errno_return = err;
+      *gpath_return = gff_path;
+    } else
+      g_free(gff_path);
+    fclose(ff);
+  } else {
+    /* We failed to open it.  If we failed for some reason other than
+       "it doesn't exist", return the errno and the pathname, so our
+       caller can report the error. */
+    if (errno != ENOENT) {
+      *gopen_errno_return = errno;
+      *gread_errno_return = 0;
+      *gpath_return = gff_path;
+    } else
+      g_free(gff_path);
+  }
 
-  ff_name = PROTOCOLS_FILE_NAME;
-  flp = &disabled_protos;
+  /* Construct the pathname of the user's disabled protocols file. */
+  ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE, FALSE);
 
-  /* To do: generalize this */
-  ff_path = get_persconffile_path(ff_name, FALSE);
-  if ((ff = fopen(ff_path, "r")) == NULL) {
-    /*
-     * Did that fail because we the file didn't exist?
-     */
+  /* If we already have a list of protocols, discard it. */
+  discard_existing_list (&disabled_protos);
+
+  /* Read the user's disabled protocols file, if it exists. */
+  *path_return = NULL;
+  if ((ff = ws_fopen(ff_path, "r")) != NULL) {
+    /* We succeeded in opening it; read it. */
+    err = read_disabled_protos_list_file(ff_path, ff, &disabled_protos);
+    if (err != 0) {
+      /* We had an error reading the file; return the errno and the
+         pathname, so our caller can report the error. */
+      *open_errno_return = 0;
+      *read_errno_return = err;
+      *path_return = ff_path;
+    } else
+      g_free(ff_path);
+    fclose(ff);
+  } else {
+    /* We failed to open it.  If we failed for some reason other than
+       "it doesn't exist", return the errno and the pathname, so our
+       caller can report the error. */
     if (errno != ENOENT) {
-      /*
-       * No.  Just give up.
-       */
-      *pref_path_return = ff_path;
       *open_errno_return = errno;
       *read_errno_return = 0;
-      return;
-    }
-
-    /*
-     * Yes.  See if there's a "protocols" file; if so, read it.
-     */
-    g_free(ff_path);
-    ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, FALSE);
-    if ((ff = fopen(ff_path, "r")) == NULL) {
-      /*
-       * Well, that didn't work, either.  Just give up.
-       * Return an error if the file existed but we couldn't open it.
-       */
-      if (errno != ENOENT) {
-       *pref_path_return = ff_path;
-       *open_errno_return = errno;
-       *read_errno_return = 0;
-      }
-      return;
-    }
+      *path_return = ff_path;
+    } else
+      g_free(ff_path);
   }
+}
+
+static int
+read_disabled_protos_list_file(const char *ff_path, FILE *ff,
+                              GList **flp)
+{
+  protocol_def *prot;
+  int         c;
+  char       *prot_name;
+  int         prot_name_len;
+  int         prot_name_index;
+  int         line = 1;
 
-  /* If we already have a list of protocols, discard it. */
-  if (*flp != NULL) {
-    fl_ent = g_list_first(*flp);
-    while (fl_ent != NULL) {
-      prot = (protocol_def *) fl_ent->data;
-      g_free(prot->name);
-      g_free(prot);
-      fl_ent = fl_ent->next;
-    }
-    g_list_free(*flp);
-    *flp = NULL;
-  }
 
   /* Allocate the protocol name buffer. */
   prot_name_len = INIT_BUF_SIZE;
-  prot_name = g_malloc(prot_name_len + 1);
+  prot_name = (char *)g_malloc(prot_name_len + 1);
 
   for (line = 1; ; line++) {
     /* Lines in a disabled protocol file contain the "filter name" of
@@ -167,7 +212,7 @@ read_disabled_protos_list(char **pref_path_return, int *open_errno_return,
       if (prot_name_index >= prot_name_len) {
        /* protocol name buffer isn't long enough; double its length. */
        prot_name_len *= 2;
-       prot_name = g_realloc(prot_name, prot_name_len + 1);
+       prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
       }
       prot_name[prot_name_index] = c;
       prot_name_index++;
@@ -205,7 +250,7 @@ read_disabled_protos_list(char **pref_path_return, int *open_errno_return,
     if (prot_name_index >= prot_name_len) {
       /* protocol name buffer isn't long enough; double its length. */
       prot_name_len *= 2;
-      prot_name = g_realloc(prot_name, prot_name_len + 1);
+      prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
     }
     prot_name[prot_name_index] = '\0';
 
@@ -214,16 +259,11 @@ read_disabled_protos_list(char **pref_path_return, int *open_errno_return,
     prot->name   = g_strdup(prot_name);
     *flp = g_list_append(*flp, prot);
   }
-  g_free(ff_path);
-  fclose(ff);
   g_free(prot_name);
-  return;
+  return 0;
 
 error:
-  *pref_path_return = ff_path;
-  *open_errno_return = 0;
-  *read_errno_return = errno;
-  fclose(ff);
+  return errno;
 }
 
 /*
@@ -240,7 +280,7 @@ set_disabled_protos_list(void)
    * assume all protocols are enabled by default
    */
   if (disabled_protos == NULL)
-    return;    /* nothing to disable */
+    goto skip;
 
   fl_ent = g_list_first(disabled_protos);
 
@@ -248,10 +288,31 @@ set_disabled_protos_list(void)
     prot = (protocol_def *) fl_ent->data;
     i = proto_get_id_by_filter_name(prot->name);
     if (i == -1) {
-       /* XXX - complain here? */
+      /* XXX - complain here? */
+    } else {
+      if (proto_can_toggle_protocol(i))
+       proto_set_decoding(i, FALSE);
+    }
+
+    fl_ent = fl_ent->next;
+  }
+
+skip:
+  if (global_disabled_protos == NULL)
+    return;
+
+  fl_ent = g_list_first(global_disabled_protos);
+
+  while (fl_ent != NULL) {
+    prot = (protocol_def *) fl_ent->data;
+    i = proto_get_id_by_filter_name(prot->name);
+    if (i == -1) {
+      /* XXX - complain here? */
     } else {
-      if (proto_can_disable_protocol(i))
-        proto_set_decoding(i, FALSE);
+      if (proto_can_toggle_protocol(i)) {
+       proto_set_decoding(i, FALSE);
+       proto_set_cant_toggle(i);
+      }
     }
 
     fl_ent = fl_ent->next;
@@ -269,25 +330,22 @@ set_disabled_protos_list(void)
 void
 save_disabled_protos_list(char **pref_path_return, int *errno_return)
 {
-  gchar      *ff_path, *ff_path_new, *ff_name;
-  FILE       *ff;
-  gint        i;
-  protocol_t *protocol;
-  void       *cookie;
+  gchar       *ff_path, *ff_path_new;
+  FILE        *ff;
+  gint         i;
+  protocol_t  *protocol;
+  void        *cookie;
 
   *pref_path_return = NULL;    /* assume no error */
 
-  ff_name = PROTOCOLS_FILE_NAME;
-
-  ff_path = get_persconffile_path(ff_name, TRUE);
+  ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE, TRUE);
 
   /* Write to "XXX.new", and rename if that succeeds.
      That means we don't trash the file if we fail to write it out
      completely. */
-  ff_path_new = (gchar *) g_malloc(strlen(ff_path) + 5);
-  sprintf(ff_path_new, "%s.new", ff_path);
+  ff_path_new = g_strdup_printf("%s.new", ff_path);
 
-  if ((ff = fopen(ff_path_new, "w")) == NULL) {
+  if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
     *pref_path_return = ff_path;
     *errno_return = errno;
     g_free(ff_path_new);
@@ -299,7 +357,7 @@ save_disabled_protos_list(char **pref_path_return, int *errno_return)
   for (i = proto_get_first_protocol(&cookie); i != -1;
        i = proto_get_next_protocol(&cookie)) {
 
-    if (!proto_can_disable_protocol(i)) {
+    if (!proto_can_toggle_protocol(i)) {
       continue;
     }
 
@@ -315,32 +373,32 @@ save_disabled_protos_list(char **pref_path_return, int *errno_return)
   if (fclose(ff) == EOF) {
     *pref_path_return = ff_path;
     *errno_return = errno;
-    unlink(ff_path_new);
+    ws_unlink(ff_path_new);
     g_free(ff_path_new);
     return;
   }
 
-#ifdef WIN32
+#ifdef _WIN32
   /* ANSI C doesn't say whether "rename()" removes the target if it
      exists; the Win32 call to rename files doesn't do so, which I
      infer is the reason why the MSVC++ "rename()" doesn't do so.
      We must therefore remove the target file first, on Windows. */
-  if (remove(ff_path) < 0 && errno != ENOENT) {
+  if (ws_remove(ff_path) < 0 && errno != ENOENT) {
     /* It failed for some reason other than "it's not there"; if
        it's not there, we don't need to remove it, so we just
        drive on. */
     *pref_path_return = ff_path;
     *errno_return = errno;
-    unlink(ff_path_new);
+    ws_unlink(ff_path_new);
     g_free(ff_path_new);
     return;
   }
 #endif
 
-  if (rename(ff_path_new, ff_path) < 0) {
+  if (ws_rename(ff_path_new, ff_path) < 0) {
     *pref_path_return = ff_path;
     *errno_return = errno;
-    unlink(ff_path_new);
+    ws_unlink(ff_path_new);
     g_free(ff_path_new);
     return;
   }