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