GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/cat/cat.c Lines: 76 116 65.5 %
Date: 2017-11-13 Branches: 71 152 46.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
2148
	if (pledge("stdio rpath flock cpath wpath", NULL) == -1)
67
		err(1, "pledge");
68
69
2212
	while ((ch = getopt(argc, argv, "benstuv")) != -1)
70


32
		switch (ch) {
71
		case 'b':
72
8
			bflag = nflag = 1;	/* -b implies -n */
73
8
			break;
74
		case 'e':
75
16
			eflag = vflag = 1;	/* -e implies -v */
76
16
			break;
77
		case 'n':
78
			nflag = 1;
79
			break;
80
		case 's':
81
8
			sflag = 1;
82
8
			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
1074
	argv += optind;
98
99
1074
	if (bflag || eflag || nflag || sflag || tflag || vflag)
100
16
		cook_args(argv);
101
	else
102
1058
		raw_args(argv);
103
1074
	if (fclose(stdout))
104
		err(1, "stdout");
105
1074
	return rval;
106
1074
}
107
108
void
109
cook_args(char **argv)
110
{
111
	FILE *fp;
112
113
	fp = stdin;
114
32
	filename = "stdin";
115
16
	do {
116
16
		if (*argv) {
117
16
			if (!strcmp(*argv, "-"))
118
				fp = stdin;
119
16
			else if ((fp = fopen(*argv, "r")) == NULL) {
120
				warn("%s", *argv);
121
				rval = 1;
122
				++argv;
123
				continue;
124
			}
125
16
			filename = *argv++;
126
16
		}
127
16
		cook_buf(fp);
128
16
		if (fp == stdin)
129
			clearerr(fp);
130
		else
131
16
			(void)fclose(fp);
132
16
	} while (*argv);
133
16
}
134
135
void
136
cook_buf(FILE *fp)
137
{
138
	int ch, gobble, line, prev;
139
140
	line = gobble = 0;
141

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

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

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

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

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

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

32
	if (ferror(stdout))
195
		err(1, "stdout");
196
16
}
197
198
void
199
raw_args(char **argv)
200
{
201
	int fd;
202
203
4232
	fd = fileno(stdin);
204
1058
	filename = "stdin";
205
1058
	do {
206
2196
		if (*argv) {
207
1583
			if (!strcmp(*argv, "-"))
208
				fd = fileno(stdin);
209
1583
			else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
210
				warn("%s", *argv);
211
				rval = 1;
212
				++argv;
213
				continue;
214
			}
215
1583
			filename = *argv++;
216
1583
		}
217
2196
		raw_cat(fd);
218

6588
		if (fd != fileno(stdin))
219
1583
			(void)close(fd);
220
2196
	} while (*argv);
221
1058
}
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
4392
	struct stat sbuf;
231
232
6588
	wfd = fileno(stdout);
233
2196
	if (buf == NULL) {
234
1058
		if (fstat(wfd, &sbuf))
235
			err(1, "stdout");
236
1058
		bsize = MAXIMUM(sbuf.st_blksize, BUFSIZ);
237
1058
		if ((buf = malloc(bsize)) == NULL)
238
			err(1, "malloc");
239
	}
240
13588
	while ((nr = read(rfd, buf, bsize)) != -1 && nr != 0)
241
18392
		for (off = 0; nr; nr -= nw, off += nw)
242
9196
			if ((nw = write(wfd, buf + off, (size_t)nr)) == 0 ||
243
4598
			     nw == -1)
244
				err(1, "stdout");
245
2196
	if (nr < 0) {
246
		warn("%s", filename);
247
		rval = 1;
248
	}
249
2196
}