226 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			226 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* vi: set sw=4 ts=4: */
 | |
| /*
 | |
|  * od implementation for busybox
 | |
|  * Based on code from util-linux v 2.11l
 | |
|  *
 | |
|  * Copyright (c) 1990
 | |
|  *	The Regents of the University of California.  All rights reserved.
 | |
|  *
 | |
|  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
 | |
|  *
 | |
|  * Original copyright notice is retained at the end of this file.
 | |
|  */
 | |
| 
 | |
| 
 | |
| #include "libbb.h"
 | |
| #if ENABLE_DESKTOP
 | |
| /* This one provides -t (busybox's own build script needs it) */
 | |
| #include "od_bloaty.c"
 | |
| #else
 | |
| #include <getopt.h>
 | |
| 
 | |
| #include "dump.h"
 | |
| 
 | |
| #define isdecdigit(c) isdigit(c)
 | |
| #define ishexdigit(c) (isxdigit)(c)
 | |
| 
 | |
| static void
 | |
| odoffset(int argc, char ***argvp)
 | |
| {
 | |
| 	char *num, *p;
 | |
| 	int base;
 | |
| 	char *end;
 | |
| 
 | |
| 	/*
 | |
| 	 * The offset syntax of od(1) was genuinely bizarre.  First, if
 | |
| 	 * it started with a plus it had to be an offset.  Otherwise, if
 | |
| 	 * there were at least two arguments, a number or lower-case 'x'
 | |
| 	 * followed by a number makes it an offset.  By default it was
 | |
| 	 * octal; if it started with 'x' or '0x' it was hex.  If it ended
 | |
| 	 * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
 | |
| 	 * multiplied the number by 512 or 1024 byte units.  There was
 | |
| 	 * no way to assign a block count to a hex offset.
 | |
| 	 *
 | |
| 	 * We assumes it's a file if the offset is bad.
 | |
| 	 */
 | |
| 	p = **argvp;
 | |
| 
 | |
| 	if (!p) {
 | |
| 		/* hey someone is probably piping to us ... */
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if ((*p != '+')
 | |
| 		&& (argc < 2
 | |
| 			|| (!isdecdigit(p[0])
 | |
| 				&& ((p[0] != 'x') || !ishexdigit(p[1])))))
 | |
| 		return;
 | |
| 
 | |
| 	base = 0;
 | |
| 	/*
 | |
| 	 * bb_dump_skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
 | |
| 	 * set base.
 | |
| 	 */
 | |
| 	if (p[0] == '+')
 | |
| 		++p;
 | |
| 	if (p[0] == 'x' && ishexdigit(p[1])) {
 | |
| 		++p;
 | |
| 		base = 16;
 | |
| 	} else if (p[0] == '0' && p[1] == 'x') {
 | |
| 		p += 2;
 | |
| 		base = 16;
 | |
| 	}
 | |
| 
 | |
| 	/* bb_dump_skip over the number */
 | |
| 	if (base == 16)
 | |
| 		for (num = p; ishexdigit(*p); ++p);
 | |
| 	else
 | |
| 		for (num = p; isdecdigit(*p); ++p);
 | |
| 
 | |
| 	/* check for no number */
 | |
| 	if (num == p)
 | |
| 		return;
 | |
| 
 | |
| 	/* if terminates with a '.', base is decimal */
 | |
| 	if (*p == '.') {
 | |
| 		if (base)
 | |
| 			return;
 | |
| 		base = 10;
 | |
| 	}
 | |
| 
 | |
| 	bb_dump_skip = strtol(num, &end, base ? base : 8);
 | |
| 
 | |
| 	/* if end isn't the same as p, we got a non-octal digit */
 | |
| 	if (end != p)
 | |
| 		bb_dump_skip = 0;
 | |
| 	else {
 | |
| 		if (*p) {
 | |
| 			if (*p == 'b') {
 | |
| 				bb_dump_skip *= 512;
 | |
| 				++p;
 | |
| 			} else if (*p == 'B') {
 | |
| 				bb_dump_skip *= 1024;
 | |
| 				++p;
 | |
| 			}
 | |
| 		}
 | |
| 		if (*p)
 | |
| 			bb_dump_skip = 0;
 | |
| 		else {
 | |
| 			++*argvp;
 | |
| 			/*
 | |
| 			 * If the offset uses a non-octal base, the base of
 | |
| 			 * the offset is changed as well.  This isn't pretty,
 | |
| 			 * but it's easy.
 | |
| 			 */
 | |
| #define	TYPE_OFFSET	7
 | |
| 			{
 | |
| 				char x_or_d;
 | |
| 				if (base == 16) {
 | |
| 					x_or_d = 'x';
 | |
| 					goto DO_X_OR_D;
 | |
| 				}
 | |
| 				if (base == 10) {
 | |
| 					x_or_d = 'd';
 | |
| 				DO_X_OR_D:
 | |
| 					bb_dump_fshead->nextfu->fmt[TYPE_OFFSET]
 | |
| 						= bb_dump_fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
 | |
| 						= x_or_d;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static const char *const add_strings[] = {
 | |
| 	"16/1 \"%3_u \" \"\\n\"",				/* a */
 | |
| 	"8/2 \" %06o \" \"\\n\"",				/* B, o */
 | |
| 	"16/1 \"%03o \" \"\\n\"",				/* b */
 | |
| 	"16/1 \"%3_c \" \"\\n\"",				/* c */
 | |
| 	"8/2 \"  %05u \" \"\\n\"",				/* d */
 | |
| 	"4/4 \"     %010u \" \"\\n\"",			/* D */
 | |
| 	"2/8 \"          %21.14e \" \"\\n\"",	/* e (undocumented in od), F */
 | |
| 	"4/4 \" %14.7e \" \"\\n\"",				/* f */
 | |
| 	"4/4 \"       %08x \" \"\\n\"",			/* H, X */
 | |
| 	"8/2 \"   %04x \" \"\\n\"",				/* h, x */
 | |
| 	"4/4 \"    %11d \" \"\\n\"",			/* I, L, l */
 | |
| 	"8/2 \" %6d \" \"\\n\"",				/* i */
 | |
| 	"4/4 \"    %011o \" \"\\n\"",			/* O */
 | |
| };
 | |
| 
 | |
| static const char od_opts[] ALIGN1 = "aBbcDdeFfHhIiLlOoXxv";
 | |
| 
 | |
| static const char od_o2si[] ALIGN1 = {
 | |
| 	0, 1, 2, 3, 5,
 | |
| 	4, 6, 6, 7, 8,
 | |
| 	9, 0xa, 0xb, 0xa, 0xa,
 | |
| 	0xb, 1, 8, 9,
 | |
| };
 | |
| 
 | |
| int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 | |
| int od_main(int argc, char **argv)
 | |
| {
 | |
| 	int ch;
 | |
| 	int first = 1;
 | |
| 	char *p;
 | |
| 	bb_dump_vflag = FIRST;
 | |
| 	bb_dump_length = -1;
 | |
| 
 | |
| 	while ((ch = getopt(argc, argv, od_opts)) > 0) {
 | |
| 		if (ch == 'v') {
 | |
| 			bb_dump_vflag = ALL;
 | |
| 		} else if (((p = strchr(od_opts, ch)) != NULL) && (*p != '\0')) {
 | |
| 			if (first) {
 | |
| 				first = 0;
 | |
| 				bb_dump_add("\"%07.7_Ao\n\"");
 | |
| 				bb_dump_add("\"%07.7_ao  \"");
 | |
| 			} else {
 | |
| 				bb_dump_add("\"         \"");
 | |
| 			}
 | |
| 			bb_dump_add(add_strings[(int)od_o2si[(p-od_opts)]]);
 | |
| 		} else {	/* P, p, s, w, or other unhandled */
 | |
| 			bb_show_usage();
 | |
| 		}
 | |
| 	}
 | |
| 	if (!bb_dump_fshead) {
 | |
| 		bb_dump_add("\"%07.7_Ao\n\"");
 | |
| 		bb_dump_add("\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
 | |
| 	}
 | |
| 
 | |
| 	argc -= optind;
 | |
| 	argv += optind;
 | |
| 
 | |
| 	odoffset(argc, &argv);
 | |
| 
 | |
| 	return bb_dump_dump(argv);
 | |
| }
 | |
| #endif /* ENABLE_DESKTOP */
 | |
| 
 | |
| /*-
 | |
|  * Copyright (c) 1990 The Regents of the University of California.
 | |
|  * All rights reserved.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  * 1. Redistributions of source code must retain the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer.
 | |
|  * 2. Redistributions in binary form must reproduce the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer in the
 | |
|  *    documentation and/or other materials provided with the distribution.
 | |
|  * 3. Neither the name of the University nor the names of its contributors
 | |
|  *    may be used to endorse or promote products derived from this software
 | |
|  *    without specific prior written permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | |
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | |
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | |
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | |
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | |
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | |
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | |
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | |
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | |
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | |
|  * SUCH DAMAGE.
 | |
|  */
 |