GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/hexdump/display.c Lines: 0 155 0.0 %
Date: 2016-12-06 Branches: 0 152 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: display.c,v 1.24 2016/03/15 04:19:13 mmcc 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
	while ((bp = get()) != NULL)
70
	    for (fs = fshead, savebp = bp, saveaddress = address; fs;
71
		fs = fs->nextfs, bp = savebp, address = saveaddress)
72
		    for (fu = fs->nextfu; fu; fu = fu->nextfu) {
73
			if (fu->flags&F_IGNORE)
74
				break;
75
			for (cnt = fu->reps; cnt; --cnt)
76
			    for (pr = fu->nextpr; pr; address += pr->bcnt,
77
				bp += pr->bcnt, pr = pr->nextpr) {
78
				    if (eaddress && address >= eaddress &&
79
					!(pr->flags & (F_TEXT|F_BPAD)))
80
					    bpad(pr);
81
				    if (cnt == 1 && pr->nospace) {
82
					savech = *pr->nospace;
83
					*pr->nospace = '\0';
84
				    }
85
				    print(pr, bp);
86
				    if (cnt == 1 && pr->nospace)
87
					*pr->nospace = savech;
88
			    }
89
		    }
90
	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
		if (!eaddress) {
96
			if (!address)
97
				return;
98
			eaddress = address;
99
		}
100
		for (pr = endfu->nextpr; pr; pr = pr->nextpr)
101
			switch(pr->flags) {
102
			case F_ADDRESS:
103
				(void)printf(pr->fmt, (quad_t)eaddress);
104
				break;
105
			case F_TEXT:
106
				(void)printf("%s", pr->fmt);
107
				break;
108
			}
109
	}
110
}
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
	switch(pr->flags) {
125
	case F_ADDRESS:
126
		(void)printf(pr->fmt, (quad_t)address);
127
		break;
128
	case F_BPAD:
129
		(void)printf(pr->fmt, "");
130
		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
		switch(pr->bcnt) {
151
		case 1:
152
			(void)printf(pr->fmt, (quad_t)*bp);
153
			break;
154
		case 2:
155
			memmove(&s2, bp, sizeof(s2));
156
			(void)printf(pr->fmt, (quad_t)s2);
157
			break;
158
		case 4:
159
			memmove(&s4, bp, sizeof(s4));
160
			(void)printf(pr->fmt, (quad_t)s4);
161
			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
		(void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
170
		break;
171
	case F_STR:
172
		(void)printf(pr->fmt, (char *)bp);
173
		break;
174
	case F_TEXT:
175
		(void)printf("%s", pr->fmt);
176
		break;
177
	case F_U:
178
		conv_u(pr, bp);
179
		break;
180
	case F_UINT:
181
		switch(pr->bcnt) {
182
		case 1:
183
			(void)printf(pr->fmt, (u_quad_t)*bp);
184
			break;
185
		case 2:
186
			memmove(&u2, bp, sizeof(u2));
187
			(void)printf(pr->fmt, (u_quad_t)u2);
188
			break;
189
		case 4:
190
			memmove(&u4, bp, sizeof(u4));
191
			(void)printf(pr->fmt, (u_quad_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
}
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
	pr->flags = F_BPAD;
213
	pr->cchar[0] = 's';
214
	pr->cchar[1] = '\0';
215
	for (p1 = pr->fmt; *p1 != '%'; ++p1);
216
	for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
217
	while ((*p2++ = *p1++) != '\0');
218
}
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
	if (!curp) {
232
		if ((curp = calloc(1, blocksize)) == NULL ||
233
		    (savp = calloc(1, blocksize)) == NULL)
234
			err(1, NULL);
235
	} else {
236
		tmpp = curp;
237
		curp = savp;
238
		savp = tmpp;
239
		address += blocksize;
240
	}
241
	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
		if (!length || (ateof && !next(NULL))) {
248
			if (need == blocksize)
249
				return(NULL);
250
			if (!need && vflag != ALL &&
251
			    !memcmp(curp, savp, nread)) {
252
				if (vflag != DUP)
253
					(void)printf("*\n");
254
				return(NULL);
255
			}
256
			memset((char *)curp + nread, 0, need);
257
			eaddress = address + nread;
258
			return(curp);
259
		}
260
		n = fread((char *)curp + nread, sizeof(u_char),
261
		    length == -1 ? need : MINIMUM(length, need), stdin);
262
		if (!n) {
263
			if (ferror(stdin))
264
				warn("%s", _argv[-1]);
265
			ateof = 1;
266
			continue;
267
		}
268
		ateof = 0;
269
		if (length != -1)
270
			length -= n;
271
		if (!(need -= n)) {
272
			if (vflag == ALL || vflag == FIRST ||
273
			    memcmp(curp, savp, blocksize)) {
274
				if (vflag == DUP || vflag == FIRST)
275
					vflag = WAIT;
276
				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
			nread += n;
287
	}
288
}
289
290
int
291
next(char **argv)
292
{
293
	static int done;
294
	int statok;
295
296
	if (argv) {
297
		_argv = argv;
298
		return(1);
299
	}
300
	for (;;) {
301
		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
			if (done++)
311
				return(0);
312
			statok = 0;
313
		}
314
		if (iobuf != NULL)
315
			setvbuf(stdin, iobuf, _IOFBF, iobufsiz);
316
		if (skip)
317
			doskip(statok ? *_argv : "stdin", statok);
318
		if (*_argv)
319
			++_argv;
320
		if (!skip)
321
			return(1);
322
	}
323
	/* NOTREACHED */
324
}
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
}