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