GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/hexdump/display.c Lines: 95 167 56.9 %
Date: 2017-11-07 Branches: 89 152 58.6 %

Line Branch Exec Source
1
/*	$OpenBSD: display.c,v 1.25 2016/08/24 03:13:45 guenther Exp $	*/
2
/*	$NetBSD: display.c,v 1.12 2001/12/07 15:14:29 bjh21 Exp $	*/
3
4
/*
5
 * Copyright (c) 1989, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/stat.h>
34
35
#include <ctype.h>
36
#include <err.h>
37
#include <errno.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41
#include <unistd.h>
42
43
#include "hexdump.h"
44
45
#define MINIMUM(a, b)	(((a) < (b)) ? (a) : (b))
46
47
enum _vflag vflag = FIRST;
48
49
static off_t address;			/* address/offset in stream */
50
static off_t eaddress;			/* end address */
51
52
static void		 bpad(PR *);
53
static void		 doskip(const char *, int);
54
static u_char		*get(void);
55
static __inline void	 print(PR *, u_char *);
56
57
void
58
display(void)
59
{
60
	FS *fs;
61
	FU *fu;
62
	PR *pr;
63
	int cnt;
64
	u_char *bp;
65
	off_t saveaddress;
66
	u_char savech, *savebp;
67
68
	savech = 0;
69
22175
	while ((bp = get()) != NULL)
70
39104
	    for (fs = fshead, savebp = bp, saveaddress = address; fs;
71
14114
		fs = fs->nextfs, bp = savebp, address = saveaddress)
72
91160
		    for (fu = fs->nextfu; fu; fu = fu->nextfu) {
73
35804
			if (fu->flags&F_IGNORE)
74
				break;
75
377468
			for (cnt = fu->reps; cnt; --cnt)
76
1007578
			    for (pr = fu->nextpr; pr; address += pr->bcnt,
77
231014
				bp += pr->bcnt, pr = pr->nextpr) {
78

642118
				    if (eaddress && address >= eaddress &&
79
181521
					!(pr->flags & (F_TEXT|F_BPAD)))
80
12915
					    bpad(pr);
81

275494
				    if (cnt == 1 && pr->nospace) {
82
8676
					savech = *pr->nospace;
83
8676
					*pr->nospace = '\0';
84
8676
				    }
85
231014
				    print(pr, bp);
86

275494
				    if (cnt == 1 && pr->nospace)
87
8676
					*pr->nospace = savech;
88
			    }
89
		    }
90
5579
	if (endfu) {
91
		/*
92
		 * If eaddress not set, error or file size was multiple of
93
		 * blocksize, and no partial block ever found.
94
		 */
95
4479
		if (!eaddress) {
96
168
			if (!address)
97
168
				return;
98
			eaddress = address;
99
		}
100
25866
		for (pr = endfu->nextpr; pr; pr = pr->nextpr)
101
17244
			switch(pr->flags) {
102
			case F_ADDRESS:
103
4311
				(void)printf(pr->fmt, (int64_t)eaddress);
104
4311
				break;
105
			case F_TEXT:
106
4311
				(void)printf("%s", pr->fmt);
107
4311
				break;
108
			}
109
	}
110
10990
}
111
112
static __inline void
113
print(PR *pr, u_char *bp)
114
{
115
	   double f8;
116
	    float f4;
117
	  int16_t s2;
118
	  int32_t s4;
119
	  int64_t s8;
120
	u_int16_t u2;
121
	u_int32_t u4;
122
	u_int64_t u8;
123
124



678736
	switch(pr->flags) {
125
	case F_ADDRESS:
126
4338
		(void)printf(pr->fmt, (int64_t)address);
127
4338
		break;
128
	case F_BPAD:
129
112404
		(void)printf(pr->fmt, "");
130
112404
		break;
131
	case F_C:
132
		conv_c(pr, bp);
133
		break;
134
	case F_CHAR:
135
		(void)printf(pr->fmt, *bp);
136
		break;
137
	case F_DBL:
138
		switch(pr->bcnt) {
139
		case 4:
140
			memmove(&f4, bp, sizeof(f4));
141
			(void)printf(pr->fmt, f4);
142
			break;
143
		case 8:
144
			memmove(&f8, bp, sizeof(f8));
145
			(void)printf(pr->fmt, f8);
146
			break;
147
		}
148
		break;
149
	case F_INT:
150

2200
		switch(pr->bcnt) {
151
		case 1:
152
			(void)printf(pr->fmt, (int64_t)*bp);
153
			break;
154
		case 2:
155
			memmove(&s2, bp, sizeof(s2));
156
			(void)printf(pr->fmt, (int64_t)s2);
157
			break;
158
		case 4:
159
1100
			memmove(&s4, bp, sizeof(s4));
160
1100
			(void)printf(pr->fmt, (int64_t)s4);
161
1100
			break;
162
		case 8:
163
			memmove(&s8, bp, sizeof(s8));
164
			(void)printf(pr->fmt, s8);
165
			break;
166
		}
167
		break;
168
	case F_P:
169
37347
		(void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
170
13206
		break;
171
	case F_STR:
172
		(void)printf(pr->fmt, (char *)bp);
173
		break;
174
	case F_TEXT:
175
86760
		(void)printf("%s", pr->fmt);
176
86760
		break;
177
	case F_U:
178
		conv_u(pr, bp);
179
		break;
180
	case F_UINT:
181

26412
		switch(pr->bcnt) {
182
		case 1:
183
13206
			(void)printf(pr->fmt, (uint64_t)*bp);
184
13206
			break;
185
		case 2:
186
			memmove(&u2, bp, sizeof(u2));
187
			(void)printf(pr->fmt, (uint64_t)u2);
188
			break;
189
		case 4:
190
			memmove(&u4, bp, sizeof(u4));
191
			(void)printf(pr->fmt, (uint64_t)u4);
192
			break;
193
		case 8:
194
			memmove(&u8, bp, sizeof(u8));
195
			(void)printf(pr->fmt, u8);
196
			break;
197
		}
198
		break;
199
	}
200
231014
}
201
202
static void
203
bpad(PR *pr)
204
{
205
	static const char *spec = " -0+#";
206
	char *p1, *p2;
207
208
	/*
209
	 * Remove all conversion flags; '-' is the only one valid
210
	 * with %s, and it's not useful here.
211
	 */
212
25830
	pr->flags = F_BPAD;
213
12915
	pr->cchar[0] = 's';
214
12915
	pr->cchar[1] = '\0';
215
25830
	for (p1 = pr->fmt; *p1 != '%'; ++p1);
216

64557
	for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
217
34434
	while ((*p2++ = *p1++) != '\0');
218
12915
}
219
220
static char **_argv;
221
222
static u_char *
223
get(void)
224
{
225
	static int ateof = 1;
226
	static u_char *curp, *savp;
227
	int n;
228
	int need, nread;
229
	u_char *tmpp;
230
231
22034
	if (!curp) {
232

11158
		if ((curp = calloc(1, blocksize)) == NULL ||
233
5579
		    (savp = calloc(1, blocksize)) == NULL)
234
			err(1, NULL);
235
	} else {
236
		tmpp = curp;
237
5438
		curp = savp;
238
5438
		savp = tmpp;
239
5438
		address += blocksize;
240
	}
241
11017
	for (need = blocksize, nread = 0;;) {
242
		/*
243
		 * if read the right number of bytes, or at EOF for one file,
244
		 * and no other files are available, zero-pad the rest of the
245
		 * block and set the end flag.
246
		 */
247

60583
		if (!length || (ateof && !next(NULL))) {
248
10990
			if (need == blocksize)
249
5579
				return(NULL);
250

5411
			if (!need && vflag != ALL &&
251
			    !memcmp(curp, savp, nread)) {
252
				if (vflag != DUP)
253
					(void)printf("*\n");
254
				return(NULL);
255
			}
256
5411
			memset((char *)curp + nread, 0, need);
257
5411
			eaddress = address + nread;
258
5411
			return(curp);
259
		}
260
22034
		n = fread((char *)curp + nread, sizeof(u_char),
261
33051
		    length == -1 ? need : MINIMUM(length, need), stdin);
262
11017
		if (!n) {
263

11158
			if (ferror(stdin))
264
				warn("%s", _argv[-1]);
265
5579
			ateof = 1;
266
5579
			continue;
267
		}
268
5438
		ateof = 0;
269
5438
		if (length != -1)
270
			length -= n;
271
5438
		if (!(need -= n)) {
272

45
			if (vflag == ALL || vflag == FIRST ||
273
18
			    memcmp(curp, savp, blocksize)) {
274
27
				if (vflag == DUP || vflag == FIRST)
275
9
					vflag = WAIT;
276
27
				return(curp);
277
			}
278
			if (vflag == WAIT)
279
				(void)printf("*\n");
280
			vflag = DUP;
281
			address += blocksize;
282
			need = blocksize;
283
			nread = 0;
284
		}
285
		else
286
5411
			nread += n;
287
	}
288
11017
}
289
290
int
291
next(char **argv)
292
{
293
	static int done;
294
	int statok;
295
296
44296
	if (argv) {
297
5579
		_argv = argv;
298
5579
		return(1);
299
	}
300
	for (;;) {
301
16569
		if (*_argv) {
302
			if (!(freopen(*_argv, "r", stdin))) {
303
				warn("%s", *_argv);
304
				exitval = done = 1;
305
				++_argv;
306
				continue;
307
			}
308
			statok = done = 1;
309
		} else {
310
16569
			if (done++)
311
10990
				return(0);
312
			statok = 0;
313
		}
314
5579
		if (iobuf != NULL)
315
			setvbuf(stdin, iobuf, _IOFBF, iobufsiz);
316
5579
		if (skip)
317
			doskip(statok ? *_argv : "stdin", statok);
318
5579
		if (*_argv)
319
			++_argv;
320
5579
		if (!skip)
321
5579
			return(1);
322
	}
323
	/* NOTREACHED */
324
22148
}
325
326
static void
327
doskip(const char *fname, int statok)
328
{
329
	off_t cnt;
330
	struct stat sb;
331
332
	if (statok) {
333
		if (fstat(fileno(stdin), &sb))
334
			err(1, "fstat %s", fname);
335
		if (S_ISREG(sb.st_mode)) {
336
			if (skip > sb.st_size) {
337
				address += sb.st_size;
338
				skip -= sb.st_size;
339
			} else {
340
				if (fseeko(stdin, skip, SEEK_SET))
341
					err(1, "fseeko %s", fname);
342
				address += skip;
343
				skip = 0;
344
			}
345
			return;
346
		}
347
	}
348
349
	for (cnt = 0; cnt < skip; ++cnt)
350
		if (getchar() == EOF)
351
			break;
352
	address += cnt;
353
	skip -= cnt;
354
}