merge with 1.5
[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     fprintf (stderr, "%s\n", version_string);
229
230   if (flag_help)
231     usage ();
232
233   output_desc = 1;
234
235   /* Get device, i-node number, and optimal blocksize of output.  */
236
237   if (fstat (output_desc, &stat_buf) < 0)
238     error (1, errno, "standard output");
239
240   outsize = ST_BLKSIZE (stat_buf);
241   /* Input file can be output file for non-regular files.
242      fstat on pipes returns S_IFSOCK on some systems, S_IFIFO
243      on others, so the checking should not be done for those types,
244      and to allow things like cat < /dev/tty > /dev/tty, checking
245      is not done for device files either. */
246
247   if (S_ISREG (stat_buf.st_mode))
248     {
249       out_dev = stat_buf.st_dev;
250       out_ino = stat_buf.st_ino;
251     }
252   else
253     check_redirection = 0;
254
255   /* Check if any of the input files are the same as the output file.  */
256
257   /* Main loop.  */
258
259   infile = "-";
260   argind = optind;
261
262   do
263     {
264       if (argind < argc)
265         infile = argv[argind];
266
267       if (infile[0] == '-' && infile[1] == 0)
268         {
269           have_read_stdin = 1;
270           input_desc = 0;
271         }
272       else
273         {
274           input_desc = open (infile, O_RDONLY);
275           if (input_desc < 0)
276             {
277               error (0, errno, "%s", infile);
278               exit_stat = 1;
279               continue;
280             }
281         }
282
283       if (fstat (input_desc, &stat_buf) < 0)
284         {
285           error (0, errno, "%s", infile);
286           exit_stat = 1;
287           goto contin;
288         }
289       insize = ST_BLKSIZE (stat_buf);
290
291       /* Compare the device and i-node numbers of this input file with
292          the corresponding values of the (output file associated with)
293          stdout, and skip this input file if they coincide.  Input
294          files cannot be redirected to themselves.  */
295
296       if (check_redirection
297           && stat_buf.st_dev == out_dev && stat_buf.st_ino == out_ino)
298         {
299           error (0, 0, "%s: input file is output file", infile);
300           exit_stat = 1;
301           goto contin;
302         }
303
304       /* Select which version of `cat' to use. If any options (more than -u,
305          --version, or --help) were specified, use `cat', otherwise use
306          `simple_cat'.  */
307
308       if (options == 0)
309         {
310           insize = max (insize, outsize);
311           inbuf = (unsigned char *) xmalloc (insize);
312
313           simple_cat (inbuf, insize);
314         }
315       else
316         {
317           inbuf = (unsigned char *) xmalloc (insize + 1);
318
319           /* Why are (OUTSIZE  - 1 + INSIZE * 4 + 13) bytes allocated for
320              the output buffer?
321
322              A test whether output needs to be written is done when the input
323              buffer empties or when a newline appears in the input.  After
324              output is written, at most (OUTSIZE - 1) bytes will remain in the
325              buffer.  Now INSIZE bytes of input is read.  Each input character
326              may grow by a factor of 4 (by the prepending of M-^).  If all
327              characters do, and no newlines appear in this block of input, we
328              will have at most (OUTSIZE - 1 + INSIZE) bytes in the buffer.  If
329              the last character in the preceding block of input was a
330              newline, a line number may be written (according to the given
331              options) as the first thing in the output buffer. (Done after the
332              new input is read, but before processing of the input begins.)  A
333              line number requires seldom more than 13 positions.  */
334
335           outbuf = (unsigned char *) xmalloc (outsize - 1 + insize * 4 + 13);
336
337           cat (inbuf, insize, outbuf, outsize, quote,
338                output_tabs, numbers, numbers_at_empty_lines, mark_line_ends,
339                squeeze_empty_lines);
340
341           free (outbuf);
342         }
343
344       free (inbuf);
345
346     contin:
347       if (strcmp (infile, "-") && close (input_desc) < 0)
348         {
349           error (0, errno, "%s", infile);
350           exit_stat = 1;
351         }
352     }
353   while (++argind < argc);
354
355   if (have_read_stdin && close (0) < 0)
356     error (1, errno, "-");
357   if (close (1) < 0)
358     error (1, errno, "write error");
359
360   exit (exit_stat);
361 }
362 \f
363 /* Plain cat.  Copies the file behind `input_desc' to the file behind
364    `output_desc'.  */
365
366 static void
367 simple_cat (buf, bufsize)
368      /* Pointer to the buffer, used by reads and writes.  */
369      unsigned char *buf;
370
371      /* Number of characters preferably read or written by each read and write
372         call.  */
373      int bufsize;
374 {
375   /* Actual number of characters read, and therefore written.  */
376   int n_read;
377
378   /* Loop until the end of the file.  */
379
380   for (;;)
381     {
382       /* Read a block of input.  */
383
384       n_read = read (input_desc, buf, bufsize);
385       if (n_read < 0)
386         {
387           error (0, errno, "%s", infile);
388           exit_stat = 1;
389           return;
390         }
391
392       /* End of this file?  */
393
394       if (n_read == 0)
395         break;
396
397       /* Write this block out.  */
398
399       if (write (output_desc, buf, n_read) != n_read)
400         error (1, errno, "write error");
401     }
402 }
403 \f
404 /* Cat the file behind INPUT_DESC to the file behind OUTPUT_DESC.
405    Called if any option more than -u was specified.
406
407    A newline character is always put at the end of the buffer, to make
408    an explicit test for buffer end unnecessary.  */
409
410 static void
411 cat (inbuf, insize, outbuf, outsize, quote,
412      output_tabs, numbers, numbers_at_empty_lines,
413      mark_line_ends, squeeze_empty_lines)
414
415      /* Pointer to the beginning of the input buffer.  */
416      unsigned char *inbuf;
417
418      /* Number of characters read in each read call.  */
419      int insize;
420
421      /* Pointer to the beginning of the output buffer.  */
422      unsigned char *outbuf;
423
424      /* Number of characters written by each write call.  */
425      int outsize;
426
427      /* Variables that have values according to the specified options.  */
428      int quote;
429      int output_tabs;
430      int numbers;
431      int numbers_at_empty_lines;
432      int mark_line_ends;
433      int squeeze_empty_lines;
434 {
435   /* Last character read from the input buffer.  */
436   unsigned char ch;
437
438   /* Pointer to the next character in the input buffer.  */
439   unsigned char *bpin;
440
441   /* Pointer to the first non-valid byte in the input buffer, i.e. the
442      current end of the buffer.  */
443   unsigned char *eob;
444
445   /* Pointer to the position where the next character shall be written.  */
446   unsigned char *bpout;
447
448   /* Number of characters read by the last read call.  */
449   int n_read;
450
451   /* Determines how many consecutive newlines there have been in the
452      input.  0 newlines makes NEWLINES -1, 1 newline makes NEWLINES 1,
453      etc.  Initially 0 to indicate that we are at the beginning of a
454      new line.  The "state" of the procedure is determined by
455      NEWLINES.  */
456   int newlines = newlines2;
457
458 #ifdef FIONREAD
459   /* If nonzero, use the FIONREAD ioctl, as an optimization.
460      (On Ultrix, it is not supported on NFS filesystems.)  */
461   int use_fionread = 1;
462 #endif
463
464   /* The inbuf pointers are initialized so that BPIN > EOB, and thereby input
465      is read immediately.  */
466
467   eob = inbuf;
468   bpin = eob + 1;
469
470   bpout = outbuf;
471
472   for (;;)
473     {
474       do
475         {
476           /* Write if there are at least OUTSIZE bytes in OUTBUF.  */
477
478           if (bpout - outbuf >= outsize)
479             {
480               unsigned char *wp = outbuf;
481               do
482                 {
483                   if (write (output_desc, wp, outsize) != outsize)
484                     error (1, errno, "write error");
485                   wp += outsize;
486                 }
487               while (bpout - wp >= outsize);
488
489               /* Move the remaining bytes to the beginning of the
490                  buffer.  */
491
492               bcopy (wp, outbuf, bpout - wp);
493               bpout = outbuf + (bpout - wp);
494             }
495
496           /* Is INBUF empty?  */
497
498           if (bpin > eob)
499             {
500 #ifdef FIONREAD
501               int n_to_read = 0;
502
503               /* Is there any input to read immediately?
504                  If not, we are about to wait,
505                  so write all buffered output before waiting.  */
506
507               if (use_fionread
508                   && ioctl (input_desc, FIONREAD, &n_to_read) < 0)
509                 {
510                   /* Ultrix returns EOPNOTSUPP on NFS;
511                      HP-UX returns ENOTTY on pipes. */
512                   if (errno == EOPNOTSUPP || errno == ENOTTY)
513                     use_fionread = 0;
514                   else
515                     {
516                       error (0, errno, "cannot do ioctl on `%s'", infile);
517                       exit_stat = 1;
518                       newlines2 = newlines;
519                       return;
520                     }
521                 }
522               if (n_to_read == 0)
523 #endif
524                 {
525                   int n_write = bpout - outbuf;
526
527                   if (write (output_desc, outbuf, n_write) != n_write)
528                     error (1, errno, "write error");
529                   bpout = outbuf;
530                 }
531
532               /* Read more input into INBUF.  */
533
534               n_read = read (input_desc, inbuf, insize);
535               if (n_read < 0)
536                 {
537                   error (0, errno, "%s", infile);
538                   exit_stat = 1;
539                   newlines2 = newlines;
540                   return;
541                 }
542               if (n_read == 0)
543                 {
544                   newlines2 = newlines;
545                   return;
546                 }
547
548               /* Update the pointers and insert a sentinel at the buffer
549                  end.  */
550
551               bpin = inbuf;
552               eob = bpin + n_read;
553               *eob = '\n';
554             }
555           else
556             {
557               /* It was a real (not a sentinel) newline.  */
558
559               /* Was the last line empty?
560                  (i.e. have two or more consecutive newlines been read?)  */
561
562               if (++newlines > 0)
563                 {
564                   /* Are multiple adjacent empty lines to be substituted by
565                      single ditto (-s), and this was the second empty line?  */
566
567                   if (squeeze_empty_lines && newlines >= 2)
568                     {
569                       ch = *bpin++;
570                       continue;
571                     }
572
573                   /* Are line numbers to be written at empty lines (-n)?  */
574
575                   if (numbers && numbers_at_empty_lines)
576                     {
577                       next_line_num ();
578                       bpout = (unsigned char *) stpcpy (bpout, line_num_print);
579                     }
580                 }
581
582               /* Output a currency symbol if requested (-e).  */
583
584               if (mark_line_ends)
585                 *bpout++ = '$';
586
587               /* Output the newline.  */
588
589               *bpout++ = '\n';
590             }
591           ch = *bpin++;
592         }
593       while (ch == '\n');
594
595       /* Are we at the beginning of a line, and line numbers are requested?  */
596
597       if (newlines >= 0 && numbers)
598         {
599           next_line_num ();
600           bpout = (unsigned char *) stpcpy (bpout, line_num_print);
601         }
602
603       /* Here CH cannot contain a newline character.  */
604
605       /* The loops below continue until a newline character is found,
606          which means that the buffer is empty or that a proper newline
607          has been found.  */
608
609       /* If quoting, i.e. at least one of -v, -e, or -t specified,
610          scan for chars that need conversion.  */
611       if (quote)
612         for (;;)
613           {
614             if (ch >= 32)
615               {
616                 if (ch < 127)
617                   *bpout++ = ch;
618                 else if (ch == 127)
619                   *bpout++ = '^',
620                     *bpout++ = '?';
621                 else
622                   {
623                     *bpout++ = 'M',
624                       *bpout++ = '-';
625                     if (ch >= 128 + 32)
626                       if (ch < 128 + 127)
627                         *bpout++ = ch - 128;
628                       else
629                         *bpout++ = '^',
630                           *bpout++ = '?';
631                     else
632                       *bpout++ = '^',
633                         *bpout++ = ch - 128 + 64;
634                   }
635               }
636             else if (ch == '\t' && output_tabs)
637               *bpout++ = '\t';
638             else if (ch == '\n')
639               {
640                 newlines = -1;
641                 break;
642               }
643             else
644               *bpout++ = '^',
645                 *bpout++ = ch + 64;
646
647             ch = *bpin++;
648           }
649       else
650         /* Not quoting, neither of -v, -e, or -t specified.  */
651         for (;;)
652           {
653             if (ch == '\t' && !output_tabs)
654               *bpout++ = '^',
655                 *bpout++ = ch + 64;
656             else if (ch != '\n')
657               *bpout++ = ch;
658             else
659               {
660                 newlines = -1;
661                 break;
662               }
663
664             ch = *bpin++;
665           }
666     }
667 }
668
669 /* Compute the next line number.  */
670
671 static void
672 next_line_num ()
673 {
674   char *endp = line_num_end;
675   do
676     {
677       if ((*endp)++ < '9')
678         return;
679       *endp-- = '0';
680     }
681   while (endp >= line_num_start);
682   *--line_num_start = '1';
683   if (line_num_start < line_num_print)
684     line_num_print--;
685 }