From: Devan Lai Date: Fri, 11 Oct 2019 03:16:01 +0000 (-0700) Subject: Set stdout to binary mode on Windows as needed X-Git-Url: https://sigrok.org/gitweb/?p=sigrok-cli.git;a=commitdiff_plain;h=e8a9eb8d33617a5210a1c10d1855a8482bd85080 Set stdout to binary mode on Windows as needed On Windows, stdout defaults to text mode, which attempts to perform newline conversion such that if it sees a bare line feed (hex 0A), it will insert a carriage return (hex 0D) before the line feed. For textual output like normal annotation display or ASCII art, this is desirable, but for binary output, this is likely to garble the output. On Windows when using stdout as the output file destination or when using the -B/--protocol-decoder-binary option, change the mode of stdout to _O_BINARY to disable this newline conversion to ensure that the binary output is faithfully delivered to stdout without modifications. On all other platforms, setup_binary_stdout() is a no-op. This fixes the original issue in bug #1427. Further follow-up work might be needed to fix the reverse behavior that is introduced by this change - now textual output sent to stdout on Windows will only have Unix style line endings, rather than being converted to Windows style line endings. --- diff --git a/Makefile.am b/Makefile.am index 84f94b4..d5cc780 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,6 +30,7 @@ sigrok_cli_SOURCES = \ device.c \ session.c \ input.c \ + output.c \ decode.c \ sigrok-cli.h \ parsers.c \ diff --git a/main.c b/main.c index 829492f..c2f39d8 100644 --- a/main.c +++ b/main.c @@ -242,6 +242,8 @@ int main(int argc, char **argv) if (opt_pd_binary) { if (setup_pd_binary(opt_pd_binary) != 0) goto done; + if (setup_binary_stdout() != 0) + goto done; if (srd_pd_output_callback_add(srd_sess, SRD_OUTPUT_BINARY, show_pd_binary, NULL) != SRD_OK) goto done; diff --git a/output.c b/output.c new file mode 100644 index 0000000..051ec8b --- /dev/null +++ b/output.c @@ -0,0 +1,41 @@ +/* + * This file is part of the sigrok-cli project. + * + * Copyright (C) 2019 Devan Lai + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#ifdef _WIN32 +#include +#include +#endif + +#include +#include "sigrok-cli.h" + +/* Disable newline translation on stdout when outputting binary data. */ +int setup_binary_stdout(void) +{ +#ifdef _WIN32 + int oldmode = _setmode(_fileno(stdout), _O_BINARY); + if (oldmode == -1) { + g_critical("Failed to set binary stdout mode: errno=%d", errno); + return -1; + } +#endif + return 0; +} diff --git a/session.c b/session.c index 3b3e962..f154235 100644 --- a/session.c +++ b/session.c @@ -117,6 +117,7 @@ const struct sr_output *setup_output_format(const struct sr_dev_inst *sdi, FILE *outfile = NULL; } } else { + setup_binary_stdout(); *outfile = stdout; } diff --git a/sigrok-cli.h b/sigrok-cli.h index 7def741..8d26699 100644 --- a/sigrok-cli.h +++ b/sigrok-cli.h @@ -82,6 +82,9 @@ void run_session(void); /* input.c */ void load_input_file(gboolean do_props); +/* output.c */ +int setup_binary_stdout(void); + /* decode.c */ #ifdef HAVE_SRD int register_pds(gchar **all_pds, char *opt_pd_annotations);