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