Introduce od and hexdump applets
This commit is contained in:
		
							
								
								
									
										270
									
								
								coreutils/od.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								coreutils/od.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,270 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
|  * | ||||
|  * Original copyright notice is retained at the end of this file. | ||||
|  */ | ||||
|  | ||||
| #include <ctype.h> | ||||
| #include <getopt.h> | ||||
| #include <stdlib.h> | ||||
| #include "dump.h" | ||||
| #include "busybox.h" | ||||
|  | ||||
| extern FS *fshead;				/* head of format strings */ | ||||
| extern int blocksize;				/* data block size */ | ||||
| extern int length;			/* max bytes to read */ | ||||
|  | ||||
| #define	ishexdigit(c) \ | ||||
| 	((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) | ||||
|  | ||||
| static void | ||||
| odoffset(int argc, char ***argvp) | ||||
| { | ||||
| 	extern off_t skip; | ||||
| 	register 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 != '+' && (argc < 2 || | ||||
| 	    (!isdigit(p[0]) && (p[0] != 'x' || !ishexdigit(p[1]))))) | ||||
| 		return; | ||||
|  | ||||
| 	base = 0; | ||||
| 	/* | ||||
| 	 * 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; | ||||
| 	} | ||||
|  | ||||
| 	/* skip over the number */ | ||||
| 	if (base == 16) | ||||
| 		for (num = p; ishexdigit(*p); ++p); | ||||
| 	else | ||||
| 		for (num = p; isdigit(*p); ++p); | ||||
|  | ||||
| 	/* check for no number */ | ||||
| 	if (num == p) | ||||
| 		return; | ||||
|  | ||||
| 	/* if terminates with a '.', base is decimal */ | ||||
| 	if (*p == '.') { | ||||
| 		if (base) | ||||
| 			return; | ||||
| 		base = 10; | ||||
| 	} | ||||
|  | ||||
| 	skip = strtol(num, &end, base ? base : 8); | ||||
|  | ||||
| 	/* if end isn't the same as p, we got a non-octal digit */ | ||||
| 	if (end != p) | ||||
| 		skip = 0; | ||||
| 	else { | ||||
| 		if (*p) { | ||||
| 			if (*p == 'b') | ||||
| 				skip *= 512; | ||||
| 			else if (*p == 'B') | ||||
| 				skip *= 1024; | ||||
| 			++p; | ||||
| 		} | ||||
| 		if (*p) | ||||
| 			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 | ||||
| 			if (base == 16) { | ||||
| 				fshead->nextfu->fmt[TYPE_OFFSET] = 'x'; | ||||
| 				fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x'; | ||||
| 			} else if (base == 10) { | ||||
| 				fshead->nextfu->fmt[TYPE_OFFSET] = 'd'; | ||||
| 				fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd'; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void odprecede(void) | ||||
| { | ||||
| 	static int first = 1; | ||||
|  | ||||
| 	if (first) { | ||||
| 		first = 0; | ||||
| 		add("\"%07.7_Ao\n\""); | ||||
| 		add("\"%07.7_ao  \""); | ||||
| 	} else | ||||
| 		add("\"         \""); | ||||
| } | ||||
|  | ||||
| int od_main(int argc, char **argv) | ||||
| { | ||||
| 	int ch; | ||||
| 	extern enum _vflag vflag; | ||||
| 	vflag = FIRST; | ||||
| 	length = -1; | ||||
|  | ||||
| 	while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != EOF) | ||||
| 		switch (ch) { | ||||
| 		case 'a': | ||||
| 			odprecede(); | ||||
| 			add("16/1 \"%3_u \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'B': | ||||
| 		case 'o': | ||||
| 			odprecede(); | ||||
| 			add("8/2 \" %06o \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'b': | ||||
| 			odprecede(); | ||||
| 			add("16/1 \"%03o \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 			odprecede(); | ||||
| 			add("16/1 \"%3_c \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'd': | ||||
| 			odprecede(); | ||||
| 			add("8/2 \"  %05u \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'D': | ||||
| 			odprecede(); | ||||
| 			add("4/4 \"     %010u \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'e':		/* undocumented in od */ | ||||
| 		case 'F': | ||||
| 			odprecede(); | ||||
| 			add("2/8 \"          %21.14e \" \"\\n\""); | ||||
| 			break; | ||||
| 			 | ||||
| 		case 'f': | ||||
| 			odprecede(); | ||||
| 			add("4/4 \" %14.7e \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'H': | ||||
| 		case 'X': | ||||
| 			odprecede(); | ||||
| 			add("4/4 \"       %08x \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'h': | ||||
| 		case 'x': | ||||
| 			odprecede(); | ||||
| 			add("8/2 \"   %04x \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'I': | ||||
| 		case 'L': | ||||
| 		case 'l': | ||||
| 			odprecede(); | ||||
| 			add("4/4 \"    %11d \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'i': | ||||
| 			odprecede(); | ||||
| 			add("8/2 \" %6d \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'O': | ||||
| 			odprecede(); | ||||
| 			add("4/4 \"    %011o \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'v': | ||||
| 			vflag = ALL; | ||||
| 			break; | ||||
| 		case 'P': | ||||
| 		case 'p': | ||||
| 		case 's': | ||||
| 		case 'w': | ||||
| 		case '?': | ||||
| 		default: | ||||
| 			error_msg("od: od(1) has been deprecated for hexdump(1).\n"); | ||||
| 			if (ch != '?') { | ||||
| 				error_msg("od: hexdump(1) compatibility doesn't support the -%c option%s\n", | ||||
| 				    ch, ch == 's' ? "; see strings(1)." : "."); | ||||
| 			} | ||||
| 			show_usage(); | ||||
| 		} | ||||
|  | ||||
| 	if (!fshead) { | ||||
| 		add("\"%07.7_Ao\n\""); | ||||
| 		add("\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\""); | ||||
| 	} | ||||
|  | ||||
| 	argc -= optind; | ||||
| 	argv += optind; | ||||
|  | ||||
| 	odoffset(argc, &argv); | ||||
|  | ||||
| 	return(dump(argv)); | ||||
| } | ||||
|  | ||||
| /*- | ||||
|  * 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. All advertising materials mentioning features or use of this software | ||||
|  *    must display the following acknowledgement: | ||||
|  *	This product includes software developed by the University of | ||||
|  *	California, Berkeley and its contributors. | ||||
|  * 4. 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. | ||||
|  */ | ||||
| @@ -200,6 +200,9 @@ | ||||
| #ifdef CONFIG_HEAD | ||||
| 	APPLET(head, head_main, _BB_DIR_USR_BIN) | ||||
| #endif | ||||
| #ifdef CONFIG_HEXDUMP | ||||
| 	APPLET(hexdump, hexdump_main, _BB_DIR_USR_BIN) | ||||
| #endif | ||||
| #ifdef CONFIG_HOSTID | ||||
| 	APPLET(hostid, hostid_main, _BB_DIR_USR_BIN) | ||||
| #endif | ||||
| @@ -317,6 +320,9 @@ | ||||
| #ifdef CONFIG_NSLOOKUP | ||||
| 	APPLET(nslookup, nslookup_main, _BB_DIR_USR_BIN) | ||||
| #endif | ||||
| #ifdef CONFIG_OD | ||||
| 	APPLET(od, od_main, _BB_DIR_USR_BIN) | ||||
| #endif | ||||
| #ifdef CONFIG_PIDOF | ||||
| 	APPLET(pidof, pidof_main, _BB_DIR_BIN) | ||||
| #endif | ||||
|   | ||||
| @@ -646,6 +646,23 @@ | ||||
| 	"root:x:0:0:root:/root:/bin/bash\n" \ | ||||
| 	"daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n" | ||||
|  | ||||
| #define hexdump_trivial_usage \ | ||||
| 	"[-[bcdefnosvx]] [OPTION] FILE" | ||||
| #define hexdump_full_usage \ | ||||
| 	"The hexdump utility is a filter which displays the specified files,\n" \ | ||||
| 	"or the standard input, if no files are specified, in a user specified\n"\ | ||||
| 	"format\n" \ | ||||
| 	"\t-b\t\tOne-byte octal display\n" \ | ||||
| 	"\t-c\t\tOne-byte character display\n" \ | ||||
| 	"\t-d\t\tTwo-byte decimal display\n" \ | ||||
| 	"\t-e FORMAT STRING\n" \ | ||||
| 	"\t-f FORMAT FILE\n" \ | ||||
| 	"\t-n LENGTH\tInterpret only length bytes of input\n" \ | ||||
| 	"\t-o\t\tTwo-byte octal display\n" \ | ||||
| 	"\t-s OFFSET\tSkip offset byte\n" \ | ||||
| 	"\t-v\t\tdisplay all input data\n" \ | ||||
| 	"\t-x\t\tTwo-byte hexadecimal display\n" | ||||
|  | ||||
| #define hostid_trivial_usage \ | ||||
| 	"" | ||||
| #define hostid_full_usage \ | ||||
| @@ -1249,6 +1266,12 @@ | ||||
| 	"Name:       debian\n" \ | ||||
| 	"Address:    127.0.0.1\n"  | ||||
|  | ||||
| #define od_trivial_usage \ | ||||
| 	"[-aBbcDdeFfHhIiLlOovXx] [FILE]" | ||||
| #define od_full_usage \ | ||||
| 	"Write an unambiguous representation, octal bytes by default, of FILE\n"\ | ||||
| 	"to standard output.  With no FILE, or when FILE is -, read standard input." | ||||
|  | ||||
| #define pidof_trivial_usage \ | ||||
| 	"process-name [process-name ...]" | ||||
| #define pidof_full_usage \ | ||||
|   | ||||
| @@ -32,7 +32,7 @@ obj-n           := | ||||
| obj-            := | ||||
|  | ||||
| obj-y += ask_confirmation.o chomp.o concat_path_file.o copy_file.o \ | ||||
| 	copy_file_chunk.o libc5.o device_open.o error_msg.o \ | ||||
| 	copy_file_chunk.o dump.o libc5.o device_open.o error_msg.o \ | ||||
| 	error_msg_and_die.o fgets_str.o find_mount_point.o find_pid_by_name.o \ | ||||
| 	find_root_device.o full_read.o full_write.o get_console.o \ | ||||
| 	get_last_path_component.o get_line_from_file.o gz_open.o human_readable.o \ | ||||
|   | ||||
							
								
								
									
										863
									
								
								libbb/dump.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										863
									
								
								libbb/dump.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,863 @@ | ||||
| /* | ||||
|  * Support code for the hexdump and od applets, | ||||
|  * based on code from util-linux v 2.11l | ||||
|  * | ||||
|  * Copyright (c) 1989 | ||||
|  *	The Regents of the University of California.  All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
|  * | ||||
|  * Original copyright notice is retained at the end of this file. | ||||
|  */ | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <ctype.h>		/* for isdigit() */ | ||||
| #include "dump.h" | ||||
| #include "libbb.h" | ||||
|  | ||||
| enum _vflag vflag = FIRST; | ||||
| FS *fshead;				/* head of format strings */ | ||||
| extern FS *fshead;				/* head of format strings */ | ||||
| extern int blocksize; | ||||
| static FU *endfu; | ||||
| static char **_argv; | ||||
| static off_t savaddress;		/* saved address/offset in stream */ | ||||
| static off_t eaddress;			/* end address */ | ||||
| static off_t address;			/* address/offset in stream */ | ||||
| off_t skip;                      /* bytes to skip */ | ||||
| off_t saveaddress; | ||||
| int exitval;				/* final exit value */ | ||||
| int blocksize;				/* data block size */ | ||||
| int length = -1;			/* max bytes to read */ | ||||
|  | ||||
|  | ||||
| int size(FS *fs) | ||||
| { | ||||
| 	register FU *fu; | ||||
| 	register int bcnt, cursize; | ||||
| 	register char *fmt; | ||||
| 	int prec; | ||||
|  | ||||
| 	/* figure out the data block size needed for each format unit */ | ||||
| 	for (cursize = 0, fu = fs->nextfu; fu; fu = fu->nextfu) { | ||||
| 		if (fu->bcnt) { | ||||
| 			cursize += fu->bcnt * fu->reps; | ||||
| 			continue; | ||||
| 		} | ||||
| 		for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) { | ||||
| 			if (*fmt != '%') | ||||
| 				continue; | ||||
| 			/* | ||||
| 			 * skip any special chars -- save precision in | ||||
| 			 * case it's a %s format. | ||||
| 			 */ | ||||
| 			while (index(".#-+ 0123456789" + 1, *++fmt)); | ||||
| 			if (*fmt == '.' && isdigit(*++fmt)) { | ||||
| 				prec = atoi(fmt); | ||||
| 				while (isdigit(*++fmt)); | ||||
| 			} | ||||
| 			switch(*fmt) { | ||||
| 			case 'c': | ||||
| 				bcnt += 1; | ||||
| 				break; | ||||
| 			case 'd': case 'i': case 'o': case 'u': | ||||
| 			case 'x': case 'X': | ||||
| 				bcnt += 4; | ||||
| 				break; | ||||
| 			case 'e': case 'E': case 'f': case 'g': case 'G': | ||||
| 				bcnt += 8; | ||||
| 				break; | ||||
| 			case 's': | ||||
| 				bcnt += prec; | ||||
| 				break; | ||||
| 			case '_': | ||||
| 				switch(*++fmt) { | ||||
| 				case 'c': case 'p': case 'u': | ||||
| 					bcnt += 1; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		cursize += bcnt * fu->reps; | ||||
| 	} | ||||
| 	return(cursize); | ||||
| } | ||||
|  | ||||
| void rewrite(FS *fs) | ||||
| { | ||||
| 	enum { NOTOKAY, USEBCNT, USEPREC } sokay; | ||||
| 	register PR *pr, **nextpr = NULL; | ||||
| 	register FU *fu; | ||||
| 	register char *p1, *p2; | ||||
| 	char savech, *fmtp; | ||||
| 	int nconv, prec = 0; | ||||
|  | ||||
| 	for (fu = fs->nextfu; fu; fu = fu->nextfu) { | ||||
| 		/* | ||||
| 		 * break each format unit into print units; each | ||||
| 		 * conversion character gets its own. | ||||
| 		 */ | ||||
| 		for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) { | ||||
| 			/* NOSTRICT */ | ||||
| 			pr = (PR *)xmalloc(sizeof(PR)); | ||||
| 			if (!fu->nextpr) | ||||
| 				fu->nextpr = pr; | ||||
| 			else | ||||
| 				*nextpr = pr; | ||||
|  | ||||
| 			/* skip preceding text and up to the next % sign */ | ||||
| 			for (p1 = fmtp; *p1 && *p1 != '%'; ++p1); | ||||
|  | ||||
| 			/* only text in the string */ | ||||
| 			if (!*p1) { | ||||
| 				pr->fmt = fmtp; | ||||
| 				pr->flags = F_TEXT; | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			/* | ||||
| 			 * get precision for %s -- if have a byte count, don't | ||||
| 			 * need it. | ||||
| 			 */ | ||||
| 			if (fu->bcnt) { | ||||
| 				sokay = USEBCNT; | ||||
| 				/* skip to conversion character */ | ||||
| 				for (++p1; index(".#-+ 0123456789", *p1); ++p1); | ||||
| 			} else { | ||||
| 				/* skip any special chars, field width */ | ||||
| 				while (index(".#-+ 0123456789" + 1, *++p1)); | ||||
| 				if (*p1 == '.' && isdigit(*++p1)) { | ||||
| 					sokay = USEPREC; | ||||
| 					prec = atoi(p1); | ||||
| 					while (isdigit(*++p1)); | ||||
| 				} | ||||
| 				else | ||||
| 					sokay = NOTOKAY; | ||||
| 			} | ||||
|  | ||||
| 			p2 = p1 + 1;		/* set end pointer */ | ||||
|  | ||||
| 			/* | ||||
| 			 * figure out the byte count for each conversion; | ||||
| 			 * rewrite the format as necessary, set up blank- | ||||
| 			 * padding for end of data. | ||||
| 			 */ | ||||
| 			switch(*p1) { | ||||
| 			case 'c': | ||||
| 				pr->flags = F_CHAR; | ||||
| 				switch(fu->bcnt) { | ||||
| 				case 0: case 1: | ||||
| 					pr->bcnt = 1; | ||||
| 					break; | ||||
| 				default: | ||||
| 					p1[1] = '\0'; | ||||
| 					error_msg_and_die("bad byte count for conversion character %s.", p1); | ||||
| 				} | ||||
| 				break; | ||||
| 			case 'd': case 'i': | ||||
| 				pr->flags = F_INT; | ||||
| 				goto sw1; | ||||
| 			case 'l': | ||||
| 				++p2; | ||||
| 				switch(p1[1]) { | ||||
| 				case 'd': case 'i': | ||||
| 					++p1; | ||||
| 					pr->flags = F_INT; | ||||
| 					goto sw1; | ||||
| 				case 'o': case 'u': case 'x': case 'X': | ||||
| 					++p1; | ||||
| 					pr->flags = F_UINT; | ||||
| 					goto sw1; | ||||
| 				default: | ||||
| 					p1[2] = '\0'; | ||||
| 					error_msg_and_die("hexdump: bad conversion character %%%s.\n", p1); | ||||
| 				} | ||||
| 				/* NOTREACHED */ | ||||
| 			case 'o': case 'u': case 'x': case 'X': | ||||
| 				pr->flags = F_UINT; | ||||
| sw1:				switch(fu->bcnt) { | ||||
| 				case 0: case 4: | ||||
| 					pr->bcnt = 4; | ||||
| 					break; | ||||
| 				case 1: | ||||
| 					pr->bcnt = 1; | ||||
| 					break; | ||||
| 				case 2: | ||||
| 					pr->bcnt = 2; | ||||
| 					break; | ||||
| 				default: | ||||
| 					p1[1] = '\0'; | ||||
| 					error_msg_and_die("bad byte count for conversion character %s.", p1); | ||||
| 				} | ||||
| 				break; | ||||
| 			case 'e': case 'E': case 'f': case 'g': case 'G': | ||||
| 				pr->flags = F_DBL; | ||||
| 				switch(fu->bcnt) { | ||||
| 				case 0: case 8: | ||||
| 					pr->bcnt = 8; | ||||
| 					break; | ||||
| 				case 4: | ||||
| 					pr->bcnt = 4; | ||||
| 					break; | ||||
| 				default: | ||||
| 					p1[1] = '\0'; | ||||
| 					error_msg_and_die("bad byte count for conversion character %s.", p1); | ||||
| 				} | ||||
| 				break; | ||||
| 			case 's': | ||||
| 				pr->flags = F_STR; | ||||
| 				switch(sokay) { | ||||
| 				case NOTOKAY: | ||||
| 					error_msg_and_die("%%s requires a precision or a byte count."); | ||||
| 				case USEBCNT: | ||||
| 					pr->bcnt = fu->bcnt; | ||||
| 					break; | ||||
| 				case USEPREC: | ||||
| 					pr->bcnt = prec; | ||||
| 					break; | ||||
| 				} | ||||
| 				break; | ||||
| 			case '_': | ||||
| 				++p2; | ||||
| 				switch(p1[1]) { | ||||
| 				case 'A': | ||||
| 					endfu = fu; | ||||
| 					fu->flags |= F_IGNORE; | ||||
| 					/* FALLTHROUGH */ | ||||
| 				case 'a': | ||||
| 					pr->flags = F_ADDRESS; | ||||
| 					++p2; | ||||
| 					switch(p1[2]) { | ||||
| 					case 'd': case 'o': case'x': | ||||
| 						*p1 = p1[2]; | ||||
| 						break; | ||||
| 					default: | ||||
| 						p1[3] = '\0'; | ||||
| 						error_msg_and_die("hexdump: bad conversion character %%%s.\n", p1); | ||||
| 					} | ||||
| 					break; | ||||
| 				case 'c': | ||||
| 					pr->flags = F_C; | ||||
| 					/* *p1 = 'c';	set in conv_c */ | ||||
| 					goto sw2; | ||||
| 				case 'p': | ||||
| 					pr->flags = F_P; | ||||
| 					*p1 = 'c'; | ||||
| 					goto sw2; | ||||
| 				case 'u': | ||||
| 					pr->flags = F_U; | ||||
| 					/* *p1 = 'c';	set in conv_u */ | ||||
| sw2:					switch(fu->bcnt) { | ||||
| 					case 0: case 1: | ||||
| 						pr->bcnt = 1; | ||||
| 						break; | ||||
| 					default: | ||||
| 						p1[2] = '\0'; | ||||
| 						error_msg_and_die("bad byte count for conversion character %s.", p1); | ||||
| 					} | ||||
| 					break; | ||||
| 				default: | ||||
| 					p1[2] = '\0'; | ||||
| 					error_msg_and_die("hexdump: bad conversion character %%%s.\n", p1); | ||||
| 				} | ||||
| 				break; | ||||
| 			default: | ||||
| 				p1[1] = '\0'; | ||||
| 				error_msg_and_die("hexdump: bad conversion character %%%s.\n", p1); | ||||
| 			} | ||||
|  | ||||
| 			/* | ||||
| 			 * copy to PR format string, set conversion character | ||||
| 			 * pointer, update original. | ||||
| 			 */ | ||||
| 			savech = *p2; | ||||
| 			p1[1] = '\0'; | ||||
| 			if (!(pr->fmt = strdup(fmtp))) | ||||
| 				perror_msg_and_die("hexdump"); | ||||
| 			*p2 = savech; | ||||
| 			pr->cchar = pr->fmt + (p1 - fmtp); | ||||
| 			fmtp = p2; | ||||
|  | ||||
| 			/* only one conversion character if byte count */ | ||||
| 			if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++) { | ||||
| 				error_msg_and_die("hexdump: byte count with multiple conversion characters.\n"); | ||||
| 			} | ||||
| 		} | ||||
| 		/* | ||||
| 		 * if format unit byte count not specified, figure it out | ||||
| 		 * so can adjust rep count later. | ||||
| 		 */ | ||||
| 		if (!fu->bcnt) | ||||
| 			for (pr = fu->nextpr; pr; pr = pr->nextpr) | ||||
| 				fu->bcnt += pr->bcnt; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * if the format string interprets any data at all, and it's | ||||
| 	 * not the same as the blocksize, and its last format unit | ||||
| 	 * interprets any data at all, and has no iteration count, | ||||
| 	 * repeat it as necessary. | ||||
| 	 * | ||||
| 	 * if, rep count is greater than 1, no trailing whitespace | ||||
| 	 * gets output from the last iteration of the format unit. | ||||
| 	 */ | ||||
| 	for (fu = fs->nextfu;; fu = fu->nextfu) { | ||||
| 		if (!fu->nextfu && fs->bcnt < blocksize && | ||||
| 		    !(fu->flags&F_SETREP) && fu->bcnt) | ||||
| 			fu->reps += (blocksize - fs->bcnt) / fu->bcnt; | ||||
| 		if (fu->reps > 1) { | ||||
| 			for (pr = fu->nextpr;; pr = pr->nextpr) | ||||
| 				if (!pr->nextpr) | ||||
| 					break; | ||||
| 			for (p1 = pr->fmt, p2 = NULL; *p1; ++p1) | ||||
| 				p2 = isspace(*p1) ? p1 : NULL; | ||||
| 			if (p2) | ||||
| 				pr->nospace = p2; | ||||
| 		} | ||||
| 		if (!fu->nextfu) | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void doskip(char *fname, int statok) | ||||
| { | ||||
| 	struct stat sbuf; | ||||
|  | ||||
| 	if (statok) { | ||||
| 		if (fstat(fileno(stdin), &sbuf)) { | ||||
| 			perror_msg_and_die("hexdump: %s", fname); | ||||
| 		} | ||||
| 		if ( ( ! (S_ISCHR(sbuf.st_mode) || | ||||
|  			  S_ISBLK(sbuf.st_mode) || | ||||
|  			  S_ISFIFO(sbuf.st_mode)) ) && | ||||
| 		     skip >= sbuf.st_size) { | ||||
| 		  /* If size valid and skip >= size */ | ||||
| 			skip -= sbuf.st_size; | ||||
| 			address += sbuf.st_size; | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 	if (fseek(stdin, skip, SEEK_SET)) { | ||||
| 		perror_msg_and_die("hexdump: %s", fname); | ||||
| 	} | ||||
| 	savaddress = address += skip; | ||||
| 	skip = 0; | ||||
| } | ||||
|  | ||||
| int next(char **argv) | ||||
| { | ||||
| 	static int done; | ||||
| 	int statok; | ||||
|  | ||||
| 	if (argv) { | ||||
| 		_argv = argv; | ||||
| 		return(1); | ||||
| 	} | ||||
| 	for (;;) { | ||||
| 		if (*_argv) { | ||||
| 			if (!(freopen(*_argv, "r", stdin))) { | ||||
| 				perror_msg("%s", *_argv); | ||||
| 				exitval = 1; | ||||
| 				++_argv; | ||||
| 				continue; | ||||
| 			} | ||||
| 			statok = done = 1; | ||||
| 		} else { | ||||
| 			if (done++) | ||||
| 				return(0); | ||||
| 			statok = 0; | ||||
| 		} | ||||
| 		if (skip) | ||||
| 			doskip(statok ? *_argv : "stdin", statok); | ||||
| 		if (*_argv) | ||||
| 			++_argv; | ||||
| 		if (!skip) | ||||
| 			return(1); | ||||
| 	} | ||||
| 	/* NOTREACHED */ | ||||
| } | ||||
|  | ||||
| static u_char * | ||||
| get(void) | ||||
| { | ||||
| 	static int ateof = 1; | ||||
| 	static u_char *curp, *savp; | ||||
| 	register int n; | ||||
| 	int need, nread; | ||||
| 	u_char *tmpp; | ||||
|  | ||||
| 	if (!curp) { | ||||
| 		curp = (u_char *)xmalloc(blocksize); | ||||
| 		savp = (u_char *)xmalloc(blocksize); | ||||
| 	} else { | ||||
| 		tmpp = curp; | ||||
| 		curp = savp; | ||||
| 		savp = tmpp; | ||||
| 		address = savaddress += blocksize; | ||||
| 	} | ||||
| 	for (need = blocksize, nread = 0;;) { | ||||
| 		/* | ||||
| 		 * if read the right number of bytes, or at EOF for one file, | ||||
| 		 * and no other files are available, zero-pad the rest of the | ||||
| 		 * block and set the end flag. | ||||
| 		 */ | ||||
| 		if (!length || (ateof && !next((char **)NULL))) { | ||||
| 			if (need == blocksize) { | ||||
| 				return((u_char *)NULL); | ||||
| 			} | ||||
| 			if (vflag != ALL && !bcmp(curp, savp, nread)) { | ||||
| 				if (vflag != DUP) { | ||||
| 					printf("*\n"); | ||||
| 				} | ||||
| 				return((u_char *)NULL); | ||||
| 			} | ||||
| 			bzero((char *)curp + nread, need); | ||||
| 			eaddress = address + nread; | ||||
| 			return(curp); | ||||
| 		} | ||||
| 		n = fread((char *)curp + nread, sizeof(u_char), | ||||
| 		    length == -1 ? need : MIN(length, need), stdin); | ||||
| 		if (!n) { | ||||
| 			if (ferror(stdin)) { | ||||
| 				perror_msg("%s", _argv[-1]); | ||||
| 			} | ||||
| 			ateof = 1; | ||||
| 			continue; | ||||
| 		} | ||||
| 		ateof = 0; | ||||
| 		if (length != -1) { | ||||
| 			length -= n; | ||||
| 		} | ||||
| 		if (!(need -= n)) { | ||||
| 			if (vflag == ALL || vflag == FIRST || | ||||
| 			    bcmp(curp, savp, blocksize)) { | ||||
| 				if (vflag == DUP || vflag == FIRST) { | ||||
| 					vflag = WAIT; | ||||
| 				} | ||||
| 				return(curp); | ||||
| 			} | ||||
| 			if (vflag == WAIT) { | ||||
| 				printf("*\n"); | ||||
| 			} | ||||
| 			vflag = DUP; | ||||
| 			address = savaddress += blocksize; | ||||
| 			need = blocksize; | ||||
| 			nread = 0; | ||||
| 		} else { | ||||
| 			nread += n; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void bpad(PR *pr) | ||||
| { | ||||
| 	register char *p1, *p2; | ||||
|  | ||||
| 	/* | ||||
| 	 * remove all conversion flags; '-' is the only one valid | ||||
| 	 * with %s, and it's not useful here. | ||||
| 	 */ | ||||
| 	pr->flags = F_BPAD; | ||||
| 	*pr->cchar = 's'; | ||||
| 	for (p1 = pr->fmt; *p1 != '%'; ++p1); | ||||
| 	for (p2 = ++p1; *p1 && index(" -0+#", *p1); ++p1); | ||||
| 	while ((*p2++ = *p1++) != 0) ; | ||||
| } | ||||
|  | ||||
| void conv_c(PR *pr, u_char *p) | ||||
| { | ||||
| 	char buf[10], *str; | ||||
|  | ||||
| 	switch(*p) { | ||||
| 	case '\0': | ||||
| 		str = "\\0"; | ||||
| 		goto strpr; | ||||
| 	/* case '\a': */ | ||||
| 	case '\007': | ||||
| 		str = "\\a"; | ||||
| 		goto strpr; | ||||
| 	case '\b': | ||||
| 		str = "\\b"; | ||||
| 		goto strpr; | ||||
| 	case '\f': | ||||
| 		str = "\\f"; | ||||
| 		goto strpr; | ||||
| 	case '\n': | ||||
| 		str = "\\n"; | ||||
| 		goto strpr; | ||||
| 	case '\r': | ||||
| 		str = "\\r"; | ||||
| 		goto strpr; | ||||
| 	case '\t': | ||||
| 		str = "\\t"; | ||||
| 		goto strpr; | ||||
| 	case '\v': | ||||
| 		str = "\\v"; | ||||
| 		goto strpr; | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| 	if (isprint(*p)) { | ||||
| 		*pr->cchar = 'c'; | ||||
| 		(void)printf(pr->fmt, *p); | ||||
| 	} else { | ||||
| 		sprintf(str = buf, "%03o", (int)*p); | ||||
| strpr: | ||||
| 		*pr->cchar = 's'; | ||||
| 		printf(pr->fmt, str); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void conv_u(PR *pr, u_char *p) | ||||
| { | ||||
| 	static char *list[] = { | ||||
| 		"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", | ||||
| 		 "bs",  "ht",  "lf",  "vt",  "ff",  "cr",  "so",  "si", | ||||
| 		"dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb", | ||||
| 		"can",  "em", "sub", "esc",  "fs",  "gs",  "rs",  "us", | ||||
| 	}; | ||||
|  | ||||
| 	/* od used nl, not lf */ | ||||
| 	if (*p <= 0x1f) { | ||||
| 		*pr->cchar = 's'; | ||||
| 		printf(pr->fmt, list[*p]); | ||||
| 	} else if (*p == 0x7f) { | ||||
| 		*pr->cchar = 's'; | ||||
| 		printf(pr->fmt, "del"); | ||||
| 	} else if (isprint(*p)) { | ||||
| 		*pr->cchar = 'c'; | ||||
| 		printf(pr->fmt, *p); | ||||
| 	} else { | ||||
| 		*pr->cchar = 'x'; | ||||
| 		printf(pr->fmt, (int)*p); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void display(void) | ||||
| { | ||||
| //	extern FU *endfu; | ||||
| 	register FS *fs; | ||||
| 	register FU *fu; | ||||
| 	register PR *pr; | ||||
| 	register int cnt; | ||||
| 	register u_char *bp; | ||||
| //	off_t saveaddress; | ||||
| 	u_char savech = 0, *savebp; | ||||
|  | ||||
| 	while ((bp = get()) != NULL) { | ||||
| 	    for (fs = fshead, savebp = bp, saveaddress = address; fs; | ||||
| 				fs = fs->nextfs, bp = savebp, address = saveaddress) { | ||||
| 		    for (fu = fs->nextfu; fu; fu = fu->nextfu) { | ||||
| 				if (fu->flags & F_IGNORE) { | ||||
| 					break; | ||||
| 				} | ||||
| 				for (cnt = fu->reps; cnt; --cnt) { | ||||
| 				    for (pr = fu->nextpr; pr; address += pr->bcnt, | ||||
| 							bp += pr->bcnt, pr = pr->nextpr) { | ||||
| 					    if (eaddress && address >= eaddress && | ||||
| 								!(pr->flags&(F_TEXT|F_BPAD))) { | ||||
| 							bpad(pr); | ||||
| 						} | ||||
| 					    if (cnt == 1 && pr->nospace) { | ||||
| 							savech = *pr->nospace; | ||||
| 							*pr->nospace = '\0'; | ||||
| 					    } | ||||
| //					    PRINT; | ||||
| 						switch(pr->flags) { | ||||
| 							case F_ADDRESS: | ||||
| 								printf(pr->fmt, address); | ||||
| 								break; | ||||
| 							case F_BPAD: | ||||
| 								printf(pr->fmt, ""); | ||||
| 								break; | ||||
| 							case F_C: | ||||
| 								conv_c(pr, bp); | ||||
| 								break; | ||||
| 							case F_CHAR: | ||||
| 								printf(pr->fmt, *bp); | ||||
| 								break; | ||||
| 							case F_DBL: { | ||||
| 								double dval; | ||||
| 								float fval; | ||||
| 								switch(pr->bcnt) { | ||||
| 									case 4: | ||||
| 										bcopy((char *)bp, (char *)&fval, sizeof(fval)); | ||||
| 										printf(pr->fmt, fval); | ||||
| 										break; | ||||
| 									case 8: | ||||
| 										bcopy((char *)bp, (char *)&dval, sizeof(dval)); | ||||
| 										printf(pr->fmt, dval); | ||||
| 										break; | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 							case F_INT: { | ||||
| 								int ival; | ||||
| 								short sval; | ||||
| 								switch(pr->bcnt) { | ||||
| 									case 1: | ||||
| 										printf(pr->fmt, (int)*bp); | ||||
| 										break; | ||||
| 									case 2: | ||||
| 										bcopy((char *)bp, (char *)&sval, sizeof(sval)); | ||||
| 										printf(pr->fmt, (int)sval); | ||||
| 										break; | ||||
| 									case 4: | ||||
| 										bcopy((char *)bp, (char *)&ival, sizeof(ival)); | ||||
| 										printf(pr->fmt, ival); | ||||
| 										break; | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 							case F_P: | ||||
| 								printf(pr->fmt, isprint(*bp) ? *bp : '.'); | ||||
| 								break; | ||||
| 							case F_STR: | ||||
| 								printf(pr->fmt, (char *)bp); | ||||
| 								break; | ||||
| 							case F_TEXT: | ||||
| 								printf(pr->fmt); | ||||
| 								break; | ||||
| 							case F_U: | ||||
| 								conv_u(pr, bp); | ||||
| 								break; | ||||
| 							case F_UINT: { | ||||
| 								u_int ival; | ||||
| 								u_short sval; | ||||
| 								switch(pr->bcnt) { | ||||
| 									case 1: | ||||
| 										printf(pr->fmt, (u_int)*bp); | ||||
| 										break; | ||||
| 									case 2: | ||||
| 										bcopy((char *)bp, (char *)&sval, sizeof(sval)); | ||||
| 										printf(pr->fmt, (u_int)sval); | ||||
| 										break; | ||||
| 									case 4: | ||||
| 										bcopy((char *)bp, (char *)&ival, sizeof(ival)); | ||||
| 										printf(pr->fmt, ival); | ||||
| 										break; | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 						} | ||||
| 				 	   if (cnt == 1 && pr->nospace) { | ||||
| 							*pr->nospace = savech; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if (endfu) { | ||||
| 		/* | ||||
| 		 * if eaddress not set, error or file size was multiple of | ||||
| 		 * blocksize, and no partial block ever found. | ||||
| 		 */ | ||||
| 		if (!eaddress) { | ||||
| 			if (!address) { | ||||
| 				return; | ||||
| 			} | ||||
| 			eaddress = address; | ||||
| 		} | ||||
| 		for (pr = endfu->nextpr; pr; pr = pr->nextpr) { | ||||
| 			switch(pr->flags) { | ||||
| 			case F_ADDRESS: | ||||
| 				(void)printf(pr->fmt, eaddress); | ||||
| 				break; | ||||
| 			case F_TEXT: | ||||
| 				(void)printf(pr->fmt); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int dump(char **argv) | ||||
| { | ||||
| 	register FS *tfs; | ||||
|  | ||||
| 	/* figure out the data block size */ | ||||
| 	for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) { | ||||
| 		tfs->bcnt = size(tfs); | ||||
| 		if (blocksize < tfs->bcnt) { | ||||
| 			blocksize = tfs->bcnt; | ||||
| 		} | ||||
| 	} | ||||
| 	/* rewrite the rules, do syntax checking */ | ||||
| 	for (tfs = fshead; tfs; tfs = tfs->nextfs) { | ||||
| 		rewrite(tfs); | ||||
| 	} | ||||
|  | ||||
| 	next(argv); | ||||
| 	display(); | ||||
|  | ||||
| 	return(exitval); | ||||
| } | ||||
|  | ||||
| void add(char *fmt) | ||||
| { | ||||
| 	register char *p; | ||||
| 	register char *p1; | ||||
| 	register char *p2; | ||||
| 	static FS **nextfs; | ||||
| 	FS *tfs; | ||||
| 	FU *tfu, **nextfu; | ||||
| 	char *savep; | ||||
|  | ||||
| 	/* start new linked list of format units */ | ||||
| 	/* NOSTRICT */ | ||||
| 	tfs = (FS *)xmalloc(sizeof(FS)); | ||||
| 	if (!fshead) { | ||||
| 		fshead = tfs; | ||||
| 	} else { | ||||
| 		*nextfs = tfs; | ||||
| 	} | ||||
| 	nextfs = &tfs->nextfs; | ||||
| 	nextfu = &tfs->nextfu; | ||||
|  | ||||
| 	/* take the format string and break it up into format units */ | ||||
| 	for (p = fmt;;) { | ||||
| 		/* skip leading white space */ | ||||
| 		for (; isspace(*p); ++p); | ||||
| 		if (!*p) { | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		/* allocate a new format unit and link it in */ | ||||
| 		/* NOSTRICT */ | ||||
| 		tfu = (FU *)xmalloc(sizeof(FU)); | ||||
| 		*nextfu = tfu; | ||||
| 		nextfu = &tfu->nextfu; | ||||
| 		tfu->reps = 1; | ||||
|  | ||||
| 		/* if leading digit, repetition count */ | ||||
| 		if (isdigit(*p)) { | ||||
| 			for (savep = p; isdigit(*p); ++p); | ||||
| 			if (!isspace(*p) && *p != '/') { | ||||
| 				error_msg_and_die("hexdump: bad format {%s}", fmt); | ||||
| 			} | ||||
| 			/* may overwrite either white space or slash */ | ||||
| 			tfu->reps = atoi(savep); | ||||
| 			tfu->flags = F_SETREP; | ||||
| 			/* skip trailing white space */ | ||||
| 			for (++p; isspace(*p); ++p); | ||||
| 		} | ||||
|  | ||||
| 		/* skip slash and trailing white space */ | ||||
| 		if (*p == '/') { | ||||
| 			while (isspace(*++p)); | ||||
| 		} | ||||
|  | ||||
| 		/* byte count */ | ||||
| 		if (isdigit(*p)) { | ||||
| 			for (savep = p; isdigit(*p); ++p); | ||||
| 			if (!isspace(*p)) { | ||||
| 				error_msg_and_die("hexdump: bad format {%s}", fmt); | ||||
| 			} | ||||
| 			tfu->bcnt = atoi(savep); | ||||
| 			/* skip trailing white space */ | ||||
| 			for (++p; isspace(*p); ++p); | ||||
| 		} | ||||
|  | ||||
| 		/* format */ | ||||
| 		if (*p != '"') { | ||||
| 			error_msg_and_die("hexdump: bad format {%s}", fmt); | ||||
| 		} | ||||
| 		for (savep = ++p; *p != '"';) { | ||||
| 			if (*p++ == 0) { | ||||
| 				error_msg_and_die("hexdump: bad format {%s}", fmt); | ||||
| 			} | ||||
| 		} | ||||
| 		if (!(tfu->fmt = malloc(p - savep + 1))) { | ||||
| 			perror_msg_and_die("hexdump"); | ||||
| 		} | ||||
| 		strncpy(tfu->fmt, savep, p - savep); | ||||
| 		tfu->fmt[p - savep] = '\0'; | ||||
| //		escape(tfu->fmt); | ||||
|  | ||||
| 		p1 = tfu->fmt; | ||||
|  | ||||
| 		/* alphabetic escape sequences have to be done in place */ | ||||
| 		for (p2 = p1;; ++p1, ++p2) { | ||||
| 			if (!*p1) { | ||||
| 				*p2 = *p1; | ||||
| 				break; | ||||
| 			} | ||||
| 			if (*p1 == '\\') { | ||||
| 				switch(*++p1) { | ||||
| 				case 'a': | ||||
| 				     /* *p2 = '\a'; */ | ||||
| 					*p2 = '\007'; | ||||
| 					break; | ||||
| 				case 'b': | ||||
| 					*p2 = '\b'; | ||||
| 					break; | ||||
| 				case 'f': | ||||
| 					*p2 = '\f'; | ||||
| 					break; | ||||
| 				case 'n': | ||||
| 					*p2 = '\n'; | ||||
| 					break; | ||||
| 				case 'r': | ||||
| 					*p2 = '\r'; | ||||
| 					break; | ||||
| 				case 't': | ||||
| 					*p2 = '\t'; | ||||
| 					break; | ||||
| 				case 'v': | ||||
| 					*p2 = '\v'; | ||||
| 					break; | ||||
| 				default: | ||||
| 					*p2 = *p1; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		p++; | ||||
| 	} | ||||
| } | ||||
| /* | ||||
|  * Copyright (c) 1989 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. All advertising materials mentioning features or use of this software | ||||
|  *    must display the following acknowledgement: | ||||
|  *	This product includes software developed by the University of | ||||
|  *	California, Berkeley and its contributors. | ||||
|  * 4. 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. | ||||
|  */ | ||||
| @@ -30,6 +30,7 @@ obj-$(CONFIG_FDFLUSH)		+= fdflush.o | ||||
| obj-$(CONFIG_FREERAMDISK)	+= freeramdisk.o | ||||
| obj-$(CONFIG_FSCK_MINIX)	+= fsck_minix.o | ||||
| obj-$(CONFIG_GETOPT)		+= getopt.o | ||||
| obj-$(CONFIG_HEXDUMP)		+= hexdump.o | ||||
| obj-$(CONFIG_MKFS_MINIX)	+= mkfs_minix.o | ||||
| obj-$(CONFIG_MKSWAP)		+= mkswap.o | ||||
| obj-$(CONFIG_MORE)		+= more.o | ||||
|   | ||||
| @@ -13,6 +13,7 @@ bool 'fdflush'		    CONFIG_FDFLUSH | ||||
| bool 'freeramdisk'	    CONFIG_FREERAMDISK | ||||
| bool 'fsck_minix'	    CONFIG_FSCK_MINIX | ||||
| bool 'getopt'		    CONFIG_GETOPT | ||||
| bool 'hexdump'  	    CONFIG_HEXDUMP   | ||||
| bool 'mkfs_minix'	    CONFIG_MKFS_MINIX | ||||
| bool 'mkswap'		    CONFIG_MKSWAP | ||||
| bool 'more'		    CONFIG_MORE | ||||
|   | ||||
							
								
								
									
										169
									
								
								util-linux/hexdump.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								util-linux/hexdump.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| /* | ||||
|  * hexdump implementation for busybox | ||||
|  * Based on code from util-linux v 2.11l | ||||
|  * | ||||
|  * Copyright (c) 1989 | ||||
|  *	The Regents of the University of California.  All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
|  * | ||||
|  * Original copyright notice is retained at the end of this file. | ||||
|  */ | ||||
|  | ||||
| #include <getopt.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include "dump.h" | ||||
| #include "busybox.h" | ||||
|  | ||||
| extern off_t skip;                      /* bytes to skip */ | ||||
|  | ||||
| extern FS *fshead;				/* head of format strings */ | ||||
| extern int blocksize;				/* data block size */ | ||||
| extern int length;			/* max bytes to read */ | ||||
|  | ||||
| void addfile(char *name) | ||||
| { | ||||
| 	register char *p; | ||||
| 	FILE *fp; | ||||
| 	int ch; | ||||
| 	char buf[2048 + 1]; | ||||
|  | ||||
| 	if (!(fp = fopen(name, "r"))) { | ||||
| 		error_msg_and_die("hexdump: can't read %s.\n", name); | ||||
| 	} | ||||
| 	while (fgets(buf, sizeof(buf), fp)) { | ||||
| 		if (!(p = index(buf, '\n'))) { | ||||
| 			error_msg("hexdump: line too long.\n"); | ||||
| 			while ((ch = getchar()) != '\n' && ch != EOF); | ||||
| 			continue; | ||||
| 		} | ||||
| 		*p = '\0'; | ||||
| 		for (p = buf; *p && isspace(*p); ++p); | ||||
| 		if (!*p || *p == '#') { | ||||
| 			continue; | ||||
| 		} | ||||
| 		add(p); | ||||
| 	} | ||||
| 	(void)fclose(fp); | ||||
| } | ||||
|  | ||||
| int hexdump_main(int argc, char **argv) | ||||
| { | ||||
| //	register FS *tfs; | ||||
| 	char *p; | ||||
| 	int ch; | ||||
| 	extern enum _vflag vflag; | ||||
| 	vflag = FIRST; | ||||
| 	length = -1; | ||||
|  | ||||
| 	while ((ch = getopt(argc, argv, "bcde:f:n:os:vx")) != EOF) { | ||||
| 		switch (ch) { | ||||
| 		case 'b': | ||||
| 			add("\"%07.7_Ax\n\""); | ||||
| 			add("\"%07.7_ax \" 16/1 \"%03o \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 			add("\"%07.7_Ax\n\""); | ||||
| 			add("\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'd': | ||||
| 			add("\"%07.7_Ax\n\""); | ||||
| 			add("\"%07.7_ax \" 8/2 \"  %05u \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 'e': | ||||
| 			add(optarg); | ||||
| 			break; | ||||
| 		case 'f': | ||||
| 			addfile(optarg); | ||||
| 			break; | ||||
| 		case 'n': | ||||
| 			if ((length = atoi(optarg)) < 0) { | ||||
| 				error_msg_and_die("hexdump: bad length value.\n"); | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'o': | ||||
| 			add("\"%07.7_Ax\n\""); | ||||
| 			add("\"%07.7_ax \" 8/2 \" %06o \" \"\\n\""); | ||||
| 			break; | ||||
| 		case 's': | ||||
| 			if ((skip = strtol(optarg, &p, 0)) < 0) { | ||||
| 				error_msg_and_die("hexdump: bad skip value.\n"); | ||||
| 			} | ||||
| 			switch(*p) { | ||||
| 				case 'b': | ||||
| 					skip *= 512; | ||||
| 					break; | ||||
| 				case 'k': | ||||
| 					skip *= 1024; | ||||
| 					break; | ||||
| 				case 'm': | ||||
| 					skip *= 1048576; | ||||
| 					break; | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'v': | ||||
| 			vflag = ALL; | ||||
| 			break; | ||||
| 		case 'x': | ||||
| 			add("\"%07.7_Ax\n\""); | ||||
| 			add("\"%07.7_ax \" 8/2 \"   %04x \" \"\\n\""); | ||||
| 			break; | ||||
| 		case '?': | ||||
| 			show_usage(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!fshead) { | ||||
| 		add("\"%07.7_Ax\n\""); | ||||
| 		add("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\""); | ||||
| 	} | ||||
|  | ||||
| 	argv += optind; | ||||
|  | ||||
| 	return(dump(argv)); | ||||
| } | ||||
| /* | ||||
|  * Copyright (c) 1989 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. All advertising materials mentioning features or use of this software | ||||
|  *    must display the following acknowledgement: | ||||
|  *	This product includes software developed by the University of | ||||
|  *	California, Berkeley and its contributors. | ||||
|  * 4. 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. | ||||
|  */ | ||||
		Reference in New Issue
	
	Block a user