119840Sdist /*
263892Sbostic * Copyright (c) 1989, 1993
363892Sbostic * The Regents of the University of California. All rights reserved.
437128Sbostic *
537128Sbostic * This code is derived from software contributed to Berkeley by
637128Sbostic * Kevin Fall.
737128Sbostic *
842524Sbostic * %sccs.include.redist.c%
919840Sdist */
1019840Sdist
1114463Ssam #ifndef lint
1263892Sbostic static char copyright[] =
1363892Sbostic "@(#) Copyright (c) 1989, 1993\n\
1463892Sbostic The Regents of the University of California. All rights reserved.\n";
1534079Sbostic #endif /* not lint */
1614463Ssam
1734079Sbostic #ifndef lint
18*68970Sbostic static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 04/27/95";
1934079Sbostic #endif /* not lint */
2034079Sbostic
2137178Sbostic #include <sys/param.h>
2237178Sbostic #include <sys/stat.h>
2358141Sbostic
2458141Sbostic #include <ctype.h>
2558141Sbostic #include <err.h>
2658141Sbostic #include <errno.h>
2748953Sbostic #include <fcntl.h>
28962Sbill #include <stdio.h>
2948953Sbostic #include <stdlib.h>
3048953Sbostic #include <string.h>
3158141Sbostic #include <unistd.h>
32962Sbill
3337179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag;
3437179Sbostic int rval;
3537128Sbostic char *filename;
36962Sbill
3758141Sbostic void cook_args __P((char *argv[]));
3858141Sbostic void cook_buf __P((FILE *));
3958141Sbostic void raw_args __P((char *argv[]));
4058141Sbostic void raw_cat __P((int));
4148953Sbostic
4258141Sbostic int
main(argc,argv)43962Sbill main(argc, argv)
4437128Sbostic int argc;
4558141Sbostic char *argv[];
46962Sbill {
4740268Sbostic extern int optind;
4837179Sbostic int ch;
49962Sbill
50*68970Sbostic while ((ch = getopt(argc, argv, "benstuv")) != -1)
5137128Sbostic switch (ch) {
5237179Sbostic case 'b':
5337179Sbostic bflag = nflag = 1; /* -b implies -n */
54962Sbill break;
5537179Sbostic case 'e':
5637179Sbostic eflag = vflag = 1; /* -e implies -v */
5737179Sbostic break;
5837179Sbostic case 'n':
5937179Sbostic nflag = 1;
6037179Sbostic break;
6137179Sbostic case 's':
6237179Sbostic sflag = 1;
6337179Sbostic break;
6437179Sbostic case 't':
6537179Sbostic tflag = vflag = 1; /* -t implies -v */
6637179Sbostic break;
6737179Sbostic case 'u':
6837179Sbostic setbuf(stdout, (char *)NULL);
6937179Sbostic break;
7037179Sbostic case 'v':
7137179Sbostic vflag = 1;
7237179Sbostic break;
73*68970Sbostic default:
7437128Sbostic case '?':
7537128Sbostic (void)fprintf(stderr,
7637179Sbostic "usage: cat [-benstuv] [-] [file ...]\n");
7737128Sbostic exit(1);
78962Sbill }
7939713Sbostic argv += optind;
8037128Sbostic
8137179Sbostic if (bflag || eflag || nflag || sflag || tflag || vflag)
8237179Sbostic cook_args(argv);
8337179Sbostic else
8437179Sbostic raw_args(argv);
8549212Sbostic if (fclose(stdout))
8658141Sbostic err(1, "stdout");
8737179Sbostic exit(rval);
8837179Sbostic }
8937179Sbostic
9048953Sbostic void
cook_args(argv)9137179Sbostic cook_args(argv)
9237179Sbostic char **argv;
9337179Sbostic {
9437179Sbostic register FILE *fp;
9537179Sbostic
9637179Sbostic fp = stdin;
9749860Sbostic filename = "stdin";
9837179Sbostic do {
9937179Sbostic if (*argv) {
10037179Sbostic if (!strcmp(*argv, "-"))
10137179Sbostic fp = stdin;
10258141Sbostic else if ((fp = fopen(*argv, "r")) == NULL) {
10358141Sbostic warn("%s", *argv);
10437179Sbostic ++argv;
10537179Sbostic continue;
10637179Sbostic }
10737179Sbostic filename = *argv++;
10837179Sbostic }
10937179Sbostic cook_buf(fp);
11037179Sbostic if (fp != stdin)
11137179Sbostic (void)fclose(fp);
11237179Sbostic } while (*argv);
11337179Sbostic }
11437179Sbostic
11548953Sbostic void
cook_buf(fp)11637179Sbostic cook_buf(fp)
11737179Sbostic register FILE *fp;
11837179Sbostic {
11937179Sbostic register int ch, gobble, line, prev;
12037179Sbostic
12137179Sbostic line = gobble = 0;
12237179Sbostic for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
12337179Sbostic if (prev == '\n') {
12437179Sbostic if (ch == '\n') {
12537179Sbostic if (sflag) {
12638900Sbostic if (!gobble && putchar(ch) == EOF)
12738471Sbostic break;
12837179Sbostic gobble = 1;
12938471Sbostic continue;
13037179Sbostic }
13137179Sbostic if (nflag && !bflag) {
13237179Sbostic (void)fprintf(stdout, "%6d\t", ++line);
13337179Sbostic if (ferror(stdout))
13437179Sbostic break;
13537179Sbostic }
13638471Sbostic } else if (nflag) {
13737179Sbostic (void)fprintf(stdout, "%6d\t", ++line);
13837179Sbostic if (ferror(stdout))
13937179Sbostic break;
14037179Sbostic }
14137179Sbostic }
14238471Sbostic gobble = 0;
14337179Sbostic if (ch == '\n') {
14437179Sbostic if (eflag)
14538900Sbostic if (putchar('$') == EOF)
14637179Sbostic break;
14737179Sbostic } else if (ch == '\t') {
14837179Sbostic if (tflag) {
14938900Sbostic if (putchar('^') == EOF || putchar('I') == EOF)
15037179Sbostic break;
15137179Sbostic continue;
15237179Sbostic }
15337179Sbostic } else if (vflag) {
15438900Sbostic if (!isascii(ch)) {
15538900Sbostic if (putchar('M') == EOF || putchar('-') == EOF)
15637179Sbostic break;
15738900Sbostic ch = toascii(ch);
15837179Sbostic }
15937179Sbostic if (iscntrl(ch)) {
16038900Sbostic if (putchar('^') == EOF ||
16138900Sbostic putchar(ch == '\177' ? '?' :
16238900Sbostic ch | 0100) == EOF)
16337179Sbostic break;
16437179Sbostic continue;
16537179Sbostic }
16637179Sbostic }
16738900Sbostic if (putchar(ch) == EOF)
16837179Sbostic break;
16937179Sbostic }
17037179Sbostic if (ferror(fp)) {
17158141Sbostic warn("%s", filename);
17248953Sbostic clearerr(fp);
17337179Sbostic }
17448953Sbostic if (ferror(stdout))
17558141Sbostic err(1, "stdout");
17637179Sbostic }
17737179Sbostic
17848953Sbostic void
raw_args(argv)17937179Sbostic raw_args(argv)
18037179Sbostic char **argv;
18137179Sbostic {
18237179Sbostic register int fd;
18337179Sbostic
18437178Sbostic fd = fileno(stdin);
18549860Sbostic filename = "stdin";
18637128Sbostic do {
18737128Sbostic if (*argv) {
18837178Sbostic if (!strcmp(*argv, "-"))
18937178Sbostic fd = fileno(stdin);
19037178Sbostic else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
19158141Sbostic warn("%s", *argv);
19237128Sbostic ++argv;
1934387Secc continue;
1944387Secc }
19537178Sbostic filename = *argv++;
196962Sbill }
19748953Sbostic raw_cat(fd);
19837178Sbostic if (fd != fileno(stdin))
19937178Sbostic (void)close(fd);
20037128Sbostic } while (*argv);
201962Sbill }
2021357Sbill
20348953Sbostic void
raw_cat(rfd)20448953Sbostic raw_cat(rfd)
20548953Sbostic register int rfd;
20617947Sralph {
20748953Sbostic register int nr, nw, off, wfd;
20837178Sbostic static int bsize;
20937178Sbostic static char *buf;
21037178Sbostic struct stat sbuf;
21117947Sralph
21248953Sbostic wfd = fileno(stdout);
21358141Sbostic if (buf == NULL) {
21448953Sbostic if (fstat(wfd, &sbuf))
21558141Sbostic err(1, "%s", filename);
21637178Sbostic bsize = MAX(sbuf.st_blksize, 1024);
21758141Sbostic if ((buf = malloc((u_int)bsize)) == NULL)
218*68970Sbostic err(1, NULL);
21937178Sbostic }
22048953Sbostic while ((nr = read(rfd, buf, bsize)) > 0)
22163891Sbostic for (off = 0; nr; nr -= nw, off += nw)
22248953Sbostic if ((nw = write(wfd, buf + off, nr)) < 0)
22358141Sbostic err(1, "stdout");
22448953Sbostic if (nr < 0)
22558141Sbostic warn("%s", filename);
22617947Sralph }
227