GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/cat/cat.c Lines: 81 116 69.8 %
Date: 2017-11-07 Branches: 74 152 48.7 %

Line Branch Exec Source
1
/*	$OpenBSD: cat.c,v 1.26 2016/10/19 18:20:25 schwarze Exp $	*/
2
/*	$NetBSD: cat.c,v 1.11 1995/09/07 06:12:54 jtc Exp $	*/
3
4
/*
5
 * Copyright (c) 1989, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * This code is derived from software contributed to Berkeley by
9
 * Kevin Fall.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the University nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 */
35
36
#include <sys/types.h>
37
#include <sys/stat.h>
38
39
#include <ctype.h>
40
#include <err.h>
41
#include <errno.h>
42
#include <fcntl.h>
43
#include <stdio.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <unistd.h>
47
48
#define MAXIMUM(a, b)	(((a) > (b)) ? (a) : (b))
49
50
extern char *__progname;
51
52
int bflag, eflag, nflag, sflag, tflag, vflag;
53
int rval;
54
char *filename;
55
56
void cook_args(char *argv[]);
57
void cook_buf(FILE *);
58
void raw_args(char *argv[]);
59
void raw_cat(int);
60
61
int
62
main(int argc, char *argv[])
63
{
64
	int ch;
65
66
9104
	if (pledge("stdio rpath flock cpath wpath", NULL) == -1)
67
		err(1, "pledge");
68
69
4660
	while ((ch = getopt(argc, argv, "benstuv")) != -1)
70


108
		switch (ch) {
71
		case 'b':
72
27
			bflag = nflag = 1;	/* -b implies -n */
73
27
			break;
74
		case 'e':
75
54
			eflag = vflag = 1;	/* -e implies -v */
76
54
			break;
77
		case 'n':
78
			nflag = 1;
79
			break;
80
		case 's':
81
27
			sflag = 1;
82
27
			break;
83
		case 't':
84
			tflag = vflag = 1;	/* -t implies -v */
85
			break;
86
		case 'u':
87
			setvbuf(stdout, NULL, _IONBF, 0);
88
			break;
89
		case 'v':
90
			vflag = 1;
91
			break;
92
		default:
93
			(void)fprintf(stderr,
94
			    "usage: %s [-benstuv] [file ...]\n", __progname);
95
			return 1;
96
		}
97
4552
	argv += optind;
98
99
4552
	if (bflag || eflag || nflag || sflag || tflag || vflag)
100
54
		cook_args(argv);
101
	else
102
4498
		raw_args(argv);
103
4552
	if (fclose(stdout))
104
		err(1, "stdout");
105
4552
	return rval;
106
4552
}
107
108
void
109
cook_args(char **argv)
110
{
111
	FILE *fp;
112
113
	fp = stdin;
114
108
	filename = "stdin";
115
54
	do {
116
54
		if (*argv) {
117
54
			if (!strcmp(*argv, "-"))
118
				fp = stdin;
119
54
			else if ((fp = fopen(*argv, "r")) == NULL) {
120
				warn("%s", *argv);
121
				rval = 1;
122
				++argv;
123
				continue;
124
			}
125
54
			filename = *argv++;
126
54
		}
127
54
		cook_buf(fp);
128
54
		if (fp == stdin)
129
			clearerr(fp);
130
		else
131
54
			(void)fclose(fp);
132
54
	} while (*argv);
133
54
}
134
135
void
136
cook_buf(FILE *fp)
137
{
138
	int ch, gobble, line, prev;
139
140
	line = gobble = 0;
141

8424
	for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
142
1620
		if (prev == '\n') {
143
216
			if (sflag) {
144
81
				if (ch == '\n') {
145
54
					if (gobble)
146
						continue;
147
					gobble = 1;
148
54
				} else
149
					gobble = 0;
150
			}
151
216
			if (nflag) {
152
135
				if (!bflag || ch != '\n') {
153
81
					(void)fprintf(stdout, "%6d\t", ++line);
154

162
					if (ferror(stdout))
155
						break;
156
54
				} else if (eflag) {
157
54
					(void)fprintf(stdout, "%6s\t", "");
158

108
					if (ferror(stdout))
159
						break;
160
				}
161
			}
162
		}
163
1620
		if (ch == '\n') {
164

864
			if (eflag && putchar('$') == EOF)
165
				break;
166
1404
		} else if (ch == '\t') {
167
			if (tflag) {
168
				if (putchar('^') == EOF || putchar('I') == EOF)
169
					break;
170
				continue;
171
			}
172
1404
		} else if (vflag) {
173
1404
			if (!isascii(ch)) {
174
				if (putchar('M') == EOF || putchar('-') == EOF)
175
					break;
176
				ch = toascii(ch);
177
			}
178
1404
			if (iscntrl(ch)) {
179
				if (putchar('^') == EOF ||
180
				    putchar(ch == '\177' ? '?' :
181
				    ch | 0100) == EOF)
182
					break;
183
				continue;
184
			}
185
		}
186

4860
		if (putchar(ch) == EOF)
187
			break;
188
	}
189

108
	if (ferror(fp)) {
190
		warn("%s", filename);
191
		rval = 1;
192
		clearerr(fp);
193
	}
194

108
	if (ferror(stdout))
195
		err(1, "stdout");
196
54
}
197
198
void
199
raw_args(char **argv)
200
{
201
	int fd;
202
203
17992
	fd = fileno(stdin);
204
4498
	filename = "stdin";
205
4498
	do {
206
7772
		if (*argv) {
207
5220
			if (!strcmp(*argv, "-"))
208
576
				fd = fileno(stdin);
209
5028
			else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
210
1
				warn("%s", *argv);
211
1
				rval = 1;
212
1
				++argv;
213
1
				continue;
214
			}
215
5219
			filename = *argv++;
216
5219
		}
217
7771
		raw_cat(fd);
218

23313
		if (fd != fileno(stdin))
219
5027
			(void)close(fd);
220
7772
	} while (*argv);
221
4498
}
222
223
void
224
raw_cat(int rfd)
225
{
226
	int wfd;
227
	ssize_t nr, nw, off;
228
	static size_t bsize;
229
	static char *buf = NULL;
230
15542
	struct stat sbuf;
231
232
23313
	wfd = fileno(stdout);
233
7771
	if (buf == NULL) {
234
4497
		if (fstat(wfd, &sbuf))
235
			err(1, "stdout");
236
4497
		bsize = MAXIMUM(sbuf.st_blksize, BUFSIZ);
237
4497
		if ((buf = malloc(bsize)) == NULL)
238
			err(1, "malloc");
239
	}
240
25951
	while ((nr = read(rfd, buf, bsize)) != -1 && nr != 0)
241
72720
		for (off = 0; nr; nr -= nw, off += nw)
242
36360
			if ((nw = write(wfd, buf + off, (size_t)nr)) == 0 ||
243
18180
			     nw == -1)
244
				err(1, "stdout");
245
7771
	if (nr < 0) {
246
		warn("%s", filename);
247
		rval = 1;
248
	}
249
7771
}