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