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