It's not only executable but a script as well: propset eol-style + keywords
[obnox/wireshark/wip.git] / capture_opts.c
index 08f023e70561948bf2c8e798ee167927c6c23e64..ed7339c845d065cb5e27ceac3823d0ecec098ca9 100644 (file)
@@ -3,8 +3,8 @@
  *
  * $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
@@ -31,8 +31,6 @@
 #include <string.h>
 #include <ctype.h>
 
-#include <pcap.h>
-
 #include <glib.h>
 
 #include <epan/packet.h>
 #include "cmdarg_err.h"
 
 #include "capture-pcap-util.h"
-#include "capture_ui_utils.h"
 #include <wiretap/file_util.h>
 
 
-static gboolean capture_opts_output_to_pipe(const char *save_file);
+static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_pipe);
 
 
 void
 capture_opts_init(capture_options *capture_opts, void *cfile)
 {
   capture_opts->cf                      = cfile;            
-  capture_opts->cfilter                            = g_strdup("");     /* No capture filter string specified */
+  capture_opts->cfilter                 = g_strdup("");     /* No capture filter string specified */
   capture_opts->iface                   = NULL;             /* Default is "pick the first interface" */
 #ifdef _WIN32
   capture_opts->buffer_size             = 1;                /* 1 MB */
 #endif
   capture_opts->has_snaplen             = FALSE;
   capture_opts->snaplen                 = WTAP_MAX_PACKET_SIZE; /* snapshot length - default is
-                                                                    infinite, in effect */
+                                                                   infinite, in effect */
   capture_opts->promisc_mode            = TRUE;             /* promiscuous mode is the default */
   capture_opts->linktype                = -1;               /* the default linktype */
+  capture_opts->saving_to_file          = FALSE;
   capture_opts->save_file               = NULL;
   capture_opts->real_time_mode          = TRUE;
   capture_opts->show_info               = TRUE;
@@ -89,7 +87,7 @@ capture_opts_init(capture_options *capture_opts, void *cfile)
 
   capture_opts->fork_child              = -1;               /* invalid process handle */
 #ifdef _WIN32
-  capture_opts->signal_pipe_fd          = -1;
+  capture_opts->signal_pipe_write_fd    = -1;
 #endif
   capture_opts->state                   = CAPTURE_STOPPED;
   capture_opts->output_to_pipe          = FALSE;
@@ -109,6 +107,7 @@ capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_optio
     g_log(log_domain, log_level, "SnapLen         (%u): %u", capture_opts->has_snaplen, capture_opts->snaplen);
     g_log(log_domain, log_level, "Promisc            : %u", capture_opts->promisc_mode);
     g_log(log_domain, log_level, "LinkType           : %d", capture_opts->linktype);
+    g_log(log_domain, log_level, "SavingToFile       : %u", capture_opts->saving_to_file);
     g_log(log_domain, log_level, "SaveFile           : %s", (capture_opts->save_file) ? capture_opts->save_file : "");
     g_log(log_domain, log_level, "RealTimeMode       : %u", capture_opts->real_time_mode);
     g_log(log_domain, log_level, "ShowInfo           : %u", capture_opts->show_info);
@@ -125,7 +124,7 @@ capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_optio
 
     g_log(log_domain, log_level, "ForkChild          : %d", capture_opts->fork_child);
 #ifdef _WIN32
-    g_log(log_domain, log_level, "SignalPipeFd       : %d", capture_opts->signal_pipe_fd);
+    g_log(log_domain, log_level, "SignalPipeWrite    : %d", capture_opts->signal_pipe_write_fd);
 #endif
 }
 
@@ -193,7 +192,7 @@ get_ring_arguments(capture_options *capture_opts, const char *arg)
 
   colonp = strchr(arg, ':');
   if (colonp == NULL)
-    return TRUE;
+    return FALSE;
 
   p = colonp;
   *p++ = '\0';
@@ -226,73 +225,12 @@ get_ring_arguments(capture_options *capture_opts, const char *arg)
     capture_opts->file_duration = get_positive_int(p, "ring buffer duration");
   }
 
-  *colonp = ':';       /* put the colon back */
+  *colonp = ':';    /* put the colon back */
   return TRUE;
 }
 
 
