home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / cat / cat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-23  |  6.1 KB  |  278 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Kevin Fall.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. char copyright[] =
  39. "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
  40.  All rights reserved.\n";
  41. #endif /* not lint */
  42.  
  43. #ifndef lint
  44. static char sccsid[] = "@(#)cat.c    5.15 (Berkeley) 5/23/91";
  45. #endif /* not lint */
  46.  
  47. #include <sys/param.h>
  48. #include <sys/stat.h>
  49. #include <fcntl.h>
  50. #include <errno.h>
  51. #include <unistd.h>
  52. #include <stdio.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <ctype.h>
  56.  
  57. int bflag, eflag, nflag, sflag, tflag, vflag;
  58. int rval;
  59. char *filename;
  60.  
  61. void cook_args(), cook_buf(), raw_args(), raw_cat();
  62. void err __P((int, const char *, ...));
  63.  
  64. main(argc, argv)
  65.     int argc;
  66.     char **argv;
  67. {
  68.     extern int optind;
  69.     int ch;
  70.  
  71.     while ((ch = getopt(argc, argv, "benstuv")) != EOF)
  72.         switch (ch) {
  73.         case 'b':
  74.             bflag = nflag = 1;    /* -b implies -n */
  75.             break;
  76.         case 'e':
  77.             eflag = vflag = 1;    /* -e implies -v */
  78.             break;
  79.         case 'n':
  80.             nflag = 1;
  81.             break;
  82.         case 's':
  83.             sflag = 1;
  84.             break;
  85.         case 't':
  86.             tflag = vflag = 1;    /* -t implies -v */
  87.             break;
  88.         case 'u':
  89.             setbuf(stdout, (char *)NULL);
  90.             break;
  91.         case 'v':
  92.             vflag = 1;
  93.             break;
  94.         case '?':
  95.             (void)fprintf(stderr,
  96.                 "usage: cat [-benstuv] [-] [file ...]\n");
  97.             exit(1);
  98.         }
  99.     argv += optind;
  100.  
  101.     if (bflag || eflag || nflag || sflag || tflag || vflag)
  102.         cook_args(argv);
  103.     else
  104.         raw_args(argv);
  105.     if (fclose(stdout))
  106.         err(1, "stdout: %s", strerror(errno));
  107.     exit(rval);
  108. }
  109.  
  110. void
  111. cook_args(argv)
  112.     char **argv;
  113. {
  114.     register FILE *fp;
  115.  
  116.     fp = stdin;
  117.     filename = "stdin";
  118.     do {
  119.         if (*argv) {
  120.             if (!strcmp(*argv, "-"))
  121.                 fp = stdin;
  122.             else if (!(fp = fopen(*argv, "r"))) {
  123.                 err(0, "%s: %s", *argv, strerror(errno));
  124.                 ++argv;
  125.                 continue;
  126.             }
  127.             filename = *argv++;
  128.         }
  129.         cook_buf(fp);
  130.         if (fp != stdin)
  131.             (void)fclose(fp);
  132.     } while (*argv);
  133. }
  134.  
  135. void
  136. cook_buf(fp)
  137.     register FILE *fp;
  138. {
  139.     register int ch, gobble, line, prev;
  140.  
  141.     line = gobble = 0;
  142.     for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
  143.         if (prev == '\n') {
  144.             if (ch == '\n') {
  145.                 if (sflag) {
  146.                     if (!gobble && putchar(ch) == EOF)
  147.                         break;
  148.                     gobble = 1;
  149.                     continue;
  150.                 }
  151.                 if (nflag && !bflag) {
  152.                     (void)fprintf(stdout, "%6d\t", ++line);
  153.                     if (ferror(stdout))
  154.                         break;
  155.                 }
  156.             } else if (nflag) {
  157.                 (void)fprintf(stdout, "%6d\t", ++line);
  158.                 if (ferror(stdout))
  159.                     break;
  160.             }
  161.         }
  162.         gobble = 0;
  163.         if (ch == '\n') {
  164.             if (eflag)
  165.                 if (putchar('$') == EOF)
  166.                     break;
  167.         } else if (ch == '\t') {
  168.             if (tflag) {
  169.                 if (putchar('^') == EOF || putchar('I') == EOF)
  170.                     break;
  171.                 continue;
  172.             }
  173.         } else if (vflag) {
  174.             if (!isascii(ch)) {
  175.                 if (putchar('M') == EOF || putchar('-') == EOF)
  176.                     break;
  177.                 ch = toascii(ch);
  178.             }
  179.             if (iscntrl(ch)) {
  180.                 if (putchar('^') == EOF ||
  181.                     putchar(ch == '\177' ? '?' :
  182.                     ch | 0100) == EOF)
  183.                     break;
  184.                 continue;
  185.             }
  186.         }
  187.         if (putchar(ch) == EOF)
  188.             break;
  189.     }
  190.     if (ferror(fp)) {
  191.         err(0, "%s: %s", strerror(errno));
  192.         clearerr(fp);
  193.     }
  194.     if (ferror(stdout))
  195.         err(1, "stdout: %s", strerror(errno));
  196. }
  197.  
  198. void
  199. raw_args(argv)
  200.     char **argv;
  201. {
  202.     register int fd;
  203.  
  204.     fd = fileno(stdin);
  205.     filename = "stdin";
  206.     do {
  207.         if (*argv) {
  208.             if (!strcmp(*argv, "-"))
  209.                 fd = fileno(stdin);
  210.             else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
  211.                 err(0, "%s: %s", *argv, strerror(errno));
  212.                 ++argv;
  213.                 continue;
  214.             }
  215.             filename = *argv++;
  216.         }
  217.         raw_cat(fd);
  218.         if (fd != fileno(stdin))
  219.             (void)close(fd);
  220.     } while (*argv);
  221. }
  222.  
  223. void
  224. raw_cat(rfd)
  225.     register int rfd;
  226. {
  227.     register int nr, nw, off, wfd;
  228.     static int bsize;
  229.     static char *buf;
  230.     struct stat sbuf;
  231.  
  232.     wfd = fileno(stdout);
  233.     if (!buf) {
  234.         if (fstat(wfd, &sbuf))
  235.             err(1, "%s: %s", filename, strerror(errno));
  236.         bsize = MAX(sbuf.st_blksize, 1024);
  237.         if (!(buf = malloc((u_int)bsize)))
  238.             err(1, "%s", strerror(errno));
  239.     }
  240.     while ((nr = read(rfd, buf, bsize)) > 0)
  241.         for (off = 0; off < nr; nr -= nw, off += nw)
  242.             if ((nw = write(wfd, buf + off, nr)) < 0)
  243.                 err(1, "stdout");
  244.     if (nr < 0)
  245.         err(0, "%s: %s", filename, strerror(errno));
  246. }
  247.  
  248. #if __STDC__
  249. #include <stdarg.h>
  250. #else
  251. #include <varargs.h>
  252. #endif
  253.  
  254. void
  255. #if __STDC__
  256. err(int ex, const char *fmt, ...)
  257. #else
  258. err(ex, fmt, va_alist)
  259.     int ex;
  260.     char *fmt;
  261.         va_dcl
  262. #endif
  263. {
  264.     va_list ap;
  265. #if __STDC__
  266.     va_start(ap, fmt);
  267. #else
  268.     va_start(ap);
  269. #endif
  270.     (void)fprintf(stderr, "cat: ");
  271.     (void)vfprintf(stderr, fmt, ap);
  272.     va_end(ap);
  273.     (void)fprintf(stderr, "\n");
  274.     if (ex)
  275.         exit(1);
  276.     rval = 1;
  277. }
  278.