safe_read and full_write + join patch
[platform/upstream/coreutils.git] / src / cat.c
1 /* cat -- concatenate files and print on the standard output.
2    Copyright (C) 1988, 1990, 1991 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
17 \f
18 /* Differences from the Unix cat:
19    * Always unbuffered, -u is ignored.
20    * 100 times faster with -v -u.
21    * 20 times faster with -v.
22
23    By tege@sics.se, Torbjorn Granlund, advised by rms, Richard Stallman. */
24
25 #ifdef HAVE_CONFIG_H
26 #if defined (CONFIG_BROKETS)
27 /* We use <config.h> instead of "config.h" so that a compilation
28    using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
29    (which it would do because it found this file in $srcdir).  */
30 #include <config.h>
31 #else
32 #include "config.h"
33 #endif
34 #endif
35
36 #include <stdio.h>
37 #include <getopt.h>
38 #include <sys/types.h>
39 #ifndef _POSIX_SOURCE
40 #include <sys/ioctl.h>
41 #endif
42 #include "system.h"
43 #include "version.h"
44
45 #define max(h,i) ((h) > (i) ? (h) : (i))
46
47 char *stpcpy ();
48 char *xmalloc ();
49 void error ();
50 int full_write ();
51 int safe_read ();
52
53 static void cat ();
54 static void next_line_num ();
55 static void simple_cat ();
56
57 /* Name under which this program was invoked.  */
58 char *program_name;
59
60 /* Name of input file.  May be "-".  */
61 static char *infile;
62
63 /* Descriptor on which input file is open.  */
64 static int input_desc;
65
66 /* Descriptor on which output file is open.  Always is 1.  */
67 static int output_desc;
68
69 /* Buffer for line numbers.  */
70 static char line_buf[13] =
71 {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', '\t', '\0'};
72
73 /* Position in `line_buf' where printing starts.  This will not change
74    unless the number of lines are more than 999999.  */
75 static char *line_num_print = line_buf + 5;
76
77 /* Position of the first digit in `line_buf'.  */
78 static char *line_num_start = line_buf + 10;
79
80 /* Position of the last digit in `line_buf'.  */
81 static char *line_num_end = line_buf + 10;
82
83 /* Preserves the `cat' function's local `newlines' between invocations.  */
84 static int newlines2 = 0;
85
86 /* Count of non-fatal error conditions.  */
87 static int exit_stat = 0;
88
89 static void
90 usage (status)
91      int status;
92 {
93   if (status != 0)
94     fprintf (stderr, "Try `%s --help' for more information.\n",
95              program_name);
96   else
97     {
98       printf ("\
99 Usage: %s [OPTION] [FILE]...\n\
100 ",
101               program_name);
102       printf ("\
103 \n\
104   -b, --number-nonblank    number nonblank output lines\n\
105   -e                       equivalent to -vE\n\
106   -n, --number             number all output lines\n\
107   -s, --squeeze-blank      never more than one single blank line\n\
108   -t                       equivalent to -vT\n\
109   -u                       (ignored)\n\
110   -v, --show-nonprinting   use ^ and M- notation, save for LFD and TAB\n\
111   -A, --show-all           equivalent to -vET\n\
112   -E, --show-ends          display $ at end of each line\n\
113   -T, --show-tabs          display TAB characters as ^I\n\
114       --help               display this help and exit\n\
115       --version            output version information and exit\n\
116 \n\
117 With no FILE, or when FILE is -, read standard input.\n\
118 ");
119     }
120   exit (status);
121 }
122
123 \f
124 void
125 main (argc, argv)
126      int argc;
127      char *argv[];
128 {
129   /* Optimal size of i/o operations of output.  */
130   int outsize;
131
132   /* Optimal size of i/o operations of input.  */
133   int insize;
134
135   /* Pointer to the input buffer.  */
136   unsigned char *inbuf;
137
138   /* Pointer to the output buffer.  */
139   unsigned char *outbuf;
140
141   int c;
142
143   /* Index in argv to processed argument.  */
144   int argind;
145
146   /* Device number of the output (file or whatever).  */
147   int out_dev;
148
149   /* I-node number of the output.  */
150   int out_ino;
151
152   /* Nonzero if the output file should not be the same as any input file. */
153   int check_redirection = 1;
154
155   /* Nonzero if we have ever read standard input. */
156   int have_read_stdin = 0;
157
158   struct stat stat_buf;
159
160   /* Variables that are set according to the specified options.  */
161   int numbers = 0;
162   int numbers_at_empty_lines = 1;
163   int squeeze_empty_lines = 0;
164   int mark_line_ends = 0;
165   int quote = 0;
166   int output_tabs = 1;
167
168 /* If non-zero, call cat, otherwise call simple_cat to do the actual work. */
169   int options = 0;
170
171   /* If non-zero, display usage information and exit.  */
172   static int show_help;
173
174   /* If non-zero, print the version on standard output then exit.  */
175   static int show_version;
176
177   static struct option const long_options[] =
178   {
179     {"number-nonblank", no_argument, NULL, 'b'},
180     {"number", no_argument, NULL, 'n'},
181     {"squeeze-blank", no_argument, NULL, 's'},
182     {"show-nonprinting", no_argument, NULL, 'v'},
183     {"show-ends", no_argument, NULL, 'E'},
184     {"show-tabs", no_argument, NULL, 'T'},
185     {"show-all", no_argument, NULL, 'A'},
186     {"help", no_argument, &show_help, 1},
187     {"version", no_argument, &show_version, 1},
188     {NULL, 0, NULL, 0}
189   };
190
191   program_name = argv[0];
192
193   /* Parse command line options.  */
194
195   while ((c = getopt_long (argc, argv, "benstuvAET", long_options, (int *) 0))
196          != EOF)
197     {
198       switch (c)
199         {
200         case 0:
201           break;
202
203         case 'b':
204           ++options;
205           numbers = 1;
206           numbers_at_empty_lines = 0;
207           break;
208
209         case 'e':
210           ++options;
211           mark_line_ends = 1;
212           quote = 1;
213           break;
214
215         case 'n':
216           ++options;
217           numbers = 1;
218           break;
219
220         case 's':
221           ++options;
222           squeeze_empty_lines = 1;
223           break;
224
225         case 't':
226           ++options;
227           output_tabs = 0;
228           quote = 1;
229           break;
230
231         case 'u':
232           /* We provide the -u feature unconditionally.  */
233           break;
234
235         case 'v':
236           ++options;
237           quote = 1;
238           break;
239
240         case 'A':
241           ++options;
242           quote = 1;
243           mark_line_ends = 1;
244           output_tabs = 0;
245           break;
246
247         case 'E':
248           ++options;
249           mark_line_ends = 1;
250           break;
251
252         case 'T':
253           ++options;
254           output_tabs = 0;
255           break;
256
257         default:
258           usage (2);
259         }
260     }
261
262   if (show_version)
263     {
264       printf ("%s\n", version_string);
265       exit (0);
266     }
267
268   if (show_help)
269     usage (0);
270
271   output_desc = 1;
272
273   /* Get device, i-node number, and optimal blocksize of output.  */
274
275   if (fstat (output_desc, &stat_buf) < 0)
276     error (1, errno, "standard output");
277
278   outsize = ST_BLKSIZE (stat_buf);
279   /* Input file can be output file for non-regular files.
280      fstat on pipes returns S_IFSOCK on some systems, S_IFIFO
281      on others, so the checking should not be done for those types,
282      and to allow things like cat < /dev/tty > /dev/tty, checking
283      is not done for device files either. */
284
285   if (S_ISREG (stat_buf.st_mode))
286     {
287       out_dev = stat_buf.st_dev;
288       out_ino = stat_buf.st_ino;
289     }
290   else
291     check_redirection = 0;
292
293   /* Check if any of the input files are the same as the output file.  */
294
295   /* Main loop.  */
296
297   infile = "-";
298   argind = optind;
299
300   do
301     {
302       if (argind < argc)
303         infile = argv[argind];
304
305       if (infile[0] == '-' && infile[1] == 0)
306         {
307           have_read_stdin = 1;
308           input_desc = 0;
309         }
310       else
311         {
312           input_desc = open (infile, O_RDONLY);
313           if (input_desc < 0)
314             {
315               error (0, errno, "%s", infile);
316               exit_stat = 1;
317               continue;
318             }
319         }
320
321       if (fstat (input_desc, &stat_buf) < 0)
322         {
323           error (0, errno, "%s", infile);
324           exit_stat = 1;
325           goto contin;
326         }
327       insize = ST_BLKSIZE (stat_buf);
328
329       /* Compare the device and i-node numbers of this input file with
330          the corresponding values of the (output file associated with)
331          stdout, and skip this input file if they coincide.  Input
332          files cannot be redirected to themselves.  */
333
334       if (check_redirection
335           && stat_buf.st_dev == out_dev && stat_buf.st_ino == out_ino)
336         {
337           error (0, 0, "%s: input file is output file", infile);
338           exit_stat = 1;
339           goto contin;
340         }
341
342       /* Select which version of `cat' to use. If any options (more than -u,
343          --version, or --help) were specified, use `cat', otherwise use
344          `simple_cat'.  */
345
346       if (options == 0)
347         {
348           insize = max (insize, outsize);
349           inbuf = (unsigned char *) xmalloc (insize);
350
351           simple_cat (inbuf, insize);
352         }
353       else
354         {
355           inbuf = (unsigned char *) xmalloc (insize + 1);
356
357           /* Why are (OUTSIZE  - 1 + INSIZE * 4 + 13) bytes allocated for
358              the output buffer?
359
360              A test whether output needs to be written is done when the input
361              buffer empties or when a newline appears in the input.  After
362              output is written, at most (OUTSIZE - 1) bytes will remain in the
363              buffer.  Now INSIZE bytes of input is read.  Each input character
364              may grow by a factor of 4 (by the prepending of M-^).  If all
365              characters do, and no newlines appear in this block of input, we
366              will have at most (OUTSIZE - 1 + INSIZE) bytes in the buffer.  If
367              the last character in the preceding block of input was a
368              newline, a line number may be written (according to the given
369              options) as the first thing in the output buffer. (Done after the
370              new input is read, but before processing of the input begins.)  A
371              line number requires seldom more than 13 positions.  */
372
373           outbuf = (unsigned char *) xmalloc (outsize - 1 + insize * 4 + 13);
374
375           cat (inbuf, insize, outbuf, outsize, quote,
376                output_tabs, numbers, numbers_at_empty_lines, mark_line_ends,
377                squeeze_empty_lines);
378
379           free (outbuf);
380         }
381
382       free (inbuf);
383
384     contin:
385       if (strcmp (infile, "-") && close (input_desc) < 0)
386         {
387           error (0, errno, "%s", infile);
388           exit_stat = 1;
389         }
390     }
391   while (++argind < argc);
392
393   if (have_read_stdin && close (0) < 0)
394     error (1, errno, "-");
395   if (close (1) < 0)
396     error (1, errno, "write error");
397
398   exit (exit_stat);
399 }
400 \f
401 /* Plain cat.  Copies the file behind `input_desc' to the file behind
402    `output_desc'.  */
403
404 static void
405 simple_cat (buf, bufsize)
406      /* Pointer to the buffer, used by reads and writes.  */
407      unsigned char *buf;
408
409      /* Number of characters preferably read or written by each read and write
410         call.  */
411      int bufsize;
412 {
413   /* Actual number of characters read, and therefore written.  */
414   int n_read;
415
416   /* Loop until the end of the file.  */
417
418   for (;;)
419     {
420       /* Read a block of input.  */
421
422       n_read = safe_read (input_desc, buf, bufsize);
423       if (n_read < 0)
424         {
425           error (0, errno, "%s", infile);
426           exit_stat = 1;
427           return;
428         }
429
430       /* End of this file?  */
431
432       if (n_read == 0)
433         break;
434
435       /* Write this block out.  */
436
437       if (full_write (output_desc, buf, n_read) < 0)
438         error (1, errno, "write error");
439     }
440 }
441 \f
442 /* Cat the file behind INPUT_DESC to the file behind OUTPUT_DESC.
443    Called if any option more than -u was specified.
444
445    A newline character is always put at the end of the buffer, to make
446    an explicit test for buffer end unnecessary.  */
447
448 static void
449 cat (inbuf, insize, outbuf, outsize, quote,
450      output_tabs, numbers, numbers_at_empty_lines,
451      mark_line_ends, squeeze_empty_lines)
452
453      /* Pointer to the beginning of the input buffer.  */
454      unsigned char *inbuf;
455
456      /* Number of characters read in each read call.  */
457      int insize;
458
459      /* Pointer to the beginning of the output buffer.  */
460      unsigned char *outbuf;
461
462      /* Number of characters written by each write call.  */
463      int outsize;
464
465      /* Variables that have values according to the specified options.  */
466      int quote;
467      int output_tabs;
468      int numbers;
469      int numbers_at_empty_lines;
470      int mark_line_ends;
471      int squeeze_empty_lines;
472 {
473   /* Last character read from the input buffer.  */
474   unsigned char ch;
475
476   /* Pointer to the next character in the input buffer.  */
477   unsigned char *bpin;
478
479   /* Pointer to the first non-valid byte in the input buffer, i.e. the
480      current end of the buffer.  */
481   unsigned char *eob;
482
483   /* Pointer to the position where the next character shall be written.  */
484   unsigned char *bpout;
485
486   /* Number of characters read by the last read call.  */
487   int n_read;
488
489   /* Determines how many consecutive newlines there have been in the
490      input.  0 newlines makes NEWLINES -1, 1 newline makes NEWLINES 1,
491      etc.  Initially 0 to indicate that we are at the beginning of a
492      new line.  The "state" of the procedure is determined by
493      NEWLINES.  */
494   int newlines = newlines2;
495
496 #ifdef FIONREAD
497   /* If nonzero, use the FIONREAD ioctl, as an optimization.
498      (On Ultrix, it is not supported on NFS filesystems.)  */
499   int use_fionread = 1;
500 #endif
501
502   /* The inbuf pointers are initialized so that BPIN > EOB, and thereby input
503      is read immediately.  */
504
505   eob = inbuf;
506   bpin = eob + 1;
507
508   bpout = outbuf;
509
510   for (;;)
511     {
512       do
513         {
514           /* Write if there are at least OUTSIZE bytes in OUTBUF.  */
515
516           if (bpout - outbuf >= outsize)
517             {
518               unsigned char *wp = outbuf;
519               do
520                 {
521                   if (full_write (output_desc, wp, outsize) < 0)
522                     error (1, errno, "write error");
523                   wp += outsize;
524                 }
525               while (bpout - wp >= outsize);
526
527               /* Move the remaining bytes to the beginning of the
528                  buffer.  */
529
530               bcopy (wp, outbuf, bpout - wp);
531               bpout = outbuf + (bpout - wp);
532             }
533
534           /* Is INBUF empty?  */
535
536           if (bpin > eob)
537             {
538 #ifdef FIONREAD
539               int n_to_read = 0;
540
541               /* Is there any input to read immediately?
542                  If not, we are about to wait,
543                  so write all buffered output before waiting.  */
544
545               if (use_fionread
546                   && ioctl (input_desc, FIONREAD, &n_to_read) < 0)
547                 {
548                   /* Ultrix returns EOPNOTSUPP on NFS;
549                      HP-UX returns ENOTTY on pipes.
550                      SunOS returns EINVAL and
551                      More/BSD returns ENODEV on special files
552                      like /dev/null.  */
553                   if (errno == EOPNOTSUPP || errno == ENOTTY
554                       || errno == EINVAL || errno == ENODEV)
555                     use_fionread = 0;
556                   else
557                     {
558                       error (0, errno, "cannot do ioctl on `%s'", infile);
559                       exit_stat = 1;
560                       newlines2 = newlines;
561                       return;
562                     }
563                 }
564               if (n_to_read == 0)
565 #endif
566                 {
567                   int n_write = bpout - outbuf;
568
569                   if (full_write (output_desc, outbuf, n_write) < 0)
570                     error (1, errno, "write error");
571                   bpout = outbuf;
572                 }
573
574               /* Read more input into INBUF.  */
575
576               n_read = safe_read (input_desc, inbuf, insize);
577               if (n_read < 0)
578                 {
579                   error (0, errno, "%s", infile);
580                   exit_stat = 1;
581                   newlines2 = newlines;
582                   return;
583                 }
584               if (n_read == 0)
585                 {
586                   newlines2 = newlines;
587                   return;
588                 }
589
590               /* Update the pointers and insert a sentinel at the buffer
591                  end.  */
592
593               bpin = inbuf;
594               eob = bpin + n_read;
595               *eob = '\n';
596             }
597           else
598             {
599               /* It was a real (not a sentinel) newline.  */
600
601               /* Was the last line empty?
602                  (i.e. have two or more consecutive newlines been read?)  */
603
604               if (++newlines > 0)
605                 {
606                   /* Are multiple adjacent empty lines to be substituted by
607                      single ditto (-s), and this was the second empty line?  */
608
609                   if (squeeze_empty_lines && newlines >= 2)
610                     {
611                       ch = *bpin++;
612                       continue;
613                     }
614
615                   /* Are line numbers to be written at empty lines (-n)?  */
616
617                   if (numbers && numbers_at_empty_lines)
618                     {
619                       next_line_num ();
620                       bpout = (unsigned char *) stpcpy (bpout, line_num_print);
621                     }
622                 }
623
624               /* Output a currency symbol if requested (-e).  */
625
626               if (mark_line_ends)
627                 *bpout++ = '$';
628
629               /* Output the newline.  */
630
631               *bpout++ = '\n';
632             }
633           ch = *bpin++;
634         }
635       while (ch == '\n');
636
637       /* Are we at the beginning of a line, and line numbers are requested?  */
638
639       if (newlines >= 0 && numbers)
640         {
641           next_line_num ();
642           bpout = (unsigned char *) stpcpy (bpout, line_num_print);
643         }
644
645       /* Here CH cannot contain a newline character.  */
646
647       /* The loops below continue until a newline character is found,
648          which means that the buffer is empty or that a proper newline
649          has been found.  */
650
651       /* If quoting, i.e. at least one of -v, -e, or -t specified,
652          scan for chars that need conversion.  */
653       if (quote)
654         for (;;)
655           {
656             if (ch >= 32)
657               {
658                 if (ch < 127)
659                   *bpout++ = ch;
660                 else if (ch == 127)
661                   *bpout++ = '^',
662                     *bpout++ = '?';
663                 else
664                   {
665                     *bpout++ = 'M',
666                       *bpout++ = '-';
667                     if (ch >= 128 + 32)
668                       if (ch < 128 + 127)
669                         *bpout++ = ch - 128;
670                       else
671                         *bpout++ = '^',
672                           *bpout++ = '?';
673                     else
674                       *bpout++ = '^',
675                         *bpout++ = ch - 128 + 64;
676                   }
677               }
678             else if (ch == '\t' && output_tabs)
679               *bpout++ = '\t';
680             else if (ch == '\n')
681               {
682                 newlines = -1;
683                 break;
684               }
685             else
686               *bpout++ = '^',
687                 *bpout++ = ch + 64;
688
689             ch = *bpin++;
690           }
691       else
692         /* Not quoting, neither of -v, -e, or -t specified.  */
693         for (;;)
694           {
695             if (ch == '\t' && !output_tabs)
696               *bpout++ = '^',
697                 *bpout++ = ch + 64;
698             else if (ch != '\n')
699               *bpout++ = ch;
700             else
701               {
702                 newlines = -1;
703                 break;
704               }
705
706             ch = *bpin++;
707           }
708     }
709 }
710
711 /* Compute the next line number.  */
712
713 static void
714 next_line_num ()
715 {
716   char *endp = line_num_end;
717   do
718     {
719       if ((*endp)++ < '9')
720         return;
721       *endp-- = '0';
722     }
723   while (endp >= line_num_start);
724   *--line_num_start = '1';
725   if (line_num_start < line_num_print)
726     line_num_print--;
727 }