summaryrefslogtreecommitdiff
path: root/src/cat.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1999-01-01 22:20:23 +0000
committerJim Meyering <jim@meyering.net>1999-01-01 22:20:23 +0000
commit7914fb4069f2c56e29eecd98b75fa9c278d90022 (patch)
tree6533b7d09633fc0b6f273a5acb613e993df96a2a /src/cat.c
parente6e8ae14c9f007a91b206f09624e7423beadec13 (diff)
downloadcoreutils-7914fb4069f2c56e29eecd98b75fa9c278d90022.tar.xz
(usage) [O_BINARY]: Describe -B,--binary option.
(main) [O_BINARY]: binary_files, binary_output, file_open_mode: new variables. Add --binary to long_options[]. Switch stdin and stdout to binary mode unless file contents are not important anyway. Open files in binary mode when required.
Diffstat (limited to 'src/cat.c')
-rw-r--r--src/cat.c93
1 files changed, 90 insertions, 3 deletions
diff --git a/src/cat.c b/src/cat.c
index 5d0bc01a7..a278a951f 100644
--- a/src/cat.c
+++ b/src/cat.c
@@ -1,5 +1,5 @@
/* cat -- concatenate files and print on the standard output.
- Copyright (C) 88, 90, 91, 95, 96, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 88, 90, 91, 1995-1998, 1999 Free Software Foundation, Inc.
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
@@ -102,6 +102,12 @@ Concatenate FILE(s), or standard input, to standard output.\n\
\n\
With no FILE, or when FILE is -, read standard input.\n\
"));
+#if O_BINARY
+ printf (_("\
+\n\
+ -B, --binary use binary writes to the console device.\n\n\
+"));
+#endif
puts (_("\nReport bugs to <bug-textutils@gnu.org>."));
}
exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
@@ -495,6 +501,11 @@ main (int argc, char **argv)
int mark_line_ends = 0;
int quote = 0;
int output_tabs = 1;
+#if O_BINARY
+ int binary_files = 0;
+ int binary_output = 0;
+#endif
+ int file_open_mode = O_RDONLY;
/* If nonzero, call cat, otherwise call simple_cat to do the actual work. */
int options = 0;
@@ -514,6 +525,9 @@ main (int argc, char **argv)
{"show-ends", no_argument, NULL, 'E'},
{"show-tabs", no_argument, NULL, 'T'},
{"show-all", no_argument, NULL, 'A'},
+#if O_BINARY
+ {"binary", no_argument, NULL, 'B'},
+#endif
{"help", no_argument, &show_help, 1},
{"version", no_argument, &show_version, 1},
{NULL, 0, NULL, 0}
@@ -526,7 +540,13 @@ main (int argc, char **argv)
/* Parse command line options. */
- while ((c = getopt_long (argc, argv, "benstuvAET", long_options, NULL)) != -1)
+ while ((c = getopt_long (argc, argv,
+#if O_BINARY
+ "benstuvABET"
+#else
+ "benstuvAET"
+#endif
+ , long_options, NULL)) != -1)
{
switch (c)
{
@@ -577,6 +597,13 @@ main (int argc, char **argv)
output_tabs = 0;
break;
+#if O_BINARY
+ case 'B':
+ ++options;
+ binary_files = 1;
+ break;
+#endif
+
case 'E':
++options;
mark_line_ends = 1;
@@ -629,6 +656,39 @@ main (int argc, char **argv)
#endif
}
+#if O_BINARY
+ /* We always read and write in BINARY mode, since this is the
+ best way to copy the files verbatim. Exceptions are when
+ they request line numbering, squeezing of empty lines or
+ marking lines' ends: then we use text I/O, because otherwise
+ -b, -s and -E would surprise users on DOS/Windows where a line
+ with only CR-LF is an empty line. (Besides, if they ask for
+ one of these options, they don't care much about the original
+ file contents anyway). */
+ if ((!isatty (output_desc)
+ && !(numbers || squeeze_empty_lines || mark_line_ends))
+ || binary_files)
+ {
+ /* Switch stdout to BINARY mode. */
+ binary_output = 1;
+ SET_BINARY (output_desc);
+ }
+ else if (quote)
+ {
+ /* If they want to see the non-printables, let's show them
+ those CR characters as well, so make the input binary.
+ But keep console output in text mode, so that LF causes
+ both CR and LF on output, and the output is readable. */
+ file_open_mode |= O_BINARY;
+ SET_BINARY (0);
+
+ /* Setting stdin to binary switches the console device to
+ raw I/O, which also affects stdout to console. Undo that. */
+ if (isatty (output_desc))
+ setmode (output_desc, O_TEXT);
+ }
+#endif
+
/* Check if any of the input files are the same as the output file. */
/* Main loop. */
@@ -645,10 +705,37 @@ main (int argc, char **argv)
{
have_read_stdin = 1;
input_desc = 0;
+
+#if O_BINARY
+ /* Switch stdin to BINARY mode if needed. */
+ if (binary_output)
+ {
+ int tty_in = isatty (input_desc);
+
+ /* If stdin is a terminal device, and it is the ONLY
+ input file (i.e. we didn't write anything to the
+ output yet), switch the output back to TEXT mode.
+ This is so "cat > xyzzy" creates a DOS-style text
+ file, like people expect. */
+ if (tty_in && optind <= argc)
+ setmode (output_desc, O_TEXT);
+ else
+ {
+ SET_BINARY (input_desc);
+# ifdef __DJGPP__
+ /* This is DJGPP-specific. By default, switching console
+ to binary mode disables SIGINT. But we want terminal
+ reads to be interruptible. */
+ if (tty_in)
+ __djgpp_set_ctrl_c (1);
+# endif
+ }
+ }
+#endif
}
else
{
- input_desc = open (infile, O_RDONLY);
+ input_desc = open (infile, file_open_mode);
if (input_desc < 0)
{
error (0, errno, "%s", infile);