GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/cat/cat.c Lines: 79 120 65.8 %
Date: 2016-12-06 Branches: 81 174 46.6 %

Line Branch Exec Source
1
/*	$OpenBSD: cat.c,v 1.25 2016/07/01 22:40:44 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 <locale.h>
44
#include <stdio.h>
45
#include <stdlib.h>
46
#include <string.h>
47
#include <unistd.h>
48
49
#define MAXIMUM(a, b)	(((a) > (b)) ? (a) : (b))
50
51
extern char *__progname;
52
53
int bflag, eflag, nflag, sflag, tflag, vflag;
54
int rval;
55
char *filename;
56
57
void cook_args(char *argv[]);
58
void cook_buf(FILE *);
59
void raw_args(char *argv[]);
60
void raw_cat(int);
61
62
int
63
main(int argc, char *argv[])
64
1264
{
65
	int ch;
66
67
1264
	setlocale(LC_ALL, "");
68
69
1264
	if (pledge("stdio rpath wpath cpath", NULL) == -1)
70
		err(1, "pledge");
71
72
1272
	while ((ch = getopt(argc, argv, "benstuv")) != -1)
73


8
		switch (ch) {
74
		case 'b':
75
2
			bflag = nflag = 1;	/* -b implies -n */
76
2
			break;
77
		case 'e':
78
4
			eflag = vflag = 1;	/* -e implies -v */
79
4
			break;
80
		case 'n':
81
			nflag = 1;
82
			break;
83
		case 's':
84
2
			sflag = 1;
85
2
			break;
86
		case 't':
87
			tflag = vflag = 1;	/* -t implies -v */
88
			break;
89
		case 'u':
90
			setvbuf(stdout, NULL, _IONBF, 0);
91
			break;
92
		case 'v':
93
			vflag = 1;
94
			break;
95
		default:
96
			(void)fprintf(stderr,
97
			    "usage: %s [-benstuv] [file ...]\n", __progname);
98
			exit(1);
99
			/* NOTREACHED */
100
		}
101
1264
	argv += optind;
102
103



1268
	if (bflag || eflag || nflag || sflag || tflag || vflag)
104
4
		cook_args(argv);
105
	else
106
1260
		raw_args(argv);
107
1264
	if (fclose(stdout))
108
		err(1, "stdout");
109
1264
	exit(rval);
110
	/* NOTREACHED */
111
}
112
113
void
114
cook_args(char **argv)
115
4
{
116
	FILE *fp;
117
118
4
	fp = stdin;
119
4
	filename = "stdin";
120
	do {
121
4
		if (*argv) {
122
4
			if (!strcmp(*argv, "-"))
123
				fp = stdin;
124
4
			else if ((fp = fopen(*argv, "r")) == NULL) {
125
				warn("%s", *argv);
126
				rval = 1;
127
				++argv;
128
				continue;
129
			}
130
4
			filename = *argv++;
131
		}
132
4
		cook_buf(fp);
133
4
		if (fp == stdin)
134
			clearerr(fp);
135
		else
136
4
			(void)fclose(fp);
137
4
	} while (*argv);
138
4
}
139
140
void
141
cook_buf(FILE *fp)
142
4
{
143
	int ch, gobble, line, prev;
144
145
4
	line = gobble = 0;
146

124
	for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
147
120
		if (prev == '\n') {
148
16
			if (sflag) {
149
6
				if (ch == '\n') {
150
4
					if (gobble)
151
						continue;
152
4
					gobble = 1;
153
				} else
154
2
					gobble = 0;
155
			}
156
16
			if (nflag) {
157
10
				if (!bflag || ch != '\n') {
158
6
					(void)fprintf(stdout, "%6d\t", ++line);
159

6
					if (ferror(stdout))
160
						break;
161
4
				} else if (eflag) {
162
4
					(void)fprintf(stdout, "%6s\t", "");
163

4
					if (ferror(stdout))
164
						break;
165
				}
166
			}
167
		}
168
120
		if (ch == '\n') {
169

16
			if (eflag && putchar('$') == EOF)
170
				break;
171
104
		} else if (ch == '\t') {
172
			if (tflag) {
173
				if (putchar('^') == EOF || putchar('I') == EOF)
174
					break;
175
				continue;
176
			}
177
104
		} else if (vflag) {
178
104
			if (!isascii(ch)) {
179
				if (putchar('M') == EOF || putchar('-') == EOF)
180
					break;
181
				ch = toascii(ch);
182
			}
183
104
			if (iscntrl(ch)) {
184
				if (putchar('^') == EOF ||
185
				    putchar(ch == '\177' ? '?' :
186
				    ch | 0100) == EOF)
187
					break;
188
				continue;
189
			}
190
		}
191

120
		if (putchar(ch) == EOF)
192
			break;
193
	}
194

4
	if (ferror(fp)) {
195
		warn("%s", filename);
196
		rval = 1;
197
		clearerr(fp);
198
	}
199

4
	if (ferror(stdout))
200
		err(1, "stdout");
201
4
}
202
203
void
204
raw_args(char **argv)
205
1260
{
206
	int fd;
207
208
1260
	fd = fileno(stdin);
209
1260
	filename = "stdin";
210
	do {
211
1790
		if (*argv) {
212
1153
			if (!strcmp(*argv, "-"))
213
191
				fd = fileno(stdin);
214
962
			else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
215
				warn("%s", *argv);
216
				rval = 1;
217
				++argv;
218
				continue;
219
			}
220
1153
			filename = *argv++;
221
		}
222
1790
		raw_cat(fd);
223

1790
		if (fd != fileno(stdin))
224
962
			(void)close(fd);
225
1790
	} while (*argv);
226
1260
}
227
228
void
229
raw_cat(int rfd)
230
1790
{
231
	int wfd;
232
	ssize_t nr, nw, off;
233
	static size_t bsize;
234
	static char *buf = NULL;
235
	struct stat sbuf;
236
237
1790
	wfd = fileno(stdout);
238
1790
	if (buf == NULL) {
239
1260
		if (fstat(wfd, &sbuf))
240
			err(1, "stdout");
241
1260
		bsize = MAXIMUM(sbuf.st_blksize, BUFSIZ);
242
1260
		if ((buf = malloc(bsize)) == NULL)
243
			err(1, "malloc");
244
	}
245

4258
	while ((nr = read(rfd, buf, bsize)) != -1 && nr != 0)
246
4936
		for (off = 0; nr; nr -= nw, off += nw)
247

2468
			if ((nw = write(wfd, buf + off, (size_t)nr)) == 0 ||
248
			     nw == -1)
249
				err(1, "stdout");
250
1790
	if (nr < 0) {
251
		warn("%s", filename);
252
		rval = 1;
253
	}
254
1790
}