summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2012-12-08 02:42:40 +0000
committerMichael Mann <mmann78@netscape.net>2012-12-08 02:42:40 +0000
commit40eca5f0de867c1f7089152a028fe6006aa8bd5c (patch)
tree4f0a31b68d64815adec117b5e40626935c430a1b
parent2ff0d7870aeb66abc5cf2905cb1125bad93b9144 (diff)
downloadwireshark-40eca5f0de867c1f7089152a028fe6006aa8bd5c.tar.gz
Allow TShark to specify columns as fields with -e option (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=2892)
svn path=/trunk/; revision=46465
-rw-r--r--docbook/wsug_src/WSUG_app_tools.xml2
-rw-r--r--print.c72
-rw-r--r--print.h3
-rw-r--r--tshark.c26
4 files changed, 70 insertions, 33 deletions
diff --git a/docbook/wsug_src/WSUG_app_tools.xml b/docbook/wsug_src/WSUG_app_tools.xml
index 6a1a793077..ad6a213456 100644
--- a/docbook/wsug_src/WSUG_app_tools.xml
+++ b/docbook/wsug_src/WSUG_app_tools.xml
@@ -81,7 +81,7 @@ Output:
-x add output of hex and ASCII dump (Packet Bytes)
-T pdml|ps|psml|text|fields
format of text output (def: text)
- -e &lt;field&gt; field to print if -Tfields selected (e.g. tcp.port);
+ -e &lt;field&gt; field to print if -Tfields selected (e.g. tcp.port, col.Info);
this option can be repeated to print multiple fields
-E&lt;fieldsoption&gt;=&lt;value&gt; set options for output when -Tfields selected:
header=y|n switch headers on and off
diff --git a/print.c b/print.c
index 438b0ab1e4..5fd989acb7 100644
--- a/print.c
+++ b/print.c
@@ -84,6 +84,7 @@ struct _output_fields {
GHashTable* field_indicies;
emem_strbuf_t** field_values;
gchar quote;
+ gboolean includes_col_fields;
};
GHashTable *output_only_tables = NULL;
@@ -1328,6 +1329,7 @@ output_fields_t* output_fields_new(void)
fields->field_indicies = NULL;
fields->field_values = NULL;
fields->quote='\0';
+ fields->includes_col_fields = FALSE;
return fields;
}
@@ -1364,6 +1366,8 @@ void output_fields_free(output_fields_t* fields)
g_free(fields);
}
+#define COLUMN_FIELD_FILTER "col."
+
void output_fields_add(output_fields_t* fields, const gchar* field)
{
gchar* field_copy;
@@ -1379,6 +1383,11 @@ void output_fields_add(output_fields_t* fields, const gchar* field)
field_copy = g_strdup(field);
g_ptr_array_add(fields->fields, field_copy);
+
+ /* See if we have a column as a field entry */
+ if (!strncmp(field, COLUMN_FIELD_FILTER, strlen(COLUMN_FIELD_FILTER)))
+ fields->includes_col_fields = TRUE;
+
}
gboolean output_fields_set_option(output_fields_t* info, gchar* option)
@@ -1499,6 +1508,11 @@ void output_fields_list_options(FILE *fh)
fputs("quote=d|s|n Print either d: double-quotes, s: single quotes or \n n: no quotes around field values (def: n: none)\n", fh);
}
+gboolean output_fields_has_cols(output_fields_t* fields)
+{
+ g_assert(fields);
+ return fields->includes_col_fields;
+}
void write_fields_preamble(output_fields_t* fields, FILE *fh)
{
@@ -1521,6 +1535,25 @@ void write_fields_preamble(output_fields_t* fields, FILE *fh)
fputc('\n', fh);
}
+static void format_field_values(output_fields_t* fields, gpointer field_index, const gchar* value)
+{
+ if(NULL != value && '\0' != *value) {
+ guint actual_index;
+ actual_index = GPOINTER_TO_UINT(field_index);
+ /* Unwrap change made to disambiguiate zero / null */
+ if (fields->field_values[actual_index - 1] == NULL ) {
+ fields->field_values[actual_index - 1] = ep_strbuf_new(value);
+ } else if (fields->occurrence == 'l' ) {
+ /* print only the value of the last occurrence of the field */
+ ep_strbuf_printf(fields->field_values[actual_index - 1],"%s",value);
+ } else if (fields->occurrence == 'a' ) {
+ /* print the value of all accurrences of the field */
+ ep_strbuf_append_printf(fields->field_values[actual_index - 1],
+ "%c%s",fields->aggregator,value);
+ }
+ }
+}
+
static void proto_tree_get_node_field_values(proto_node *node, gpointer data)
{
write_field_data_t *call_data;
@@ -1535,25 +1568,9 @@ static void proto_tree_get_node_field_values(proto_node *node, gpointer data)
field_index = g_hash_table_lookup(call_data->fields->field_indicies, fi->hfinfo->abbrev);
if(NULL != field_index) {
- const gchar* value;
-
- value = get_node_field_value(fi, call_data->edt); /* ep_alloced string */
-
- if(NULL != value && '\0' != *value) {
- guint actual_index;
- actual_index = GPOINTER_TO_UINT(field_index);
- /* Unwrap change made to disambiguiate zero / null */
- if ( call_data->fields->field_values[actual_index - 1] == NULL ) {
- call_data->fields->field_values[actual_index - 1] = ep_strbuf_new(value);
- } else if ( call_data->fields->occurrence == 'l' ) {
- /* print only the value of the last occurrence of the field */
- ep_strbuf_printf(call_data->fields->field_values[actual_index - 1],"%s",value);
- } else if ( call_data->fields->occurrence == 'a' ) {
- /* print the value of all accurrences of the field */
- ep_strbuf_append_printf(call_data->fields->field_values[actual_index - 1],
- "%c%s",call_data->fields->aggregator,value);
- }
- }
+ format_field_values(call_data->fields, field_index,
+ get_node_field_value(fi, call_data->edt) /* ep_alloced string */
+ );
}
/* Recurse here. */
@@ -1563,9 +1580,12 @@ static void proto_tree_get_node_field_values(proto_node *node, gpointer data)
}
}
-void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, FILE *fh)
+void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, column_info *cinfo, FILE *fh)
{
gsize i;
+ gint col;
+ gchar* col_name;
+ gpointer field_index;
write_field_data_t data;
@@ -1597,6 +1617,18 @@ void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, FILE
proto_tree_children_foreach(edt->tree, proto_tree_get_node_field_values,
&data);
+ if (fields->includes_col_fields) {
+ for (col = 0; col < cinfo->num_cols; col++) {
+ /* Prepend COLUMN_FIELD_FILTER as the field name */
+ col_name = ep_strdup_printf("%s%s", COLUMN_FIELD_FILTER, cinfo->col_title[col]);
+ field_index = g_hash_table_lookup(fields->field_indicies, col_name);
+
+ if(NULL != field_index) {
+ format_field_values(fields, field_index, cinfo->col_data[col]);
+ }
+ }
+ }
+
for(i = 0; i < fields->fields->len; ++i) {
if(0 != i) {
fputc(fields->separator, fh);
diff --git a/print.h b/print.h
index fdb855eccc..dd86882521 100644
--- a/print.h
+++ b/print.h
@@ -123,6 +123,7 @@ extern void output_fields_add(output_fields_t* info, const gchar* field);
extern gsize output_fields_num_fields(output_fields_t* info);
extern gboolean output_fields_set_option(output_fields_t* info, gchar* option);
extern void output_fields_list_options(FILE *fh);
+extern gboolean output_fields_has_cols(output_fields_t* info);
/*
* Output only these protocols
@@ -154,7 +155,7 @@ extern void proto_tree_write_carrays(guint32 num, FILE *fh, epan_dissect_t *edt)
extern void write_carrays_finale(FILE *fh);
extern void write_fields_preamble(output_fields_t* fields, FILE *fh);
-extern void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, FILE *fh);
+extern void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, column_info *cinfo, FILE *fh);
extern void write_fields_finale(output_fields_t* fields, FILE *fh);
extern const gchar* get_node_field_value(field_info* fi, epan_dissect_t* edt);
diff --git a/tshark.c b/tshark.c
index b25badcf5a..84f2f14f1c 100644
--- a/tshark.c
+++ b/tshark.c
@@ -142,7 +142,7 @@ static char *separator = "";
/*
* TRUE if we're to print packet counts to keep track of captured packets.
*/
-static gboolean print_packet_counts;
+static gboolean print_packet_counts = TRUE;
static capture_options global_capture_opts;
@@ -307,7 +307,7 @@ print_usage(gboolean print_ver)
fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n");
fprintf(output, " -T pdml|ps|psml|text|fields\n");
fprintf(output, " format of text output (def: text)\n");
- fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port);\n");
+ fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port, col.Info);\n");
fprintf(output, " this option can be repeated to print multiple fields\n");
fprintf(output, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
fprintf(output, " header=y|n switch headers on and off\n");
@@ -3148,8 +3148,10 @@ process_packet(capture_file *cf, gint64 offset, struct wtap_pkthdr *whdr,
1) some tap needs the columns
or
2) we're printing packet info but we're *not* verbose; in verbose
- mode, we print the protocol tree, not the protocol summary. */
- if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary))
+ mode, we print the protocol tree, not the protocol summary.
+ or
+ 3) there is a column mapped as an individual field */
+ if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields))
cinfo = &cf->cinfo;
else
cinfo = NULL;
@@ -3503,24 +3505,26 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
{
print_args_t print_args;
- if (print_summary) {
+ if (print_summary || output_fields_has_cols(output_fields)) {
/* Just fill in the columns. */
epan_dissect_fill_in_columns(edt, FALSE, TRUE);
- /* Now print them. */
- switch (output_action) {
+ if (print_summary) {
+ /* Now print them. */
+ switch (output_action) {
- case WRITE_TEXT:
+ case WRITE_TEXT:
if (!print_columns(cf))
return FALSE;
break;
- case WRITE_XML:
+ case WRITE_XML:
proto_tree_write_psml(edt, stdout);
return !ferror(stdout);
- case WRITE_FIELDS: /*No non-verbose "fields" format */
+ case WRITE_FIELDS: /*No non-verbose "fields" format */
g_assert_not_reached();
break;
+ }
}
}
if (print_details) {
@@ -3553,7 +3557,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
printf("\n");
return !ferror(stdout);
case WRITE_FIELDS:
- proto_tree_write_fields(output_fields, edt, stdout);
+ proto_tree_write_fields(output_fields, edt, &cf->cinfo, stdout);
printf("\n");
return !ferror(stdout);
}