1 /* $OpenBSD: odsyntax.c,v 1.13 2003/06/12 20:58:09 deraadt Exp $ */ 2 /* $NetBSD: odsyntax.c,v 1.15 2001/12/07 15:14:29 bjh21 Exp $ */ 3 4 /*- 5 * Copyright (c) 1990, 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 #ifndef lint 34 /*static char sccsid[] = "from: @(#)odsyntax.c 5.4 (Berkeley) 3/8/91";*/ 35 static char rcsid[] = "$OpenBSD: odsyntax.c,v 1.13 2003/06/12 20:58:09 deraadt Exp $"; 36 #endif /* not lint */ 37 38 #include <sys/types.h> 39 40 #include <ctype.h> 41 #include <err.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <unistd.h> 45 46 #include "hexdump.h" 47 48 int deprecated; 49 50 static void odoffset(int, char ***); 51 static void posixtypes(char *); 52 static void odprecede(void); 53 54 55 /* 56 * formats used for -t 57 */ 58 static const char *fmt[4][4] = { 59 { 60 "16/1 \"%3d \" \"\\n\"", 61 "8/2 \" %05d \" \"\\n\"", 62 "4/4 \" %010d \" \"\\n\"", 63 "2/8 \" %019d \" \"\\n\"" 64 }, { 65 "16/1 \"%03o \" \"\\n\"", 66 "8/2 \" %06o \" \"\\n\"", 67 "4/4 \" %011o\" \"\\n\"", 68 "2/8 \" %022o \" \"\\n\"" 69 }, { 70 "16/1 \"%03u \" \"\\n\"", 71 "8/2 \" %05u \" \"\\n\"", 72 "4/4 \" %010u \" \"\\n\"", 73 "2/8 \" %020u \" \"\\n\"" 74 }, { 75 "16/1 \" %02x \" \"\\n\"", 76 "8/2 \" %04x \" \"\\n\"", 77 "4/4 \" %08x \" \"\\n\"", 78 "2/8 \" %16x \" \"\\n\"" 79 } 80 }; 81 82 void 83 oldsyntax(int argc, char ***argvp) 84 { 85 int ch; 86 char *p, **argv; 87 88 deprecated = 1; 89 argv = *argvp; 90 while ((ch = getopt(argc, argv, 91 "aBbcDdeFfHhIij:LlN:OoPpst:wvXx")) != -1) 92 switch (ch) { 93 case 'a': 94 odprecede(); 95 add("16/1 \"%3_u \" \"\\n\""); 96 break; 97 case 'B': 98 case 'o': 99 odprecede(); 100 add("8/2 \" %06o \" \"\\n\""); 101 break; 102 case 'b': 103 odprecede(); 104 add("16/1 \"%03o \" \"\\n\""); 105 break; 106 case 'c': 107 odprecede(); 108 add("16/1 \"%3_c \" \"\\n\""); 109 break; 110 case 'd': 111 odprecede(); 112 add("8/2 \" %05u \" \"\\n\""); 113 break; 114 case 'D': 115 odprecede(); 116 add("4/4 \" %010u \" \"\\n\""); 117 break; 118 case 'e': /* undocumented in od */ 119 case 'F': 120 odprecede(); 121 add("2/8 \" %21.14e \" \"\\n\""); 122 break; 123 124 case 'f': 125 odprecede(); 126 add("4/4 \" %14.7e \" \"\\n\""); 127 break; 128 case 'H': 129 case 'X': 130 odprecede(); 131 add("4/4 \" %08x \" \"\\n\""); 132 break; 133 case 'h': 134 case 'x': 135 odprecede(); 136 add("8/2 \" %04x \" \"\\n\""); 137 break; 138 case 'I': 139 case 'L': 140 case 'l': 141 odprecede(); 142 add("4/4 \" %11d \" \"\\n\""); 143 break; 144 case 'i': 145 odprecede(); 146 add("8/2 \" %6d \" \"\\n\""); 147 break; 148 case 'j': 149 if ((skip = strtol(optarg, &p, 0)) < 0) 150 errx(1, "%s: bad skip value", optarg); 151 switch(*p) { 152 case 'b': 153 skip *= 512; 154 break; 155 case 'k': 156 skip *= 1024; 157 break; 158 case 'm': 159 skip *= 1048576; 160 break; 161 } 162 break; 163 case 'N': 164 if ((length = atoi(optarg)) < 0) 165 errx(1, "%s: bad length value", optarg); 166 break; 167 case 'O': 168 odprecede(); 169 add("4/4 \" %011o \" \"\\n\""); 170 break; 171 case 't': 172 posixtypes(optarg); 173 break; 174 case 'v': 175 vflag = ALL; 176 break; 177 case 'P': 178 case 'p': 179 case 's': 180 case 'w': 181 case '?': 182 default: 183 warnx("od(1) has been deprecated for hexdump(1)."); 184 if (ch != '?') 185 warnx( 186 "hexdump(1) compatibility doesn't support the -%c option%s\n", 187 ch, ch == 's' ? "; see strings(1)." : "."); 188 oldusage(); 189 } 190 191 if (!fshead) { 192 add("\"%07.7_Ao\n\""); 193 add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\""); 194 } 195 196 argc -= optind; 197 *argvp += optind; 198 199 if (argc) 200 odoffset(argc, argvp); 201 } 202 203 /* 204 * Interpret a POSIX-style -t argument. 205 */ 206 static void 207 posixtypes(char *type_string) 208 { 209 int x, y, nbytes; 210 211 while (*type_string) { 212 odprecede(); 213 switch (*type_string) { 214 case 'a': 215 type_string++; 216 add("16/1 \"%3_u \" \"\\n\""); 217 break; 218 case 'c': 219 type_string++; 220 add("16/1 \"%3_c \" \"\\n\""); 221 break; 222 case 'f': 223 type_string++; 224 if (*type_string == 'F' || 225 *type_string == '4') { 226 type_string++; 227 add("4/4 \" %14.7e\" \"\\n\""); 228 } else if (*type_string == 'L' || 229 *type_string == '8') { 230 type_string++; 231 add("2/8 \" %16.14e\" \"\\n\""); 232 } else if (*type_string == 'D') 233 /* long doubles vary in size */ 234 oldusage(); 235 else 236 add("2/8 \" %16.14e\" \"\\n\""); 237 break; 238 case 'd': 239 x = 0; 240 goto extensions; 241 case 'o': 242 x = 1; 243 goto extensions; 244 case 'u': 245 x = 2; 246 goto extensions; 247 case 'x': 248 x = 3; 249 extensions: 250 type_string++; 251 y = 2; 252 if (isupper(*type_string)) { 253 switch(*type_string) { 254 case 'C': 255 nbytes = sizeof(char); 256 break; 257 case 'S': 258 nbytes = sizeof(short); 259 break; 260 case 'I': 261 nbytes = sizeof(int); 262 break; 263 case 'L': 264 nbytes = sizeof(long); 265 break; 266 default: 267 warnx("Bad type-size qualifier '%c'", 268 *type_string); 269 oldusage(); 270 } 271 type_string++; 272 } else if (isdigit(*type_string)) 273 nbytes = strtol(type_string, &type_string, 10); 274 275 switch (nbytes) { 276 case 1: 277 y = 0; 278 break; 279 case 2: 280 y = 1; 281 break; 282 case 4: 283 y = 2; 284 break; 285 case 8: 286 y = 3; 287 break; 288 default: 289 warnx("%d-byte integer formats are not " 290 "supported", nbytes); 291 oldusage(); 292 } 293 add(fmt[x][y]); 294 break; 295 default: 296 oldusage(); 297 } 298 } 299 } 300 301 void 302 oldusage(void) 303 { 304 extern char *__progname; 305 fprintf(stderr, "usage: %s [-aBbcDdeFfHhIiLlOovXx] [-j skip] " 306 "[-N length] [-t type_string] " 307 "[[+]offset[.][Bb]] [file ...]\n", __progname); 308 exit(1); 309 } 310 311 static void 312 odoffset(int argc, char ***argvp) 313 { 314 char *num, *p; 315 int base; 316 char *end; 317 318 /* 319 * The offset syntax of od(1) was genuinely bizarre. First, if 320 * it started with a plus it had to be an offset. Otherwise, if 321 * there were at least two arguments, a number or lower-case 'x' 322 * followed by a number makes it an offset. By default it was 323 * octal; if it started with 'x' or '0x' it was hex. If it ended 324 * in a '.', it was decimal. If a 'b' or 'B' was appended, it 325 * multiplied the number by 512 or 1024 byte units. There was 326 * no way to assign a block count to a hex offset. 327 * 328 * We assume it's a file if the offset is bad. 329 */ 330 p = argc == 1 ? (*argvp)[0] : (*argvp)[1]; 331 if (!p) 332 return; 333 334 if (*p != '+' && (argc < 2 || 335 (!isdigit((unsigned char)p[0]) && 336 (p[0] != 'x' || !isxdigit((unsigned char)p[1]))))) 337 return; 338 339 base = 0; 340 /* 341 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and 342 * set base. 343 */ 344 if (p[0] == '+') 345 ++p; 346 if (p[0] == 'x' && isxdigit((unsigned char)p[1])) { 347 ++p; 348 base = 16; 349 } else if (p[0] == '0' && p[1] == 'x') { 350 p += 2; 351 base = 16; 352 } 353 354 /* skip over the number */ 355 if (base == 16) 356 for (num = p; isxdigit((unsigned char)*p); ++p); 357 else 358 for (num = p; isdigit((unsigned char)*p); ++p); 359 360 /* check for no number */ 361 if (num == p) 362 return; 363 364 /* if terminates with a '.', base is decimal */ 365 if (*p == '.') { 366 if (base) 367 return; 368 base = 10; 369 } 370 371 skip = strtol(num, &end, base ? base : 8); 372 373 /* if end isn't the same as p, we got a non-octal digit */ 374 if (end != p) { 375 skip = 0; 376 return; 377 } 378 379 if (*p) { 380 if (*p == 'B') { 381 skip *= 1024; 382 ++p; 383 } else if (*p == 'b') { 384 skip *= 512; 385 ++p; 386 } 387 } 388 if (*p) { 389 skip = 0; 390 return; 391 } 392 /* 393 * If the offset uses a non-octal base, the base of the offset 394 * is changed as well. This isn't pretty, but it's easy. 395 */ 396 #define TYPE_OFFSET 7 397 if (base == 16) { 398 fshead->nextfu->fmt[TYPE_OFFSET] = 'x'; 399 fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x'; 400 } else if (base == 10) { 401 fshead->nextfu->fmt[TYPE_OFFSET] = 'd'; 402 fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd'; 403 } 404 405 /* Terminate file list. */ 406 (*argvp)[1] = NULL; 407 } 408 409 static void 410 odprecede(void) 411 { 412 static int first = 1; 413 414 if (first) { 415 first = 0; 416 add("\"%07.7_Ao\n\""); 417 add("\"%07.7_ao \""); 418 } else 419 add("\" \""); 420 } 421