-#ifdef _WIN32
-/*
- * Given a string of the form "<pipe name>:<file descriptor>", as might appear
- * as an argument to a "-Z" option, parse it and set the arguments in
- * question.  Return an indication of whether it succeeded or failed
- * in some fashion.
- */
-static gboolean
-get_pipe_arguments(capture_options *capture_opts, const char *arg)
-{
-  gchar *p = NULL, *colonp;
-  int pipe_fd;
-
-
-  colonp = strchr(arg, ':');
-  if (colonp == NULL)
-    return TRUE;
-
-  p = colonp;
-  *p++ = '\0';
-
-  /*
-   * Skip over any white space (there probably won't be any, but
-   * as we allow it in the preferences file, we might as well
-   * allow it here).
-   */
-  while (isspace((guchar)*p))
-    p++;
-  if (*p == '\0') {
-    /*
-     * Put the colon back, so if our caller uses, in an
-     * error message, the string they passed us, the message
-     * looks correct.
-     */
-    *colonp = ':';
-    return FALSE;
-  }
-
-  if (strcmp(arg,"sync") == 0) {
-    /* associate stdout with sync pipe */
-    pipe_fd = get_natural_int(p, "sync pipe file descriptor");
-    if (dup2(pipe_fd, 1) < 0) {
-      cmdarg_err("Unable to dup sync pipe handle");
-      return FALSE;
-    }
-  } else if (strcmp(arg,"signal") == 0) {
-    /* associate stdin with signal pipe */
-    pipe_fd = get_natural_int(p, "signal pipe file descriptor");
-    if (dup2(pipe_fd, 0) < 0) {
-      cmdarg_err("Unable to dup signal pipe handle");
-      return FALSE;
-    }
-    capture_opts->signal_pipe_fd = pipe_fd;
-  }
-
-  *colonp = ':';       /* put the colon back */
-  return TRUE;
-}
-#endif
-
-
-void
+static int
 capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg)
 {
     long        adapter_index;
@@ -300,13 +238,13 @@ capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg)
     GList       *if_list;
     if_info_t   *if_info;
     int         err;
-    gchar       err_str[PCAP_ERRBUF_SIZE];
+    gchar       err_str[CAPTURE_PCAP_ERRBUF_SIZE];
     gchar       *cant_get_if_list_errstr;
 
 
     /*
      * If the argument is a number, treat it as an index into the list
-     * of adapters, as printed by "tethereal -D".
+     * of adapters, as printed by "tshark -D".
      *
      * This should be OK on UNIX systems, as interfaces shouldn't have
      * names that begin with digits.  It can be useful on Windows, where
@@ -316,16 +254,16 @@ capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg)
     if (p != NULL && *p == '\0') {
       if (adapter_index < 0) {
         cmdarg_err("The specified adapter index is a negative number");
-       exit(1);
+        return 1;
       }
       if (adapter_index > INT_MAX) {
         cmdarg_err("The specified adapter index is too large (greater than %d)",
             INT_MAX);
-        exit(1);
+        return 1;
       }
       if (adapter_index == 0) {
         cmdarg_err("there is no interface with that adapter index");
-        exit(1);
+        return 1;
       }
       if_list = get_interface_list(&err, err_str);
       if (if_list == NULL) {
@@ -342,35 +280,39 @@ capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg)
             cmdarg_err("There are no interfaces on which a capture can be done");
             break;
         }
-        exit(2);
+        return 2;
       }
       if_info = g_list_nth_data(if_list, adapter_index - 1);
       if (if_info == NULL) {
         cmdarg_err("there is no interface with that adapter index");
-        exit(1);
+        return 1;
       }
       capture_opts->iface = g_strdup(if_info->name);
       free_interface_list(if_list);
     } else {
       capture_opts->iface = g_strdup(optarg);
     }
+
+    return 0;
 }
 
-void
+int
 capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg, gboolean *start_capture)
 {
+    int status;
+
     switch(opt) {
     case 'a':        /* autostop criteria */
         if (set_autostop_criterion(capture_opts, optarg) == FALSE) {
           cmdarg_err("Invalid or unknown -a flag \"%s\"", optarg);
-          exit(1);
+          return 1;
         }
         break;
     case 'b':        /* Ringbuffer option */
         capture_opts->multi_files_on = TRUE;
         if (get_ring_arguments(capture_opts, optarg) == FALSE) {
           cmdarg_err("Invalid or unknown -b arg \"%s\"", optarg);
-          exit(1);
+          return 1;
         }
         break;
 #ifdef _WIN32
