diff --git a/doc/man/sieve-dump.1.in b/doc/man/sieve-dump.1.in index 10c381c8744d9afcd9f5a9d10b58c6468b96701d..d553b5a299ee25b681d3b6d9d84c61552d53acc7 100644 --- a/doc/man/sieve-dump.1.in +++ b/doc/man/sieve-dump.1.in @@ -40,6 +40,10 @@ the binary. .BI \-c\ config\-file Alternative Dovecot configuration file path. .TP +.B \-h +Produce per-block hexdump output of the whole binary instead of the normal +human-readable output. +.TP .BI \-x\ extensions Set the available extensions. The parameter is a space\-separated list of the active extensions. By prepending the extension identifiers with \fB+\fP or diff --git a/src/lib-sieve-tool/sieve-tool.c b/src/lib-sieve-tool/sieve-tool.c index 80dca2e6c60cb72ac130ed9bb337c83802253268..359ab715dbbd2efd97260a6926be5a8a2a9dad9d 100644 --- a/src/lib-sieve-tool/sieve-tool.c +++ b/src/lib-sieve-tool/sieve-tool.c @@ -547,7 +547,8 @@ struct sieve_binary *sieve_tool_script_open return sbin; } -void sieve_tool_dump_binary_to(struct sieve_binary *sbin, const char *filename) +void sieve_tool_dump_binary_to +(struct sieve_binary *sbin, const char *filename, bool hexdump) { struct ostream *dumpstream; @@ -555,7 +556,10 @@ void sieve_tool_dump_binary_to(struct sieve_binary *sbin, const char *filename) dumpstream = sieve_tool_open_output_stream(filename); if ( dumpstream != NULL ) { - (void) sieve_dump(sbin, dumpstream, FALSE); + if ( hexdump ) + (void) sieve_hexdump(sbin, dumpstream); + else + (void) sieve_dump(sbin, dumpstream, FALSE); o_stream_destroy(&dumpstream); } else { i_fatal("Failed to create stream for sieve code dump."); diff --git a/src/lib-sieve-tool/sieve-tool.h b/src/lib-sieve-tool/sieve-tool.h index da1e4a91fcea40dfe3ddff0647cd8de32c1f461c..ec0365049ee91f625e6594441f2d1d83679090ca 100644 --- a/src/lib-sieve-tool/sieve-tool.h +++ b/src/lib-sieve-tool/sieve-tool.h @@ -87,7 +87,7 @@ struct sieve_binary *sieve_tool_script_compile struct sieve_binary *sieve_tool_script_open (struct sieve_instance *svinst, const char *filename); void sieve_tool_dump_binary_to - (struct sieve_binary *sbin, const char *filename); + (struct sieve_binary *sbin, const char *filename, bool hexdump); /* * Command line option parsing diff --git a/src/lib-sieve/sieve-binary-dumper.c b/src/lib-sieve/sieve-binary-dumper.c index f86a861ac2da9376b4d7303d550295763eb96c92..d1812e5b4b325cb3d2052cf35de357adb3c9fc05 100644 --- a/src/lib-sieve/sieve-binary-dumper.c +++ b/src/lib-sieve/sieve-binary-dumper.c @@ -4,13 +4,15 @@ #include "lib.h" #include "str.h" #include "ostream.h" +#include "array.h" +#include "buffer.h" #include "sieve-common.h" #include "sieve-extensions.h" -#include "sieve-binary.h" - #include "sieve-dump.h" +#include "sieve-binary-private.h" + /* * Binary dumper object */ @@ -180,3 +182,91 @@ bool sieve_binary_dumper_run return TRUE; } + +/* + * Hexdump production + */ + +void sieve_binary_dumper_hexdump +(struct sieve_binary_dumper *dumper, struct ostream *stream) +{ + struct sieve_binary *sbin = dumper->dumpenv.sbin; + struct sieve_dumptime_env *denv = &(dumper->dumpenv); + int count, i; + + dumper->dumpenv.stream = stream; + + count = sieve_binary_block_count(sbin); + + /* Block overview */ + + sieve_binary_dump_sectionf + (denv, "Binary blocks (count: %d)", count); + + for ( i = 0; i < count; i++ ) { + struct sieve_binary_block *sblock = sieve_binary_block_get(sbin, i); + + sieve_binary_dumpf(denv, + "%3d: size: %"PRIuSIZE_T" bytes\n", i, + sieve_binary_block_get_size(sblock)); + } + + /* Hexdump for each block */ + + for ( i = 0; i < count; i++ ) { + struct sieve_binary_block *sblock = sieve_binary_block_get(sbin, i); + buffer_t *blockbuf = sieve_binary_block_get_buffer(sblock); + string_t *line; + size_t data_size; + const char *data; + size_t offset; + + data = (const char *) buffer_get_data(blockbuf, &data_size); + + sieve_binary_dump_sectionf + (denv, "Block %d (%"PRIuSIZE_T" bytes, file offset %08llx)", i, + data_size, sblock->offset + 8 /* header size (yuck) */); + + line = t_str_new(128); + offset = 0; + while ( offset < data_size ) { + size_t len = ( data_size - offset >= 16 ? 16 : data_size - offset ); + size_t b; + + str_printfa(line, "%08llx ", (unsigned long long) offset); + + for ( b = 0; b < len; b++ ) { + str_printfa(line, "%02x ", (unsigned int) data[offset+b]); + if ( b == 7 ) str_append_c(line, ' '); + } + + if ( len < 16 ) { + if ( len <= 7 ) str_append_c(line, ' '); + + for ( b = len; b < 16; b++ ) { + str_append(line, " "); + } + } + + str_append(line, " |"); + + for ( b = 0; b < len; b++ ) { + const char c = data[offset+b]; + + if ( c >= 32 && c <= 126 ) + str_append_c(line, c); + else + str_append_c(line, '.'); + } + + str_append(line, "|\n"); + o_stream_send(stream, str_data(line), str_len(line)); + str_truncate(line, 0); + offset += len; + } + + str_printfa(line, "%08llx\n", (unsigned long long) offset); + o_stream_send(stream, str_data(line), str_len(line)); + } +} + diff --git a/src/lib-sieve/sieve-binary-dumper.h b/src/lib-sieve/sieve-binary-dumper.h index 24238963a4ea1adfe56f3fc6cd4de26ffa4f1501..dda7bfa0b0166812fbcd00e7f2962384294aefd6 100644 --- a/src/lib-sieve/sieve-binary-dumper.h +++ b/src/lib-sieve/sieve-binary-dumper.h @@ -36,5 +36,11 @@ void sieve_binary_dump_sectionf bool sieve_binary_dumper_run (struct sieve_binary_dumper *dumper, struct ostream *stream, bool verbose); +/* + * Hexdump production + */ + +void sieve_binary_dumper_hexdump +(struct sieve_binary_dumper *dumper, struct ostream *stream); #endif /* __SIEVE_BINARY_DUMPER_H */ diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h index d33754ca4859dc20190e55e253666c8d49d6b21f..cd45da71ef7af40f8c3fb6eb1f6f962bd8271cbf 100644 --- a/src/lib-sieve/sieve-binary.h +++ b/src/lib-sieve/sieve-binary.h @@ -257,7 +257,6 @@ struct sieve_binary_debug_reader *sieve_binary_debug_reader_init void sieve_binary_debug_reader_deinit (struct sieve_binary_debug_reader **dreader); - void sieve_binary_debug_reader_reset (struct sieve_binary_debug_reader *dreader); diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 3c0caef11344b4824724877f7ae56b75ecb0724e..b93b46d781b4ae4c609cef7f2cc7ac6d2f258f70 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -397,7 +397,8 @@ void sieve_close(struct sieve_binary **sbin) * Debugging */ -void sieve_dump(struct sieve_binary *sbin, struct ostream *stream, bool verbose) +void sieve_dump +(struct sieve_binary *sbin, struct ostream *stream, bool verbose) { struct sieve_binary_dumper *dumpr = sieve_binary_dumper_create(sbin); @@ -406,6 +407,16 @@ void sieve_dump(struct sieve_binary *sbin, struct ostream *stream, bool verbose) sieve_binary_dumper_free(&dumpr); } +void sieve_hexdump +(struct sieve_binary *sbin, struct ostream *stream) +{ + struct sieve_binary_dumper *dumpr = sieve_binary_dumper_create(sbin); + + sieve_binary_dumper_hexdump(dumpr, stream); + + sieve_binary_dumper_free(&dumpr); +} + int sieve_test (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, struct sieve_error_handler *ehandler, diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h index ac58cf77ba98a1634d0fc8f51676d913725d16e9..50db0cbd023455e5731931a9df6446433c13fd76 100644 --- a/src/lib-sieve/sieve.h +++ b/src/lib-sieve/sieve.h @@ -119,7 +119,16 @@ bool sieve_is_loaded(struct sieve_binary *sbin); * * Dumps the byte code in human-readable form to the specified ostream. */ -void sieve_dump(struct sieve_binary *sbin, struct ostream *stream, bool verbose); +void sieve_dump + (struct sieve_binary *sbin, struct ostream *stream, bool verbose); + +/* sieve_hexdump: + * + * Dumps the byte code in hexdump form to the specified ostream. + */ + +void sieve_hexdump + (struct sieve_binary *sbin, struct ostream *stream); /* sieve_test: * diff --git a/src/sieve-tools/sieve-dump.c b/src/sieve-tools/sieve-dump.c index 1e9d8a0046ca375250ed0c6f31c668b17a72768e..17f8118977698f52e763ce74223e8ecd9ce7d126 100644 --- a/src/sieve-tools/sieve-dump.c +++ b/src/sieve-tools/sieve-dump.c @@ -30,7 +30,7 @@ static void print_help(void) { printf( -"Usage: sieve-dump [-P <plugin>] [-x <extensions>]\n" +"Usage: sieve-dump [-h] [-P <plugin>] [-x <extensions>]\n" " <sieve-binary> [<out-file>]\n" ); } @@ -44,16 +44,25 @@ int main(int argc, char **argv) struct sieve_instance *svinst; struct sieve_binary *sbin; const char *binfile, *outfile; + bool hexdump = FALSE; int exit_status = EXIT_SUCCESS; int c; - sieve_tool = sieve_tool_init("sieve-dump", &argc, &argv, "P:x:", FALSE); + sieve_tool = sieve_tool_init("sieve-dump", &argc, &argv, "hP:x:", FALSE); binfile = outfile = NULL; - if ( (c = sieve_tool_getopt(sieve_tool)) > 0 ) { - print_help(); - i_fatal_status(EX_USAGE, "Unknown argument: %c", c); + while ((c = sieve_tool_getopt(sieve_tool)) > 0) { + switch (c) { + case 'h': + /* produce hexdump */ + hexdump = TRUE; + break; + default: + print_help(); + i_fatal_status(EX_USAGE, "Unknown argument: %c", c); + break; + } } if ( optind < argc ) { @@ -76,7 +85,7 @@ int main(int argc, char **argv) /* Dump binary */ sbin = sieve_load(svinst, binfile, NULL); if ( sbin != NULL ) { - sieve_tool_dump_binary_to(sbin, outfile == NULL ? "-" : outfile); + sieve_tool_dump_binary_to(sbin, outfile == NULL ? "-" : outfile, hexdump); sieve_close(&sbin); } else { diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c index fdf8a89756311b001e86a8473bf5fb1990a86de7..b9ca7601bcd32b962b877ca5b990997e7940e149 100644 --- a/src/sieve-tools/sieve-test.c +++ b/src/sieve-tools/sieve-test.c @@ -224,7 +224,7 @@ int main(int argc, char **argv) exit_status = EXIT_FAILURE; } else { /* Dump script */ - sieve_tool_dump_binary_to(main_sbin, dumpfile); + sieve_tool_dump_binary_to(main_sbin, dumpfile, FALSE); /* Obtain mail namespaces from -l argument */ if ( mailloc != NULL ) { diff --git a/src/sieve-tools/sievec.c b/src/sieve-tools/sievec.c index 40c97e27ee31104121f2d399f61f63bd607447d9..f93d3447c4944b596e63eadd2513ca4dbc9300cf 100644 --- a/src/sieve-tools/sievec.c +++ b/src/sieve-tools/sievec.c @@ -143,7 +143,7 @@ int main(int argc, char **argv) if ( sbin != NULL ) { if ( dump ) - sieve_tool_dump_binary_to(sbin, outfile); + sieve_tool_dump_binary_to(sbin, outfile, FALSE); else { sieve_save(sbin, outfile, TRUE, NULL); } diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c index 2ff4d3a2956b305e2bbac9d11b9bc47177944ce0..5d688aab8e37fb4a0d56fdfc3aa94bbb3f44be90 100644 --- a/src/testsuite/testsuite.c +++ b/src/testsuite/testsuite.c @@ -170,7 +170,7 @@ int main(int argc, char **argv) struct sieve_script_env scriptenv; /* Dump script */ - sieve_tool_dump_binary_to(sbin, dumpfile); + sieve_tool_dump_binary_to(sbin, dumpfile, FALSE); if ( tracefile != NULL ) tracestream = sieve_tool_open_output_stream(tracefile);