1 /* $NetBSD: display.c,v 1.17 2003/10/22 12:30:39 dmcmahill Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #if defined(__RCSID) && !defined(lint) 34 #if 0 35 static char sccsid[] = "@(#)display.c 8.1 (Berkeley) 6/6/93"; 36 #else 37 __RCSID("$NetBSD: display.c,v 1.17 2003/10/22 12:30:39 dmcmahill Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #if HAVE_CONFIG_H 42 #include "config.h" 43 #endif 44 45 #include <sys/param.h> 46 #include <sys/stat.h> 47 48 #include <ctype.h> 49 #include <err.h> 50 #include <errno.h> 51 #include <inttypes.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <unistd.h> 56 57 #include "hexdump.h" 58 59 enum _vflag vflag = FIRST; 60 61 static off_t address; /* address/offset in stream */ 62 static off_t eaddress; /* end address */ 63 64 static inline void print __P((PR *, u_char *)); 65 66 void 67 display() 68 { 69 FS *fs; 70 FU *fu; 71 PR *pr; 72 int cnt; 73 u_char *bp; 74 off_t saveaddress; 75 u_char savech, *savebp; 76 77 savech = 0; 78 while ((bp = get()) != NULL) 79 for (fs = fshead, savebp = bp, saveaddress = address; fs; 80 fs = fs->nextfs, bp = savebp, address = saveaddress) 81 for (fu = fs->nextfu; fu; fu = fu->nextfu) { 82 if (fu->flags&F_IGNORE) 83 break; 84 for (cnt = fu->reps; cnt; --cnt) 85 for (pr = fu->nextpr; pr; address += pr->bcnt, 86 bp += pr->bcnt, pr = pr->nextpr) { 87 if (eaddress && address >= eaddress && 88 !(pr->flags & (F_TEXT|F_BPAD))) 89 bpad(pr); 90 if (cnt == 1 && pr->nospace) { 91 savech = *pr->nospace; 92 *pr->nospace = '\0'; 93 } 94 print(pr, bp); 95 if (cnt == 1 && pr->nospace) 96 *pr->nospace = savech; 97 } 98 } 99 if (endfu) { 100 /* 101 * If eaddress not set, error or file size was multiple of 102 * blocksize, and no partial block ever found. 103 */ 104 if (!eaddress) { 105 if (!address) 106 return; 107 eaddress = address; 108 } 109 for (pr = endfu->nextpr; pr; pr = pr->nextpr) 110 switch(pr->flags) { 111 case F_ADDRESS: 112 (void)printf(pr->fmt, (int64_t)eaddress); 113 break; 114 case F_TEXT: 115 (void)printf("%s", pr->fmt); 116 break; 117 } 118 } 119 } 120 121 static inline void 122 print(pr, bp) 123 PR *pr; 124 u_char *bp; 125 { 126 double f8; 127 float f4; 128 int16_t s2; 129 int32_t s4; 130 int64_t s8; 131 u_int16_t u2; 132 u_int32_t u4; 133 u_int64_t u8; 134 135 switch(pr->flags) { 136 case F_ADDRESS: 137 (void)printf(pr->fmt, (int64_t)address); 138 break; 139 case F_BPAD: 140 (void)printf(pr->fmt, ""); 141 break; 142 case F_C: 143 conv_c(pr, bp); 144 break; 145 case F_CHAR: 146 (void)printf(pr->fmt, *bp); 147 break; 148 case F_DBL: 149 switch(pr->bcnt) { 150 case 4: 151 memmove(&f4, bp, sizeof(f4)); 152 (void)printf(pr->fmt, f4); 153 break; 154 case 8: 155 memmove(&f8, bp, sizeof(f8)); 156 (void)printf(pr->fmt, f8); 157 break; 158 } 159 break; 160 case F_INT: 161 switch(pr->bcnt) { 162 case 1: 163 (void)printf(pr->fmt, (int64_t)*bp); 164 break; 165 case 2: 166 memmove(&s2, bp, sizeof(s2)); 167 (void)printf(pr->fmt, (int64_t)s2); 168 break; 169 case 4: 170 memmove(&s4, bp, sizeof(s4)); 171 (void)printf(pr->fmt, (int64_t)s4); 172 break; 173 case 8: 174 memmove(&s8, bp, sizeof(s8)); 175 (void)printf(pr->fmt, s8); 176 break; 177 } 178 break; 179 case F_P: 180 (void)printf(pr->fmt, isprint(*bp) ? *bp : '.'); 181 break; 182 case F_STR: 183 (void)printf(pr->fmt, (char *)bp); 184 break; 185 case F_TEXT: 186 (void)printf("%s", pr->fmt); 187 break; 188 case F_U: 189 conv_u(pr, bp); 190 break; 191 case F_UINT: 192 switch(pr->bcnt) { 193 case 1: 194 (void)printf(pr->fmt, (uint64_t)*bp); 195 break; 196 case 2: 197 memmove(&u2, bp, sizeof(u2)); 198 (void)printf(pr->fmt, (uint64_t)u2); 199 break; 200 case 4: 201 memmove(&u4, bp, sizeof(u4)); 202 (void)printf(pr->fmt, (uint64_t)u4); 203 break; 204 case 8: 205 memmove(&u8, bp, sizeof(u8)); 206 (void)printf(pr->fmt, u8); 207 break; 208 } 209 break; 210 } 211 } 212 213 void 214 bpad(pr) 215 PR *pr; 216 { 217 static const char *spec = " -0+#"; 218 char *p1, *p2; 219 220 /* 221 * Remove all conversion flags; '-' is the only one valid 222 * with %s, and it's not useful here. 223 */ 224 pr->flags = F_BPAD; 225 pr->cchar[0] = 's'; 226 pr->cchar[1] = '\0'; 227 for (p1 = pr->fmt; *p1 != '%'; ++p1); 228 for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1); 229 while ((*p2++ = *p1++) != '\0'); 230 } 231 232 static char **_argv; 233 234 u_char * 235 get() 236 { 237 static int ateof = 1; 238 static u_char *curp, *savp; 239 int n; 240 int need, nread; 241 u_char *tmpp; 242 243 if (!curp) { 244 curp = emalloc(blocksize); 245 savp = emalloc(blocksize); 246 } else { 247 tmpp = curp; 248 curp = savp; 249 savp = tmpp; 250 address += blocksize; 251 } 252 for (need = blocksize, nread = 0;;) { 253 /* 254 * if read the right number of bytes, or at EOF for one file, 255 * and no other files are available, zero-pad the rest of the 256 * block and set the end flag. 257 */ 258 if (!length || (ateof && !next(NULL))) { 259 if (need == blocksize) 260 return(NULL); 261 if (!need && vflag != ALL && 262 !memcmp(curp, savp, nread)) { 263 if (vflag != DUP) 264 (void)printf("*\n"); 265 return(NULL); 266 } 267 memset((char *)curp + nread, 0, need); 268 eaddress = address + nread; 269 return(curp); 270 } 271 n = fread((char *)curp + nread, sizeof(u_char), 272 length == -1 ? need : MIN(length, need), stdin); 273 if (!n) { 274 if (ferror(stdin)) 275 warn("%s", _argv[-1]); 276 ateof = 1; 277 continue; 278 } 279 ateof = 0; 280 if (length != -1) 281 length -= n; 282 if (!(need -= n)) { 283 if (vflag == ALL || vflag == FIRST || 284 memcmp(curp, savp, blocksize)) { 285 if (vflag == DUP || vflag == FIRST) 286 vflag = WAIT; 287 return(curp); 288 } 289 if (vflag == WAIT) 290 (void)printf("*\n"); 291 vflag = DUP; 292 address += blocksize; 293 need = blocksize; 294 nread = 0; 295 } 296 else 297 nread += n; 298 } 299 } 300 301 int 302 next(argv) 303 char **argv; 304 { 305 static int done; 306 int statok; 307 308 if (argv) { 309 _argv = argv; 310 return(1); 311 } 312 for (;;) { 313 if (*_argv) { 314 if (!(freopen(*_argv, "r", stdin))) { 315 warn("%s", *_argv); 316 exitval = 1; 317 ++_argv; 318 continue; 319 } 320 statok = done = 1; 321 } else { 322 if (done++) 323 return(0); 324 statok = 0; 325 } 326 if (skip) 327 doskip(statok ? *_argv : "stdin", statok); 328 if (*_argv) 329 ++_argv; 330 if (!skip) 331 return(1); 332 } 333 /* NOTREACHED */ 334 } 335 336 void 337 doskip(fname, statok) 338 const char *fname; 339 int statok; 340 { 341 int cnt; 342 struct stat sb; 343 344 if (statok) { 345 if (fstat(fileno(stdin), &sb)) 346 err(1, "fstat %s", fname); 347 if (S_ISREG(sb.st_mode) && skip >= sb.st_size) { 348 address += sb.st_size; 349 skip -= sb.st_size; 350 return; 351 } 352 } 353 if (S_ISREG(sb.st_mode)) { 354 if (fseek(stdin, skip, SEEK_SET)) 355 err(1, "fseek %s", fname); 356 address += skip; 357 skip = 0; 358 } else { 359 for (cnt = 0; cnt < skip; ++cnt) 360 if (getchar() == EOF) 361 break; 362 address += cnt; 363 skip -= cnt; 364 } 365 } 366 367 void * 368 emalloc(allocsize) 369 int allocsize; 370 { 371 void *p; 372 373 if ((p = malloc((u_int)allocsize)) == NULL) 374 nomem(); 375 memset(p, 0, allocsize); 376 return(p); 377 } 378 379 void 380 nomem() 381 { 382 err(1, NULL); 383 } 384