@@ -378,7 +320,7 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg,
         capture_opts->buffer_size = get_positive_int(optarg, "buffer size");
         break;
 #endif
-    case 'c':        /* Capture xxx packets */
+    case 'c':        /* Capture n packets */
         capture_opts->has_autostop_packets = TRUE;
         capture_opts->autostop_packets = get_positive_int(optarg, "packet count");
         break;
@@ -390,8 +332,11 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg,
     case 'H':        /* Hide capture info dialog box */
         capture_opts->show_info = FALSE;
         break;
-    case 'i':        /* Use interface xxx */
-        capture_opts_add_iface_opt(capture_opts, optarg);
+    case 'i':        /* Use interface x */
+        status = capture_opts_add_iface_opt(capture_opts, optarg);
+        if(status != 0) {
+            return status;
+        }
         break;
     case 'k':        /* Start capture immediately */
         *start_capture = TRUE;
@@ -411,47 +356,42 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg,
     case 'S':        /* "Real-Time" mode: used for following file ala tail -f */
         capture_opts->real_time_mode = TRUE;
         break;
-    case 'w':        /* Write to capture file xxx */
+    case 'w':        /* Write to capture file x */
+        capture_opts->saving_to_file = TRUE;
 #if defined _WIN32 && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
         /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
         capture_opts->save_file = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
 #else
         capture_opts->save_file = g_strdup(optarg);
 #endif
-        capture_opts->output_to_pipe = capture_opts_output_to_pipe(capture_opts->save_file);
-           break;
+        status = capture_opts_output_to_pipe(capture_opts->save_file, &capture_opts->output_to_pipe);
+        return status;
+        break;
     case 'y':        /* Set the pcap data link type */
 #ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL
-        capture_opts->linktype = pcap_datalink_name_to_val(optarg);
+        capture_opts->linktype = linktype_name_to_val(optarg);
         if (capture_opts->linktype == -1) {
           cmdarg_err("The specified data link type \"%s\" isn't valid",
                   optarg);
-          exit(1);
+          return 1;
         }
 #else /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
-        /* XXX - just treat it as a number */
+        /* we can't get the type name, just treat it as a number */
         capture_opts->linktype = get_natural_int(optarg, "data link type");
 #endif /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
         break;
-#ifdef _WIN32
-      /* Hidden option supporting Sync mode */
-    case 'Z':        /* Write to pipe FD XXX */
-       if (get_pipe_arguments(capture_opts, optarg) == FALSE) {
-          cmdarg_err("Invalid or unknown -Z flag \"%s\"", optarg);
-          exit(1);
-        }
-        break;
-#endif /* _WIN32 */
     default:
         /* the caller is responsible to send us only the right opt's */
         g_assert_not_reached();
     }
+
+    return 0;
 }
 
 
-void capture_opts_list_link_layer_types(capture_options *capture_opts)
+int capture_opts_list_link_layer_types(capture_options *capture_opts)
 {
-    gchar err_str[PCAP_ERRBUF_SIZE];
+    gchar err_str[CAPTURE_PCAP_ERRBUF_SIZE];
     GList *lt_list, *lt_entry;
     data_link_info_t *data_link_info;
 
@@ -459,12 +399,12 @@ void capture_opts_list_link_layer_types(capture_options *capture_opts)
     lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
     if (lt_list == NULL) {
       if (err_str[0] != '\0') {
-       cmdarg_err("The list of data link types for the capture device could not be obtained (%s)."
-         "Please check to make sure you have sufficient permissions, and that\n"
-         "you have the proper interface or pipe specified.\n", err_str);
+        cmdarg_err("The list of data link types for the capture device \"%s\" could not be obtained (%s)."
+         "Please check to make sure you have sufficient permissions, and that\n"
+         "you have the proper interface or pipe specified.\n", capture_opts->iface, err_str);
       } else
-       cmdarg_err("The capture device has no data link types.");
-      exit(2);
+        cmdarg_err("The capture device \"%s\" has no data link types.", capture_opts->iface);
+      return 2;
     }
     cmdarg_err_cont("Data link types (use option -y to set):");
     for (lt_entry = lt_list; lt_entry != NULL;
@@ -472,24 +412,31 @@ void capture_opts_list_link_layer_types(capture_options *capture_opts)
       data_link_info = lt_entry->data;
       cmdarg_err_cont("  %s", data_link_info->name);
       if (data_link_info->description != NULL)
-       cmdarg_err_cont(" (%s)", data_link_info->description);
+        cmdarg_err_cont(" (%s)", data_link_info->description);
       else
-       cmdarg_err_cont(" (not supported)");
+        cmdarg_err_cont(" (not supported)");
       putchar('\n');
     }
     free_pcap_linktype_list(lt_list);
+
+    return 0;
 }
 
 
