aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--file.c108
-rw-r--r--gtk/follow_dlg.c126
-rw-r--r--print.c449
-rw-r--r--print.h49
-rw-r--r--tethereal.c212
5 files changed, 677 insertions, 267 deletions
diff --git a/file.c b/file.c
index 22dd637338..6c1a703fa9 100644
--- a/file.c
+++ b/file.c
@@ -1495,7 +1495,7 @@ retap_packets(capture_file *cf)
typedef struct {
print_args_t *print_args;
- FILE *print_fh;
+ print_stream_t *stream;
gboolean print_header_line;
char *header_line_buf;
int header_line_buf_len;
@@ -1519,6 +1519,8 @@ print_packet(capture_file *cf, frame_data *fdata,
int column_len;
int cp_off;
gboolean proto_tree_needed;
+ char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
+ char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
/* Create the protocol tree, and make it visible, if we're printing
the dissection or the hex data.
@@ -1536,16 +1538,25 @@ print_packet(capture_file *cf, frame_data *fdata,
epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
if (args->print_formfeed) {
- print_formfeed(args->print_fh, args->print_args->format);
+ if (!new_page(args->stream))
+ goto fail;
} else {
- if (args->print_separator)
- print_line(args->print_fh, 0, args->print_args->format, "");
+ if (args->print_separator) {
+ if (!print_line(args->stream, 0, ""))
+ goto fail;
+ }
}
+ /*
+ * We generate bookmarks, if the output format supports them.
+ * The name is "__frameN__".
+ */
+ sprintf(bookmark_name, "__frame%u__", fdata->num);
+
if (args->print_args->print_summary) {
if (args->print_header_line) {
- print_line(args->print_fh, 0, args->print_args->format,
- args->header_line_buf);
+ if (!print_line(args->stream, 0, args->header_line_buf))
+ goto fail;
args->print_header_line = FALSE; /* we might not need to print any more */
}
cp = &args->line_buf[0];
@@ -1577,19 +1588,34 @@ print_packet(capture_file *cf, frame_data *fdata,
}
*cp = '\0';
- print_packet_header(args->print_fh, args->print_args->format, fdata->num, args->line_buf);
+ /*
+ * Generate a bookmark, using the summary line as the title.
+ */
+ if (!print_bookmark(args->stream, bookmark_name, args->line_buf))
+ goto fail;
- print_line(args->print_fh, 0, args->print_args->format, args->line_buf);
+ if (!print_line(args->stream, 0, args->line_buf))
+ goto fail;
+ } else {
+ /*
+ * Generate a bookmark, using "Frame N" as the title, as we're not
+ * printing the summary line.
+ */
+ sprintf(bookmark_title, "Frame %u", fdata->num);
+ if (!print_bookmark(args->stream, bookmark_name, bookmark_title))
+ goto fail;
} /* if (print_summary) */
-
+
if (args->print_args->print_dissections != print_dissections_none) {
if (args->print_args->print_summary) {
/* Separate the summary line from the tree with a blank line. */
- print_line(args->print_fh, 0, args->print_args->format, "");
+ if (!print_line(args->stream, 0, ""))
+ goto fail;
}
/* Print the information in that tree. */
- proto_tree_print(args->print_args, edt, args->print_fh);
+ if (!proto_tree_print(args->print_args, edt, args->stream))
+ goto fail;
/* Print a blank line if we print anything after this (aka more than one packet). */
args->print_separator = TRUE;
@@ -1600,14 +1626,15 @@ print_packet(capture_file *cf, frame_data *fdata,
if (args->print_args->print_hex) {
/* Print the full packet data as hex. */
- print_hex_data(args->print_fh, args->print_args->format, edt);
+ if (!print_hex_data(args->stream, edt))
+ goto fail;
/* Print a blank line if we print anything after this (aka more than one packet). */
args->print_separator = TRUE;
/* Print a header line if we print any more packet summaries */
args->print_header_line = TRUE;
- } /* if (print_summary) */
+ } /* if (args->print_args->print_dissections != print_dissections_none) */
epan_dissect_free(edt);
@@ -1616,7 +1643,11 @@ print_packet(capture_file *cf, frame_data *fdata,
args->print_formfeed = TRUE;
}
- return !ferror(args->print_fh);
+ return TRUE;
+
+fail:
+ epan_dissect_free(edt);
+ return FALSE;
}
pp_return_t
@@ -1631,19 +1662,37 @@ print_packets(capture_file *cf, print_args_t *print_args)
int line_len;
psp_return_t ret;
- if(print_args->to_file) {
- callback_args.print_fh = open_print_dest(print_args->to_file,
- print_args->file);
- } else {
- callback_args.print_fh = open_print_dest(print_args->to_file,
- print_args->cmd);
+ switch (print_args->format) {
+
+ case PR_FMT_TEXT:
+ if (print_args->to_file) {
+ callback_args.stream = print_stream_text_new(print_args->to_file,
+ print_args->file);
+ } else {
+ callback_args.stream = print_stream_text_new(print_args->to_file,
+ print_args->cmd);
+ }
+ break;
+
+ case PR_FMT_PS:
+ if (print_args->to_file) {
+ callback_args.stream = print_stream_ps_new(print_args->to_file,
+ print_args->file);
+ } else {
+ callback_args.stream = print_stream_ps_new(print_args->to_file,
+ print_args->cmd);
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
+ return PP_OPEN_ERROR;
}
- if (callback_args.print_fh == NULL)
+ if (callback_args.stream == NULL)
return PP_OPEN_ERROR; /* attempt to open destination failed */
- print_preamble(callback_args.print_fh, print_args->format, cf->filename);
- if (ferror(callback_args.print_fh)) {
- close_print_dest(print_args->to_file, callback_args.print_fh);
+ if (!print_preamble(callback_args.stream, cf->filename)) {
+ destroy_print_stream(callback_args.stream);
return PP_WRITE_ERROR;
}
@@ -1746,18 +1795,17 @@ print_packets(capture_file *cf, print_args_t *print_args)
will get printed if we're piping to a print program; we'd
have to write to a file and then hand that to the print
program to make it actually not print anything. */
- close_print_dest(print_args->to_file, callback_args.print_fh);
+ destroy_print_stream(callback_args.stream);
return PP_WRITE_ERROR;
}
- print_finale(callback_args.print_fh, print_args->format);
- if (ferror(callback_args.print_fh)) {
- close_print_dest(print_args->to_file, callback_args.print_fh);
+ if (!print_finale(callback_args.stream)) {
+ destroy_print_stream(callback_args.stream);
return PP_WRITE_ERROR;
}
- /* XXX - check for an error */
- close_print_dest(print_args->to_file, callback_args.print_fh);
+ if (!destroy_print_stream(callback_args.stream))
+ return PP_WRITE_ERROR;
return PP_OK;
}
diff --git a/gtk/follow_dlg.c b/gtk/follow_dlg.c
index 1fb308edcf..ce695ab82e 100644
--- a/gtk/follow_dlg.c
+++ b/gtk/follow_dlg.c
@@ -256,33 +256,33 @@ follow_stream_cb(GtkWidget * w, gpointer data _U_)
follow_info->streamwindow = streamwindow;
gtk_widget_set_name(streamwindow, "TCP stream window");
- gtk_window_set_default_size(GTK_WINDOW(streamwindow), DEF_WIDTH, DEF_HEIGHT);
+ gtk_window_set_default_size(GTK_WINDOW(streamwindow), DEF_WIDTH, DEF_HEIGHT);
gtk_container_border_width(GTK_CONTAINER(streamwindow), 6);
/* setup the container */
- tooltips = gtk_tooltips_new ();
+ tooltips = gtk_tooltips_new ();
vbox = gtk_vbox_new(FALSE, 6);
gtk_container_add(GTK_CONTAINER(streamwindow), vbox);
/* content frame */
if (incomplete_tcp_stream) {
- stream_fr = gtk_frame_new("Stream Content (incomplete)");
+ stream_fr = gtk_frame_new("Stream Content (incomplete)");
} else {
- stream_fr = gtk_frame_new("Stream Content");
+ stream_fr = gtk_frame_new("Stream Content");
}
gtk_container_add(GTK_CONTAINER(vbox), stream_fr);
gtk_widget_show(stream_fr);
- stream_vb = gtk_vbox_new(FALSE, 6);
+ stream_vb = gtk_vbox_new(FALSE, 6);
gtk_container_set_border_width( GTK_CONTAINER(stream_vb) , 6);
gtk_container_add(GTK_CONTAINER(stream_fr), stream_vb);
/* create a scrolled window for the text */
txt_scrollw = scrolled_window_new(NULL, NULL);
#if GTK_MAJOR_VERSION >= 2
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scrollw),
- GTK_SHADOW_IN);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scrollw),
+ GTK_SHADOW_IN);
#endif
gtk_box_pack_start(GTK_BOX(stream_vb), txt_scrollw, TRUE, TRUE, 0);
@@ -303,15 +303,15 @@ follow_stream_cb(GtkWidget * w, gpointer data _U_)
gtk_box_pack_start(GTK_BOX(stream_vb), hbox, FALSE, FALSE, 0);
/* Create Save As Button */
- button = BUTTON_NEW_FROM_STOCK(GTK_STOCK_SAVE_AS);
+ button = BUTTON_NEW_FROM_STOCK(GTK_STOCK_SAVE_AS);
SIGNAL_CONNECT(button, "clicked", follow_save_as_cmd_cb, follow_info);
- gtk_tooltips_set_tip (tooltips, button, "Save the content as currently displayed ", NULL);
+ gtk_tooltips_set_tip (tooltips, button, "Save the content as currently displayed ", NULL);
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
/* Create Print Button */
- button = BUTTON_NEW_FROM_STOCK(GTK_STOCK_PRINT);
+ button = BUTTON_NEW_FROM_STOCK(GTK_STOCK_PRINT);
SIGNAL_CONNECT(button, "clicked", follow_print_stream, follow_info);
- gtk_tooltips_set_tip (tooltips, button, "Print the content as currently displayed", NULL);
+ gtk_tooltips_set_tip (tooltips, button, "Print the content as currently displayed", NULL);
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
/* Stream to show */
@@ -373,8 +373,8 @@ follow_stream_cb(GtkWidget * w, gpointer data _U_)
gtk_option_menu_set_menu(GTK_OPTION_MENU(stream_om), stream_menu);
/* Set history to 0th item, i.e., the first item. */
gtk_option_menu_set_history(GTK_OPTION_MENU(stream_om), 0);
- gtk_tooltips_set_tip (tooltips, stream_om,
- "Select the stream direction to display", NULL);
+ gtk_tooltips_set_tip (tooltips, stream_om,
+ "Select the stream direction to display", NULL);
gtk_box_pack_start(GTK_BOX(hbox), stream_om, FALSE, FALSE, 0);
/* ASCII radio button */
@@ -419,24 +419,24 @@ follow_stream_cb(GtkWidget * w, gpointer data _U_)
/* button hbox */
button_hbox = gtk_hbutton_box_new();
gtk_box_pack_start(GTK_BOX(vbox), button_hbox, FALSE, FALSE, 0);
- gtk_button_box_set_layout (GTK_BUTTON_BOX(button_hbox), GTK_BUTTONBOX_END);
- gtk_button_box_set_spacing(GTK_BUTTON_BOX(button_hbox), 5);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX(button_hbox), GTK_BUTTONBOX_END);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX(button_hbox), 5);
/* Create exclude stream button */
button = gtk_button_new_with_label("Filter out this stream");
SIGNAL_CONNECT(button, "clicked", follow_filter_out_stream, follow_info);
- gtk_tooltips_set_tip (tooltips, button,
+ gtk_tooltips_set_tip (tooltips, button,
"Build a display filter which cuts this stream from the capture", NULL);
gtk_box_pack_start(GTK_BOX(button_hbox), button, FALSE, FALSE, 0);
/* Create Close Button */
- button = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
- gtk_tooltips_set_tip (tooltips, button,
- "Close the dialog and keep the current display filter", NULL);
+ button = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
+ gtk_tooltips_set_tip (tooltips, button,
+ "Close the dialog and keep the current display filter", NULL);
gtk_box_pack_start(GTK_BOX(button_hbox), button, FALSE, FALSE, 0);
- GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
- window_set_cancel_button(streamwindow, button, window_cancel_button_cb);
+ window_set_cancel_button(streamwindow, button, window_cancel_button_cb);
/* Tuck away the follow_info object into the window */
OBJECT_SET_DATA(streamwindow, E_FOLLOW_INFO_KEY, follow_info);
@@ -446,7 +446,7 @@ follow_stream_cb(GtkWidget * w, gpointer data _U_)
data_out_file = NULL;
- SIGNAL_CONNECT(streamwindow, "delete_event", window_delete_event_cb, NULL);
+ SIGNAL_CONNECT(streamwindow, "delete_event", window_delete_event_cb, NULL);
SIGNAL_CONNECT(streamwindow, "destroy", follow_destroy_cb, NULL);
/* Make sure this widget gets destroyed if we quit the main loop,
@@ -465,14 +465,14 @@ static void
follow_destroy_cb(GtkWidget *w, gpointer data _U_)
{
follow_info_t *follow_info;
- int i;
+ int i;
follow_info = OBJECT_GET_DATA(w, E_FOLLOW_INFO_KEY);
i = unlink(follow_info->data_out_filename);
- if(i != 0) {
- g_warning("Follow: Couldn't remove temporary file: \"%s\", errno: %s (%u)",
- follow_info->data_out_filename, strerror(errno), errno);
- }
+ if(i != 0) {
+ g_warning("Follow: Couldn't remove temporary file: \"%s\", errno: %s (%u)",
+ follow_info->data_out_filename, strerror(errno), errno);
+ }
g_free(follow_info->filter_out_filter);
forget_follow_info(follow_info);
g_free(follow_info);
@@ -536,8 +536,8 @@ typedef enum {
static frs_return_t
follow_read_stream(follow_info_t *follow_info,
- gboolean (*print_line) (char *, int, gboolean, void *, print_format_e),
- void *arg, print_format_e format)
+ gboolean (*print_line) (char *, int, gboolean, void *),
+ void *arg)
{
tcp_stream_chunk sc;
int bcount, iplen;
@@ -597,7 +597,7 @@ follow_read_stream(follow_info_t *follow_info,
case SHOW_EBCDIC:
/* If our native arch is ASCII, call: */
EBCDIC_to_ASCII(buffer, nchars);
- if (!(*print_line) (buffer, nchars, is_server, arg, format))
+ if (!(*print_line) (buffer, nchars, is_server, arg))
goto print_error;
break;
@@ -605,7 +605,7 @@ follow_read_stream(follow_info_t *follow_info,
/* If our native arch is EBCDIC, call:
* ASCII_TO_EBCDIC(buffer, nchars);
*/
- if (!(*print_line) (buffer, nchars, is_server, arg, format))
+ if (!(*print_line) (buffer, nchars, is_server, arg))
goto print_error;
break;
@@ -662,7 +662,7 @@ follow_read_stream(follow_info_t *follow_info,
(*global_pos) += i;
hexbuf[cur++] = '\n';
hexbuf[cur] = 0;
- if (!(*print_line) (hexbuf, strlen(hexbuf), is_server, arg, format))
+ if (!(*print_line) (hexbuf, strlen(hexbuf), is_server, arg))
goto print_error;
}
break;
@@ -671,7 +671,7 @@ follow_read_stream(follow_info_t *follow_info,
current_pos = 0;
g_snprintf(initbuf, 256, "char peer%d_%d[] = {\n", is_server ? 1 : 0,
is_server ? server_packet_count++ : client_packet_count++);
- if (!(*print_line) (initbuf, strlen(initbuf), is_server, arg, format))
+ if (!(*print_line) (initbuf, strlen(initbuf), is_server, arg))
goto print_error;
while (current_pos < nchars) {
gchar hexbuf[256];
@@ -705,7 +705,7 @@ follow_read_stream(follow_info_t *follow_info,
(*global_pos) += i;
hexbuf[cur++] = '\n';
hexbuf[cur] = 0;
- if (!(*print_line) (hexbuf, strlen(hexbuf), is_server, arg, format))
+ if (!(*print_line) (hexbuf, strlen(hexbuf), is_server, arg))
goto print_error;
}
break;
@@ -740,9 +740,9 @@ print_error:
* suggestion.
*/
static gboolean
-follow_print_text(char *buffer, int nchars, gboolean is_server _U_, void *arg, print_format_e format)
+follow_print_text(char *buffer, int nchars, gboolean is_server _U_, void *arg)
{
- FILE *fh = arg;
+ print_stream_t *stream = arg;
int i;
char *str;
@@ -759,7 +759,7 @@ follow_print_text(char *buffer, int nchars, gboolean is_server _U_, void *arg, p
str = g_malloc(nchars + 1);
memcpy(str, buffer, nchars);
str[nchars] = 0;
- print_line(fh, /*indent*/ 0, format, str);
+ print_line(stream, /*indent*/ 0, str);
g_free(str);
return TRUE;
@@ -788,7 +788,7 @@ follow_filter_out_stream(GtkWidget * w _U_, gpointer data)
static void
follow_print_stream(GtkWidget * w _U_, gpointer data)
{
- FILE *fh;
+ print_stream_t *stream;
gboolean to_file;
char *print_dest;
follow_info_t *follow_info = data;
@@ -796,7 +796,6 @@ follow_print_stream(GtkWidget * w _U_, gpointer data)
gboolean win_printer = FALSE;
#endif
-
switch (prefs.pr_dest) {
case PR_DEST_CMD:
#ifdef _WIN32
@@ -820,8 +819,21 @@ follow_print_stream(GtkWidget * w _U_, gpointer data)
return;
}
- fh = open_print_dest(to_file, print_dest);
- if (fh == NULL) {
+ switch (prefs.pr_format) {
+
+ case PR_FMT_TEXT:
+ stream = print_stream_text_new(to_file, print_dest);
+ break;
+
+ case PR_FMT_PS:
+ stream = print_stream_ps_new(to_file, print_dest);
+ break;
+
+ default:
+ g_assert_not_reached();
+ stream = NULL;
+ }
+ if (stream == NULL) {
if (to_file) {
open_failure_alert_box(prefs.pr_file, errno, TRUE);
} else {
@@ -831,31 +843,29 @@ follow_print_stream(GtkWidget * w _U_, gpointer data)
return;
}
- print_preamble(fh, prefs.pr_format, cfile.filename);
- if (ferror(fh))
+ if (!print_preamble(stream, cfile.filename))
goto print_error;
- switch (follow_read_stream(follow_info, follow_print_text, fh, prefs.pr_format)) {
+ switch (follow_read_stream(follow_info, follow_print_text, stream)) {
case FRS_OK:
break;
case FRS_OPEN_ERROR:
case FRS_READ_ERROR:
/* XXX - cancel printing? */
- close_print_dest(to_file, fh);
+ destroy_print_stream(stream);
return;
case FRS_PRINT_ERROR:
goto print_error;
}
- print_finale(fh, prefs.pr_format);
- if (ferror(fh))
+ if (!print_finale(stream))
goto print_error;
- if (!close_print_dest(to_file, fh)) {
+ if (!destroy_print_stream(stream)) {
if (to_file) {
- write_failure_alert_box(prefs.pr_file, errno);
+ write_failure_alert_box(prefs.pr_file, errno);
} else {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Error closing print destination.");
}
}
@@ -877,7 +887,7 @@ print_error:
"Error writing to print command: %s", strerror(errno));
}
/* XXX - cancel printing? */
- close_print_dest(to_file, fh);
+ destroy_print_stream(stream);
#ifdef _WIN32
if (win_printer) {
@@ -889,7 +899,7 @@ print_error:
static gboolean
follow_add_to_gtk_text(char *buffer, int nchars, gboolean is_server,
- void *arg, print_format_e format _U_)
+ void *arg)
{
GtkWidget *text = arg;
GdkColor fg, bg;
@@ -964,7 +974,7 @@ follow_load_text(follow_info_t *follow_info)
#else
gtk_text_buffer_set_text(buf, "", -1);
#endif
- follow_read_stream(follow_info, follow_add_to_gtk_text, follow_info->text, PR_FMT_TEXT);
+ follow_read_stream(follow_info, follow_add_to_gtk_text, follow_info->text);
#if GTK_MAJOR_VERSION < 2
gtk_text_thaw(GTK_TEXT(follow_info->text));
#endif
@@ -1030,6 +1040,7 @@ follow_save_as_ok_cb(GtkWidget * w _U_, gpointer fs)
gchar *to_name;
follow_info_t *follow_info;
FILE *fh;
+ print_stream_t *stream;
gchar *dirname;
#if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
@@ -1055,26 +1066,27 @@ follow_save_as_ok_cb(GtkWidget * w _U_, gpointer fs)
g_free(to_name);
return;
}
+ stream = print_stream_text_stdio_new(fh);
gtk_widget_hide(GTK_WIDGET(fs));
follow_info = OBJECT_GET_DATA(fs, E_FOLLOW_INFO_KEY);
window_destroy(GTK_WIDGET(fs));
- switch (follow_read_stream(follow_info, follow_print_text, fh, PR_FMT_TEXT)) {
+ switch (follow_read_stream(follow_info, follow_print_text, stream)) {
case FRS_OK:
- if (fclose(fh) == EOF)
+ if (!destroy_print_stream(stream))
write_failure_alert_box(to_name, errno);
break;
case FRS_OPEN_ERROR:
case FRS_READ_ERROR:
- fclose(fh);
+ destroy_print_stream(stream);
break;
case FRS_PRINT_ERROR:
write_failure_alert_box(to_name, errno);
- fclose(fh);
+ destroy_print_stream(stream);
break;
}
diff --git a/print.c b/print.c
index 23f5884a06..0fb42cf878 100644
--- a/print.c
+++ b/print.c
@@ -48,12 +48,12 @@
typedef struct {
int level;
- FILE *fh;
+ print_stream_t *stream;
+ gboolean success;
GSList *src_list;
print_dissections_e print_dissections;
gboolean print_hex_for_data;
char_enc encoding;
- gint format;
epan_dissect_t *edt;
} print_data;
@@ -68,15 +68,16 @@ static void proto_tree_print_node(proto_node *node, gpointer data);
static void proto_tree_write_node_pdml(proto_node *node, gpointer data);
static const guint8 *get_field_data(GSList *src_list, field_info *fi);
static void write_pdml_field_hex_value(write_pdml_data *pdata, field_info *fi);
-static void print_hex_data_buffer(FILE *fh, register const guchar *cp,
- register guint length, char_enc encoding, print_format_e format);
+static gboolean print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
+ guint length, char_enc encoding);
static void ps_clean_string(unsigned char *out, const unsigned char *in,
int outbuf_size);
static void print_escaped_xml(FILE *fh, char *unescaped_string);
static void print_pdml_geninfo(proto_tree *tree, FILE *fh);
-FILE *open_print_dest(int to_file, const char *dest)
+static FILE *
+open_print_dest(int to_file, const char *dest)
{
FILE *fh;
@@ -89,7 +90,8 @@ FILE *open_print_dest(int to_file, const char *dest)
return fh;
}
-gboolean close_print_dest(int to_file, FILE *fh)
+static gboolean
+close_print_dest(int to_file, FILE *fh)
{
/* Close the file or command */
if (to_file)
@@ -100,55 +102,26 @@ gboolean close_print_dest(int to_file, FILE *fh)
#define MAX_PS_LINE_LENGTH 256
-/* Some formats need stuff at the beginning of the output */
-void
-print_preamble(FILE *fh, print_format_e format, gchar *filename)
-{
- char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */
-
-
- switch (format) {
-
- case(PR_FMT_TEXT):
- /* do nothing */
- break;
-
- case(PR_FMT_PS):
- print_ps_preamble(fh);
-
- fputs("%% Set the font to 10 point\n", fh);
- fputs("/Courier findfont 10 scalefont setfont\n", fh);
- fputs("\n", fh);
- fputs("%% the page title\n", fh);
- ps_clean_string(psbuffer, filename, MAX_PS_LINE_LENGTH);
- fprintf(fh, "/eth_pagetitle (%s - Ethereal) def\n", psbuffer);
- fputs("\n", fh);
- break;
-
- default:
- g_assert_not_reached();
- }
-}
-
-void
+gboolean
proto_tree_print(print_args_t *print_args, epan_dissect_t *edt,
- FILE *fh)
+ print_stream_t *stream)
{
print_data data;
/* Create the output */
data.level = 0;
- data.fh = fh;
+ data.stream = stream;
+ data.success = TRUE;
data.src_list = edt->pi.data_src;
data.encoding = edt->pi.fd->flags.encoding;
data.print_dissections = print_args->print_dissections;
/* If we're printing the entire packet in hex, don't
print uninterpreted data fields in hex as well. */
data.print_hex_for_data = !print_args->print_hex;
- data.format = print_args->format;
data.edt = edt;
proto_tree_children_foreach(edt->tree, proto_tree_print_node, &data);
+ return data.success;
}
#define MAX_INDENT 160
@@ -167,6 +140,10 @@ void proto_tree_print_node(proto_node *node, gpointer data)
if (PROTO_ITEM_IS_HIDDEN(node))
return;
+ /* Give up if we've already gotten an error. */
+ if (!pdata->success)
+ return;
+
/* was a free format label produced? */
if (fi->rep) {
label_ptr = fi->rep->representation;
@@ -176,7 +153,10 @@ void proto_tree_print_node(proto_node *node, gpointer data)
proto_item_fill_label(fi, label_str);
}
- print_line(pdata->fh, pdata->level, pdata->format, label_ptr);
+ if (!print_line(pdata->stream, pdata->level, label_ptr)) {
+ pdata->success = FALSE;
+ return;
+ }
/* If it's uninterpreted data, dump it (unless our caller will
be printing the entire packet in hex). */
@@ -186,8 +166,11 @@ void proto_tree_print_node(proto_node *node, gpointer data)
*/
pd = get_field_data(pdata->src_list, fi);
if (pd) {
- print_hex_data_buffer(pdata->fh, pd, fi->length,
- pdata->encoding, pdata->format);
+ if (!print_hex_data_buffer(pdata->stream, pd,
+ fi->length, pdata->encoding)) {
+ pdata->success = FALSE;
+ return;
+ }
}
}
@@ -203,29 +186,12 @@ void proto_tree_print_node(proto_node *node, gpointer data)
proto_tree_children_foreach(node,
proto_tree_print_node, pdata);
pdata->level--;
+ if (!pdata->success)
+ return;
}
}
}
-/* Some formats need stuff at the end of the output */
-void
-print_finale(FILE *fh, print_format_e format)
-{
- switch (format) {
-
- case(PR_FMT_TEXT):
- /* do nothing */
- break;
-
- case(PR_FMT_PS):
- print_ps_finale(fh);
- break;
-
- default:
- g_assert_not_reached();
- }
-}
-
void
write_pdml_preamble(FILE *fh)
{
@@ -640,8 +606,8 @@ write_pdml_field_hex_value(write_pdml_data *pdata, field_info *fi)
}
}
-
-void print_hex_data(FILE *fh, print_format_e format, epan_dissect_t *edt)
+gboolean
+print_hex_data(print_stream_t *stream, epan_dissect_t *edt)
{
gboolean multiple_sources;
GSList *src_le;
@@ -666,18 +632,20 @@ void print_hex_data(FILE *fh, print_format_e format, epan_dissect_t *edt)
tvb = src->tvb;
if (multiple_sources) {
name = src->name;
- print_line(fh, 0, format, "");
+ print_line(stream, 0, "");
line = g_malloc(strlen(name) + 2); /* <name>:\0 */
strcpy(line, name);
strcat(line, ":");
- print_line(fh, 0, format, line);
+ print_line(stream, 0, line);
g_free(line);
}
length = tvb_length(tvb);
cp = tvb_get_ptr(tvb, 0, length);
- print_hex_data_buffer(fh, cp, length,
- edt->pi.fd->flags.encoding, format);
+ if (!print_hex_data_buffer(stream, cp, length,
+ edt->pi.fd->flags.encoding))
+ return FALSE;
}
+ return TRUE;
}
/*
@@ -702,9 +670,9 @@ void print_hex_data(FILE *fh, print_format_e format, epan_dissect_t *edt)
offset, 2 blanks separating offset
from data dump, data dump */
-static void
-print_hex_data_buffer(FILE *fh, register const guchar *cp,
- register guint length, char_enc encoding, print_format_e format)
+static gboolean
+print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
+ guint length, char_enc encoding)
{
register unsigned int ad, i, j, k, l;
guchar c;
@@ -714,7 +682,8 @@ print_hex_data_buffer(FILE *fh, register const guchar *cp,
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- print_line(fh, 0, format, "");
+ if (!print_line(stream, 0, ""))
+ return FALSE;
/*
* How many of the leading digits of the offset will we supply?
@@ -775,10 +744,12 @@ print_hex_data_buffer(FILE *fh, register const guchar *cp,
* and advance the offset.
*/
line[k] = '\0';
- print_line(fh, 0, format, line);
+ if (!print_line(stream, 0, line))
+ return FALSE;
ad += 16;
}
}
+ return TRUE;
}
static
@@ -821,6 +792,17 @@ print_packet_header(FILE *fh, print_format_e format, guint32 number, gchar *summ
case(PR_FMT_PS):
ps_clean_string(psbuffer, summary, MAX_PS_LINE_LENGTH);
+ /*
+ * See the Adobe "pdfmark reference". The pdfmark stuff
+ * tells code that turns PostScript into PDF stuff that
+ * it should do.
+ *
+ * The /OUT stuff creates a bookmark that goes to the
+ * destination with the name "__frame{N}__", where N is
+ * the "number" argument, and with "summary" as the title.
+ *
+ * The "/DEST" creates the destination.
+ */
fprintf(fh, "[/Dest /__frame%u__ /Title (%s) /OUT pdfmark\n", number, psbuffer);
fputs("[/View [/XYZ -4 currentpoint matrix currentmatrix matrix defaultmatrix\n", fh);
fputs("matrix invertmatrix matrix concatmatrix transform exch pop 20 add null]\n", fh);
@@ -832,57 +814,300 @@ print_packet_header(FILE *fh, print_format_e format, guint32 number, gchar *summ
}
}
-void
-print_formfeed(FILE *fh, print_format_e format)
+/* Some formats need stuff at the beginning of the output */
+gboolean
+print_preamble(print_stream_t *self, gchar *filename)
{
- switch (format) {
+ return (self->ops->print_preamble)(self, filename);
+}
- case(PR_FMT_TEXT):
- fputs("\f", fh);
- break;
+gboolean
+print_line(print_stream_t *self, int indent, const char *line)
+{
+ return (self->ops->print_line)(self, indent, line);
+}
- case(PR_FMT_PS):
- fputs("formfeed\n", fh);
- break;
+/* Insert bookmark */
+gboolean
+print_bookmark(print_stream_t *self, const gchar *name, const gchar *title)
+{
+ return (self->ops->print_bookmark)(self, name, title);
+}
- default:
- g_assert_not_reached();
+gboolean
+new_page(print_stream_t *self)
+{
+ return (self->ops->new_page)(self);
+}
+
+/* Some formats need stuff at the end of the output */
+gboolean
+print_finale(print_stream_t *self)
+{
+ return (self->ops->print_finale)(self);
+}
+
+gboolean
+destroy_print_stream(print_stream_t *self)
+{
+ return (self->ops->destroy)(self);
+}
+
+typedef struct {
+ int to_file;
+ FILE *fh;
+} output_text;
+
+static gboolean
+print_preamble_text(print_stream_t *self _U_, gchar *filename _U_)
+{
+ /* do nothing */
+ return TRUE; /* always succeeds */
+}
+
+static gboolean
+print_line_text(print_stream_t *self, int indent, const char *line)
+{
+ output_text *output = self->data;
+ char space[MAX_INDENT+1];
+ int i;
+ int num_spaces;
+
+ /* Prepare the tabs for printing, depending on tree level */
+ num_spaces = indent * 4;
+ if (num_spaces > MAX_INDENT) {
+ num_spaces = MAX_INDENT;
}
+ for (i = 0; i < num_spaces; i++) {
+ space[i] = ' ';
+ }
+ /* The string is NUL-terminated */
+ space[num_spaces] = '\0';
+
+ fputs(space, output->fh);
+ fputs(line, output->fh);
+ putc('\n', output->fh);
+ return !ferror(output->fh);
}
-void
-print_line(FILE *fh, int indent, print_format_e format, char *line)
+static gboolean
+print_bookmark_text(print_stream_t *self _U_, const gchar *name _U_,
+ const gchar *title _U_)
{
- char space[MAX_INDENT+1];
- int i;
- int num_spaces;
+ /* do nothing */
+ return TRUE;
+}
+
+static gboolean
+new_page_text(print_stream_t *self)
+{
+ output_text *output = self->data;
+
+ fputs("\f", output->fh);
+ return !ferror(output->fh);
+}
+
+static gboolean
+print_finale_text(print_stream_t *self _U_)
+{
+ /* do nothing */
+ return TRUE; /* always succeeds */
+}
+
+static gboolean
+destroy_text(print_stream_t *self)
+{
+ output_text *output = self->data;
+ gboolean ret;
+
+ ret = close_print_dest(output->to_file, output->fh);
+ g_free(output);
+ g_free(self);
+ return ret;
+}
+
+static const print_stream_ops_t print_text_ops = {
+ print_preamble_text,
+ print_line_text,
+ print_bookmark_text,
+ new_page_text,
+ print_finale_text,
+ destroy_text
+};
+
+print_stream_t *
+print_stream_text_new(int to_file, const char *dest)
+{
+ FILE *fh;
+ print_stream_t *stream;
+ output_text *output;
+
+ fh = open_print_dest(to_file, dest);
+ if (fh == NULL)
+ return NULL;
+
+ output = g_malloc(sizeof *output);
+ output->to_file = to_file;
+ output->fh = fh;
+ stream = g_malloc(sizeof (print_stream_t));
+ stream->ops = &print_text_ops;
+ stream->data = output;
+
+ return stream;
+}
+
+print_stream_t *
+print_stream_text_stdio_new(FILE *fh)
+{
+ print_stream_t *stream;
+ output_text *output;
+
+ output = g_malloc(sizeof *output);
+ output->to_file = TRUE;
+ output->fh = fh;
+ stream = g_malloc(sizeof (print_stream_t));
+ stream->ops = &print_text_ops;
+ stream->data = output;
+
+ return stream;
+}
+
+typedef struct {
+ int to_file;
+ FILE *fh;
+} output_ps;
+
+static gboolean
+print_preamble_ps(print_stream_t *self, gchar *filename)
+{
+ output_ps *output = self->data;
char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */
- switch (format) {
+ print_ps_preamble(output->fh);
- case(PR_FMT_TEXT):
- /* Prepare the tabs for printing, depending on tree level */
- num_spaces = indent * 4;
- if (num_spaces > MAX_INDENT) {
- num_spaces = MAX_INDENT;
- }
- for (i = 0; i < num_spaces; i++) {
- space[i] = ' ';
- }
- /* The string is NUL-terminated */
- space[num_spaces] = '\0';
+ fputs("%% Set the font to 10 point\n", output->fh);
+ fputs("/Courier findfont 10 scalefont setfont\n", output->fh);
+ fputs("\n", output->fh);
+ fputs("%% the page title\n", output->fh);
+ ps_clean_string(psbuffer, filename, MAX_PS_LINE_LENGTH);
+ fprintf(output->fh, "/eth_pagetitle (%s - Ethereal) def\n", psbuffer);
+ fputs("\n", output->fh);
+ return !ferror(output->fh);
+}
- fputs(space, fh);
- fputs(line, fh);
- putc('\n', fh);
- break;
+static gboolean
+print_line_ps(print_stream_t *self, int indent, const char *line)
+{
+ output_ps *output = self->data;
+ char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */
- case(PR_FMT_PS):
- ps_clean_string(psbuffer, line, MAX_PS_LINE_LENGTH);
- fprintf(fh, "%d (%s) putline\n", indent, psbuffer);
- break;
+ ps_clean_string(psbuffer, line, MAX_PS_LINE_LENGTH);
+ fprintf(output->fh, "%d (%s) putline\n", indent, psbuffer);
+ return !ferror(output->fh);
+}
- default:
- g_assert_not_reached();
- }
+static gboolean
+print_bookmark_ps(print_stream_t *self, const gchar *name, const gchar *title)
+{
+ output_ps *output = self->data;
+ char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */
+
+ /*
+ * See the Adobe "pdfmark reference":
+ *
+ * http://partners.adobe.com/asn/acrobat/docs/pdfmark.pdf
+ *
+ * The pdfmark stuff tells code that turns PostScript into PDF
+ * things that it should do.
+ *
+ * The /OUT stuff creates a bookmark that goes to the
+ * destination with "name" as the name and "title" as the title.
+ *
+ * The "/DEST" creates the destination.
+ */
+ ps_clean_string(psbuffer, title, MAX_PS_LINE_LENGTH);
+ fprintf(output->fh, "[/Dest /%s /Title (%s) /OUT pdfmark\n", name,
+ psbuffer);
+ fputs("[/View [/XYZ -4 currentpoint matrix currentmatrix matrix defaultmatrix\n",
+ output->fh);
+ fputs("matrix invertmatrix matrix concatmatrix transform exch pop 20 add null]\n",
+ output->fh);
+ fprintf(output->fh, "/Dest /%s /DEST pdfmark\n", name);
+ return !ferror(output->fh);
+}
+
+static gboolean
+new_page_ps(print_stream_t *self)
+{
+ output_ps *output = self->data;
+
+ fputs("formfeed\n", output->fh);
+ return !ferror(output->fh);
+}
+
+static gboolean
+print_finale_ps(print_stream_t *self)
+{
+ output_ps *output = self->data;
+
+ print_ps_finale(output->fh);
+ return !ferror(output->fh);
+}
+
+static gboolean
+destroy_ps(print_stream_t *self)
+{
+ output_ps *output = self->data;
+ gboolean ret;
+
+ ret = close_print_dest(output->to_file, output->fh);
+ g_free(output);
+ g_free(self);
+ return ret;
+}
+
+static const print_stream_ops_t print_ps_ops = {
+ print_preamble_ps,
+ print_line_ps,
+ print_bookmark_ps,
+ new_page_ps,
+ print_finale_ps,
+ destroy_ps
+};
+
+print_stream_t *
+print_stream_ps_new(int to_file, const char *dest)
+{
+ FILE *fh;
+ print_stream_t *stream;
+ output_ps *output;
+
+ fh = open_print_dest(to_file, dest);
+ if (fh == NULL)
+ return NULL;
+
+ output = g_malloc(sizeof *output);
+ output->to_file = to_file;
+ output->fh = fh;
+ stream = g_malloc(sizeof (print_stream_t));
+ stream->ops = &print_ps_ops;
+ stream->data = output;
+
+ return stream;
+}
+
+print_stream_t *
+print_stream_ps_stdio_new(FILE *fh)
+{
+ print_stream_t *stream;
+ output_ps *output;
+
+ output = g_malloc(sizeof *output);
+ output->to_file = TRUE;
+ output->fh = fh;
+ stream = g_malloc(sizeof (print_stream_t));
+ stream->ops = &print_ps_ops;
+ stream->data = output;
+
+ return stream;
}
diff --git a/print.h b/print.h
index 848608ffd4..d131f18f91 100644
--- a/print.h
+++ b/print.h
@@ -52,7 +52,7 @@ typedef enum {
} print_dissections_e;
typedef struct {
- print_format_e format; /* plain text, PostScript, PDML, ... */
+ print_format_e format; /* plain text or PostScript */
gboolean to_file; /* TRUE if we're printing to a file */
char *file; /* file output pathname */
char *cmd; /* print command string (not win32) */
@@ -69,21 +69,48 @@ typedef struct {
/* Functions in print.h */
-extern FILE *open_print_dest(int to_file, const char *dest);
-extern gboolean close_print_dest(int to_file, FILE *fh);
-extern void print_preamble(FILE *fh, print_format_e format, gchar *filename);
-extern void print_packet_header(FILE *fh, print_format_e format, guint32 number, gchar *summary);
-extern void print_formfeed(FILE *fh, print_format_e format);
-extern void print_finale(FILE *fh, print_format_e format);
-extern void proto_tree_print(print_args_t *print_args, epan_dissect_t *edt,
- FILE *fh);
extern void write_pdml_preamble(FILE *fh);
extern void proto_tree_write_pdml(epan_dissect_t *edt, FILE *fh);
extern void write_pdml_finale(FILE *fh);
+
extern void write_psml_preamble(FILE *fh);
extern void proto_tree_write_psml(epan_dissect_t *edt, FILE *fh);
extern void write_psml_finale(FILE *fh);
-extern void print_hex_data(FILE *fh, print_format_e format, epan_dissect_t *edt);
-extern void print_line(FILE *fh, int indent, print_format_e format, char *line);
+
+struct print_stream;
+
+typedef struct print_stream_ops {
+ gboolean (*print_preamble)(struct print_stream *self, gchar *filename);
+ gboolean (*print_line)(struct print_stream *self, int indent,
+ const char *line);
+ gboolean (*print_bookmark)(struct print_stream *self,
+ const gchar *name, const gchar *title);
+ gboolean (*new_page)(struct print_stream *self);
+ gboolean (*print_finale)(struct print_stream *self);
+ gboolean (*destroy)(struct print_stream *self);
+} print_stream_ops_t;
+
+typedef struct print_stream {
+ const print_stream_ops_t *ops;
+ void *data;
+} print_stream_t;
+
+extern gboolean proto_tree_print(print_args_t *print_args, epan_dissect_t *edt,
+ print_stream_t *stream);
+extern gboolean print_hex_data(print_stream_t *stream, epan_dissect_t *edt);
+extern void print_packet_header(FILE *fh, print_format_e format, guint32 number, gchar *summary);
+
+extern print_stream_t *print_stream_text_new(int to_file, const char *dest);
+extern print_stream_t *print_stream_text_stdio_new(FILE *fh);
+extern print_stream_t *print_stream_ps_new(int to_file, const char *dest);
+extern print_stream_t *print_stream_ps_stdio_new(FILE *fh);
+
+extern gboolean print_preamble(print_stream_t *self, gchar *filename);
+extern gboolean print_line(print_stream_t *self, int indent, const char *line);
+extern gboolean print_bookmark(print_stream_t *self, const gchar *name,
+ const gchar *title);
+extern gboolean new_page(print_stream_t *self);
+extern gboolean print_finale(print_stream_t *self);
+extern gboolean destroy_print_stream(print_stream_t *self);
#endif /* print.h */
diff --git a/tethereal.c b/tethereal.c
index 3c1384adb9..b6dcab2e34 100644
--- a/tethereal.c
+++ b/tethereal.c
@@ -137,7 +137,8 @@ static gboolean verbose;
static gboolean print_hex;
static gboolean line_buffered;
static guint32 cum_bytes = 0;
-static print_format_e print_format;
+static print_format_e print_format = PR_FMT_TEXT;
+static print_stream_t *print_stream;
#ifdef HAVE_LIBPCAP
typedef struct _loop_data {
@@ -184,9 +185,9 @@ static gboolean process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
const guchar *pd, int *err);
static void show_capture_file_io_error(const char *, int, gboolean);
static void show_print_file_io_error(int err);
-static void write_preamble(capture_file *cf);
-static void print_packet(capture_file *cf, epan_dissect_t *edt);
-static void write_finale(void);
+static gboolean write_preamble(capture_file *cf);
+static gboolean print_packet(capture_file *cf, epan_dissect_t *edt);
+static gboolean write_finale(void);
static char *cf_open_error_message(int err, gchar *err_info,
gboolean for_writing, int file_type);
#ifdef HAVE_LIBPCAP
@@ -1223,21 +1224,21 @@ main(int argc, char *argv[])
break;
case 'T': /* printing Type */
if (strcmp(optarg, "text") == 0) {
- output_action = WRITE_TEXT;
- print_format = PR_FMT_TEXT;
+ output_action = WRITE_TEXT;
+ print_format = PR_FMT_TEXT;
} else if (strcmp(optarg, "ps") == 0) {
- output_action = WRITE_TEXT;
- print_format = PR_FMT_PS;
+ output_action = WRITE_TEXT;
+ print_format = PR_FMT_PS;
} else if (strcmp(optarg, "pdml") == 0) {
- output_action = WRITE_XML;
- verbose = TRUE;
+ output_action = WRITE_XML;
+ verbose = TRUE;
} else if (strcmp(optarg, "psml") == 0) {
- output_action = WRITE_XML;
- verbose = FALSE;
+ output_action = WRITE_XML;
+ verbose = FALSE;
} else {
- fprintf(stderr, "tethereal: Invalid -T parameter.\n");
- fprintf(stderr, "It must be \"ps\", \"text\", \"pdml\", or \"psml\".\n");
- exit(1);
+ fprintf(stderr, "tethereal: Invalid -T parameter.\n");
+ fprintf(stderr, "It must be \"ps\", \"text\", \"pdml\", or \"psml\".\n");
+ exit(1);
}
break;
case 'v': /* Show version and exit */
@@ -1528,6 +1529,26 @@ main(int argc, char *argv[])
}
cfile.rfcode = rfcode;
+ if (print_packet_info) {
+ /* If we're printing as text or PostScript, we have
+ to create a print stream. */
+ if (output_action == WRITE_TEXT) {
+ switch (print_format) {
+
+ case PR_FMT_TEXT:
+ print_stream = print_stream_text_stdio_new(stdout);
+ break;
+
+ case PR_FMT_PS:
+ print_stream = print_stream_ps_stdio_new(stdout);
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+ }
+ }
+
/* We have to dissect each packet if:
we're printing information about each packet;
@@ -2344,8 +2365,7 @@ load_cap_file(capture_file *cf, int out_file_type)
goto out;
}
} else {
- write_preamble(cf);
- if (ferror(stdout)) {
+ if (!write_preamble(cf)) {
err = errno;
show_print_file_io_error(err);
goto out;
@@ -2407,8 +2427,7 @@ load_cap_file(capture_file *cf, int out_file_type)
if (!wtap_dump_close(pdh, &err))
show_capture_file_io_error(cfile.save_file, err, TRUE);
} else {
- write_finale();
- if (ferror(stdout)) {
+ if (!write_finale()) {
err = errno;
show_print_file_io_error(err);
}
@@ -2671,13 +2690,13 @@ show_capture_file_io_error(const char *fname, int err, gboolean is_close)
}
}
-static void
+static gboolean
write_preamble(capture_file *cf)
{
switch (output_action) {
case WRITE_TEXT:
- print_preamble(stdout, print_format, cf->filename);
+ return print_preamble(print_stream, cf->filename);
break;
case WRITE_XML:
@@ -2685,15 +2704,29 @@ write_preamble(capture_file *cf)
write_pdml_preamble(stdout);
else
write_psml_preamble(stdout);
- break;
+ return !ferror(stdout);
+
+ default:
+ g_assert_not_reached();
+ return FALSE;
}
}
-static void
+static gboolean
print_columns(capture_file *cf)
{
+ static char *line_bufp = NULL;
+ static size_t line_buf_len = 0;
int i;
+ size_t buf_offset;
+ size_t column_len;
+ if (line_bufp == NULL) {
+ line_buf_len = 256;
+ line_bufp = g_malloc(line_buf_len + 1);
+ }
+ buf_offset = 0;
+ *line_bufp = '\0';
for (i = 0; i < cf->cinfo.num_cols; i++) {
switch (cf->cinfo.col_fmt[i]) {
case COL_NUMBER:
@@ -2710,14 +2743,28 @@ print_columns(capture_file *cf)
*/
if (cf->iface != NULL)
continue;
- printf("%3s", cf->cinfo.col_data[i]);
+ column_len = strlen(cf->cinfo.col_data[i]);
+ if (column_len < 3)
+ column_len = 3;
+ if (buf_offset + column_len > line_buf_len) {
+ line_buf_len *= 2;
+ line_bufp = g_realloc(line_bufp, line_buf_len + 1);
+ }
+ snprintf(line_bufp + buf_offset, COL_MAX_LEN+1, "%3s", cf->cinfo.col_data[i]);
break;
case COL_CLS_TIME:
case COL_REL_TIME:
case COL_ABS_TIME:
case COL_ABS_DATE_TIME: /* XXX - wider */
- printf("%10s", cf->cinfo.col_data[i]);
+ column_len = strlen(cf->cinfo.col_data[i]);
+ if (column_len < 10)
+ column_len = 10;
+ if (buf_offset + column_len > line_buf_len) {
+ line_buf_len *= 2;
+ line_bufp = g_realloc(line_bufp, line_buf_len + 1);
+ }
+ snprintf(line_bufp + buf_offset, COL_MAX_LEN+1, "%10s", cf->cinfo.col_data[i]);
break;
case COL_DEF_SRC:
@@ -2729,7 +2776,14 @@ print_columns(capture_file *cf)
case COL_DEF_NET_SRC:
case COL_RES_NET_SRC:
case COL_UNRES_NET_SRC:
- printf("%12s", cf->cinfo.col_data[i]);
+ column_len = strlen(cf->cinfo.col_data[i]);
+ if (column_len < 12)
+ column_len = 12;
+ if (buf_offset + column_len > line_buf_len) {
+ line_buf_len *= 2;
+ line_bufp = g_realloc(line_bufp, line_buf_len + 1);
+ }
+ snprintf(line_bufp + buf_offset, COL_MAX_LEN+1, "%12s", cf->cinfo.col_data[i]);
break;
case COL_DEF_DST:
@@ -2741,13 +2795,26 @@ print_columns(capture_file *cf)
case COL_DEF_NET_DST:
case COL_RES_NET_DST:
case COL_UNRES_NET_DST:
- printf("%-12s", cf->cinfo.col_data[i]);
+ column_len = strlen(cf->cinfo.col_data[i]);
+ if (column_len < 12)
+ column_len = 12;
+ if (buf_offset + column_len > line_buf_len) {
+ line_buf_len *= 2;
+ line_bufp = g_realloc(line_bufp, line_buf_len + 1);
+ }
+ snprintf(line_bufp + buf_offset, COL_MAX_LEN+1, "%-12s", cf->cinfo.col_data[i]);
break;
default:
- printf("%s", cf->cinfo.col_data[i]);
+ column_len = strlen(cf->cinfo.col_data[i]);
+ if (buf_offset + column_len > line_buf_len) {
+ line_buf_len *= 2;
+ line_bufp = g_realloc(line_bufp, line_buf_len + 1);
+ }
+ strcat(line_bufp + buf_offset, cf->cinfo.col_data[i]);
break;
}
+ buf_offset += column_len;
if (i != cf->cinfo.num_cols - 1) {
/*
* This isn't the last column, so we need to print a
@@ -2759,7 +2826,14 @@ print_columns(capture_file *cf)
* and are printing a network source of the same type
* next, separate them with "<-"; otherwise separate them
* with a space.
+ *
+ * We add enough space to the buffer for " <- " or " -> ",
+ * even if we're only adding " ".
*/
+ if (buf_offset + 4 > line_buf_len) {
+ line_buf_len *= 2;
+ line_bufp = g_realloc(line_bufp, line_buf_len + 1);
+ }
switch (cf->cinfo.col_fmt[i]) {
case COL_DEF_SRC:
@@ -2770,11 +2844,13 @@ print_columns(capture_file *cf)
case COL_DEF_DST:
case COL_RES_DST:
case COL_UNRES_DST:
- printf(" -> ");
+ strcat(line_bufp + buf_offset, " -> ");
+ buf_offset += 4;
break;
default:
- putchar(' ');
+ strcat(line_bufp + buf_offset, " ");
+ buf_offset += 1;
break;
}
break;
@@ -2787,11 +2863,13 @@ print_columns(capture_file *cf)
case COL_DEF_DL_DST:
case COL_RES_DL_DST:
case COL_UNRES_DL_DST:
- printf(" -> ");
+ strcat(line_bufp + buf_offset, " -> ");
+ buf_offset += 4;
break;
default:
- putchar(' ');
+ strcat(line_bufp + buf_offset, " ");
+ buf_offset += 1;
break;
}
break;
@@ -2804,11 +2882,13 @@ print_columns(capture_file *cf)
case COL_DEF_NET_DST:
case COL_RES_NET_DST:
case COL_UNRES_NET_DST:
- printf(" -> ");
+ strcat(line_bufp + buf_offset, " -> ");
+ buf_offset += 4;
break;
default:
- putchar(' ');
+ strcat(line_bufp + buf_offset, " ");
+ buf_offset += 1;
break;
}
break;
@@ -2821,11 +2901,13 @@ print_columns(capture_file *cf)
case COL_DEF_SRC:
case COL_RES_SRC:
case COL_UNRES_SRC:
- printf(" <- ");
+ strcat(line_bufp + buf_offset, " <- ");
+ buf_offset += 4;
break;
default:
- putchar(' ');
+ strcat(line_bufp + buf_offset, " ");
+ buf_offset += 1;
break;
}
break;
@@ -2838,11 +2920,13 @@ print_columns(capture_file *cf)
case COL_DEF_DL_SRC:
case COL_RES_DL_SRC:
case COL_UNRES_DL_SRC:
- printf(" <- ");
+ strcat(line_bufp + buf_offset, " <- ");
+ buf_offset += 4;
break;
default:
- putchar(' ');
+ strcat(line_bufp + buf_offset, " ");
+ buf_offset += 1;
break;
}
break;
@@ -2855,25 +2939,28 @@ print_columns(capture_file *cf)
case COL_DEF_NET_SRC:
case COL_RES_NET_SRC:
case COL_UNRES_NET_SRC:
- printf(" <- ");
+ strcat(line_bufp + buf_offset, " <- ");
+ buf_offset += 4;
break;
default:
- putchar(' ');
+ strcat(line_bufp + buf_offset, " ");
+ buf_offset += 1;
break;
}
break;
default:
- putchar(' ');
+ strcat(line_bufp + buf_offset, " ");
+ buf_offset += 1;
break;
}
}
}
- putchar('\n');
+ return print_line(print_stream, 0, line_bufp);
}
-static void
+static gboolean
print_packet(capture_file *cf, epan_dissect_t *edt)
{
print_args_t print_args;
@@ -2893,18 +2980,21 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
/* init the packet range */
packet_range_init(&print_args.range);
- proto_tree_print(&print_args, edt, stdout);
+ if (!proto_tree_print(&print_args, edt, print_stream))
+ return FALSE;
+ if (!print_hex) {
+ /* "print_hex_data()" will put out a leading blank line, as well
+ as a trailing one; print one here, to separate the packets,
+ only if "print_hex_data()" won't be called. */
+ if (!print_line(print_stream, 0, ""))
+ return FALSE;
+ }
break;
case WRITE_XML:
proto_tree_write_pdml(edt, stdout);
- break;
- }
- if (!print_hex) {
- /* "print_hex_data()" will put out a leading blank line, as well
- as a trailing one; print one here, to separate the packets,
- only if "print_hex_data()" won't be called. */
printf("\n");
+ return !ferror(stdout);
}
} else {
/* Just fill in the columns. */
@@ -2914,27 +3004,31 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
switch (output_action) {
case WRITE_TEXT:
- print_columns(cf);
+ if (!print_columns(cf))
+ return FALSE;
break;
case WRITE_XML:
proto_tree_write_psml(edt, stdout);
- break;
+ return !ferror(stdout);
}
}
if (print_hex) {
- print_hex_data(stdout, print_format, edt);
- putchar('\n');
+ if (!print_hex_data(print_stream, edt))
+ return FALSE;
+ if (!print_line(print_stream, 0, ""))
+ return FALSE;
}
+ return TRUE;
}
-static void
+static gboolean
write_finale(void)
{
switch (output_action) {
case WRITE_TEXT:
- print_finale(stdout, print_format);
+ return print_finale(print_stream);
break;
case WRITE_XML:
@@ -2942,7 +3036,11 @@ write_finale(void)
write_pdml_finale(stdout);
else
write_psml_finale(stdout);
- break;
+ return !ferror(stdout);
+
+ default:
+ g_assert_not_reached();
+ return FALSE;
}
}