1 /* $OpenBSD: display.c,v 1.6 2001/07/12 05:17:10 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1989 The Regents of the University of California. 5 * 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. 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 #ifndef lint 37 /*static char sccsid[] = "from: @(#)display.c 5.11 (Berkeley) 3/9/91";*/ 38 static char rcsid[] = "$OpenBSD: display.c,v 1.6 2001/07/12 05:17:10 deraadt Exp $"; 39 #endif /* not lint */ 40 41 #include <sys/param.h> 42 #include <sys/stat.h> 43 #include <unistd.h> 44 #include <errno.h> 45 #include <ctype.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include "hexdump.h" 50 51 enum _vflag vflag = FIRST; 52 53 static off_t address; /* address/offset in stream */ 54 static off_t eaddress; /* end address */ 55 static off_t savaddress; /* saved address/offset in stream */ 56 57 #define PRINT { \ 58 switch(pr->flags) { \ 59 case F_ADDRESS: \ 60 (void)printf(pr->fmt, address); \ 61 break; \ 62 case F_BPAD: \ 63 (void)printf(pr->fmt, ""); \ 64 break; \ 65 case F_C: \ 66 conv_c(pr, bp); \ 67 break; \ 68 case F_CHAR: \ 69 (void)printf(pr->fmt, *bp); \ 70 break; \ 71 case F_DBL: { \ 72 double dval; \ 73 float fval; \ 74 switch(pr->bcnt) { \ 75 case 4: \ 76 bcopy((char *)bp, (char *)&fval, sizeof(fval)); \ 77 (void)printf(pr->fmt, fval); \ 78 break; \ 79 case 8: \ 80 bcopy((char *)bp, (char *)&dval, sizeof(dval)); \ 81 (void)printf(pr->fmt, dval); \ 82 break; \ 83 } \ 84 break; \ 85 } \ 86 case F_INT: { \ 87 int ival; \ 88 short sval; \ 89 switch(pr->bcnt) { \ 90 case 1: \ 91 (void)printf(pr->fmt, (int)*bp); \ 92 break; \ 93 case 2: \ 94 bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ 95 (void)printf(pr->fmt, (int)sval); \ 96 break; \ 97 case 4: \ 98 bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ 99 (void)printf(pr->fmt, ival); \ 100 break; \ 101 } \ 102 break; \ 103 } \ 104 case F_P: \ 105 (void)printf(pr->fmt, isprint(*bp) ? *bp : '.'); \ 106 break; \ 107 case F_STR: \ 108 (void)printf(pr->fmt, (char *)bp); \ 109 break; \ 110 case F_TEXT: \ 111 (void)printf(pr->fmt); \ 112 break; \ 113 case F_U: \ 114 conv_u(pr, bp); \ 115 break; \ 116 case F_UINT: { \ 117 u_int ival; \ 118 u_short sval; \ 119 switch(pr->bcnt) { \ 120 case 1: \ 121 (void)printf(pr->fmt, (u_int)*bp); \ 122 break; \ 123 case 2: \ 124 bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ 125 (void)printf(pr->fmt, (u_int)sval); \ 126 break; \ 127 case 4: \ 128 bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ 129 (void)printf(pr->fmt, ival); \ 130 break; \ 131 } \ 132 break; \ 133 } \ 134 } \ 135 } 136 137 void 138 display() 139 { 140 extern FU *endfu; 141 register FS *fs; 142 register FU *fu; 143 register PR *pr; 144 register int cnt; 145 register u_char *bp; 146 off_t saveaddress; 147 u_char savech, *savebp, *get(); 148 149 while ((bp = get())) 150 for (fs = fshead, savebp = bp, saveaddress = address; fs; 151 fs = fs->nextfs, bp = savebp, address = saveaddress) 152 for (fu = fs->nextfu; fu; fu = fu->nextfu) { 153 if (fu->flags&F_IGNORE) 154 break; 155 for (cnt = fu->reps; cnt; --cnt) 156 for (pr = fu->nextpr; pr; address += pr->bcnt, 157 bp += pr->bcnt, pr = pr->nextpr) { 158 if (eaddress && address >= eaddress && 159 !(pr->flags&(F_TEXT|F_BPAD))) 160 bpad(pr); 161 if (cnt == 1 && pr->nospace) { 162 savech = *pr->nospace; 163 *pr->nospace = '\0'; 164 } 165 PRINT; 166 if (cnt == 1 && pr->nospace) 167 *pr->nospace = savech; 168 } 169 } 170 if (endfu) { 171 /* 172 * if eaddress not set, error or file size was multiple of 173 * blocksize, and no partial block ever found. 174 */ 175 if (!eaddress) { 176 if (!address) 177 return; 178 eaddress = address; 179 } 180 for (pr = endfu->nextpr; pr; pr = pr->nextpr) 181 switch(pr->flags) { 182 case F_ADDRESS: 183 (void)printf(pr->fmt, eaddress); 184 break; 185 case F_TEXT: 186 (void)printf(pr->fmt); 187 break; 188 } 189 } 190 } 191 192 void 193 bpad(pr) 194 PR *pr; 195 { 196 static char *spec = " -0+#"; 197 register char *p1, *p2; 198 199 /* 200 * remove all conversion flags; '-' is the only one valid 201 * with %s, and it's not useful here. 202 */ 203 pr->flags = F_BPAD; 204 *pr->cchar = 's'; 205 for (p1 = pr->fmt; *p1 != '%'; ++p1); 206 for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1); 207 while ((*p2++ = *p1++)) 208 ; 209 } 210 211 static char **_argv; 212 213 u_char * 214 get() 215 { 216 extern enum _vflag vflag; 217 extern int length; 218 static int ateof = 1; 219 static u_char *curp, *savp; 220 register int n; 221 int need, nread; 222 int valid_save = 0; 223 u_char *tmpp; 224 225 if (!curp) { 226 curp = (u_char *)emalloc(blocksize); 227 savp = (u_char *)emalloc(blocksize); 228 } else { 229 tmpp = curp; 230 curp = savp; 231 savp = tmpp; 232 address = savaddress += blocksize; 233 valid_save = 1; 234 } 235 for (need = blocksize, nread = 0;;) { 236 /* 237 * if read the right number of bytes, or at EOF for one file, 238 * and no other files are available, zero-pad the rest of the 239 * block and set the end flag. 240 */ 241 if (!length || ateof && !next((char **)NULL)) { 242 if (need == blocksize) 243 return((u_char *)NULL); 244 if (vflag != ALL && valid_save && 245 !bcmp(curp, savp, nread)) { 246 if (vflag != DUP) 247 (void)printf("*\n"); 248 return((u_char *)NULL); 249 } 250 bzero((char *)curp + nread, need); 251 eaddress = address + nread; 252 return(curp); 253 } 254 n = fread((char *)curp + nread, sizeof(u_char), 255 length == -1 ? need : MIN(length, need), stdin); 256 if (!n) { 257 if (ferror(stdin)) 258 (void)fprintf(stderr, "hexdump: %s: %s\n", 259 _argv[-1], strerror(errno)); 260 ateof = 1; 261 continue; 262 } 263 ateof = 0; 264 if (length != -1) 265 length -= n; 266 if (!(need -= n)) { 267 if (vflag == ALL || vflag == FIRST || !valid_save || 268 bcmp(curp, savp, blocksize)) { 269 if (vflag == DUP || vflag == FIRST) 270 vflag = WAIT; 271 return(curp); 272 } 273 if (vflag == WAIT) 274 (void)printf("*\n"); 275 vflag = DUP; 276 address = savaddress += blocksize; 277 need = blocksize; 278 nread = 0; 279 } 280 else 281 nread += n; 282 } 283 } 284 285 extern off_t skip; /* bytes to skip */ 286 287 int 288 next(argv) 289 char **argv; 290 { 291 extern int exitval; 292 static int done; 293 int statok; 294 295 if (argv) { 296 _argv = argv; 297 return(1); 298 } 299 for (;;) { 300 if (*_argv) { 301 if (!(freopen(*_argv, "r", stdin))) { 302 (void)fprintf(stderr, "hexdump: %s: %s\n", 303 *_argv, strerror(errno)); 304 exitval = 1; 305 ++_argv; 306 continue; 307 } 308 statok = done = 1; 309 } else { 310 if (done++) 311 return(0); 312 statok = 0; 313 } 314 if (skip) 315 doskip(statok ? *_argv : "stdin", statok); 316 if (*_argv) 317 ++_argv; 318 if (!skip) 319 return(1); 320 } 321 /* NOTREACHED */ 322 } 323 324 void 325 doskip(fname, statok) 326 char *fname; 327 int statok; 328 { 329 struct stat sbuf; 330 331 if (statok) { 332 if (fstat(fileno(stdin), &sbuf)) { 333 (void)fprintf(stderr, "hexdump: %s: %s.\n", 334 fname, strerror(errno)); 335 exit(1); 336 } 337 if (skip >= sbuf.st_size) { 338 skip -= sbuf.st_size; 339 address += sbuf.st_size; 340 return; 341 } 342 } 343 if (fseek(stdin, skip, SEEK_SET)) { 344 (void)fprintf(stderr, "hexdump: %s: %s.\n", 345 fname, strerror(errno)); 346 exit(1); 347 } 348 savaddress = address += skip; 349 skip = 0; 350 } 351 352 char * 353 emalloc(size) 354 int size; 355 { 356 char *p; 357 358 if (!(p = malloc((u_int)size))) 359 nomem(); 360 bzero(p, size); 361 return(p); 362 } 363 364 void 365 nomem() 366 { 367 (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno)); 368 exit(1); 369 } 370