-void capture_opts_list_interfaces()
+int capture_opts_list_interfaces()
 {
     GList       *if_list;
     GList       *if_entry;
     if_info_t   *if_info;
     int         err;
-    gchar       err_str[PCAP_ERRBUF_SIZE];
+    gchar       err_str[CAPTURE_PCAP_ERRBUF_SIZE];
     gchar       *cant_get_if_list_errstr;
     int         i;
+#if 0
+    GSList      *ip_addr;
+    if_addr_t   *if_addr;
+    guint8      ipv4[4];
+#endif
 
 
     if_list = get_interface_list(&err, err_str);
@@ -505,7 +452,7 @@ void capture_opts_list_interfaces()
             cmdarg_err("There are no interfaces on which a capture can be done");
         break;
         }
-        exit(2);
+        return 2;
     }
 
     i = 1;  /* Interface id number */
@@ -515,9 +462,30 @@ void capture_opts_list_interfaces()
         printf("%d. %s", i++, if_info->name);
         if (if_info->description != NULL)
             printf(" (%s)", if_info->description);
+#if 0
+        for(ip_addr = g_slist_nth(if_info->ip_addr, 0); ip_addr != NULL;
+        ip_addr = g_slist_next(ip_addr)) {
+            if_addr = ip_addr->data;
+            switch(if_addr->type) {
+            case AT_IPv4:
+                memcpy(ipv4, (void *) &if_addr->ip_addr.ip4_addr, 4);
+                printf(" %u.%u.%u.%u", ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
+                break;
+            case AT_IPv6:
+                /* XXX - display the IPv6 address without using stuff from epan */
+                printf(" XXX-IPv6");
+                break;
+            default:
+                printf(" unknown address type %u", if_addr->type);
+            }
+        }
+#endif
+
         printf("\n");
     }
     free_interface_list(if_list);
+
+    return 0;
 }
 
 
@@ -547,7 +515,7 @@ gboolean capture_opts_trim_iface(capture_options *capture_opts, const char *capt
     GList       *if_list;
     if_info_t   *if_info;
     int         err;
-    gchar       err_str[PCAP_ERRBUF_SIZE];
+    gchar       err_str[CAPTURE_PCAP_ERRBUF_SIZE];
     gchar       *cant_get_if_list_errstr;
 
 
@@ -607,7 +575,7 @@ static int capture_opts_test_for_fifo(const char *path)
                return 0;
 }
 
-static gboolean capture_opts_output_to_pipe(const char *save_file)
+static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_pipe)
 {
   int err;
 
@@ -619,7 +587,7 @@ static gboolean capture_opts_output_to_pipe(const char *save_file)
          silly to do "-w - >output_file" rather than "-w output_file",
          but by not checking we might be violating the Principle Of
          Least Astonishment. */
-      return TRUE;
+      *is_pipe = TRUE;
     } else {
       /* not a capture file, test for a FIFO (aka named pipe) */
       err = capture_opts_test_for_fifo(save_file);
@@ -631,18 +599,20 @@ static gboolean capture_opts_output_to_pipe(const char *save_file)
         break;
 
       case ESPIPE:     /* it is a FIFO */
-        return TRUE;
+        *is_pipe = TRUE;
         break;
 
       default:         /* couldn't stat it */
         cmdarg_err("Error testing whether capture file is a pipe: %s",
                 strerror(errno));
-        exit(2);
+        return 2;
       }
     }
   }
 
-  return FALSE;
+  *is_pipe = FALSE;
+
+  return 0;
 }
 
 #endif /* HAVE_LIBPCAP */