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