(root)/
util-linux-2.39/
text-utils/
hexdump.c
       1  /*
       2   * Copyright (c) 1989 The Regents of the University of California.
       3   * All rights reserved.
       4   *
       5   * Redistribution and use in source and binary forms, with or without
       6   * modification, are permitted provided that the following conditions
       7   * are met:
       8   * 1. Redistributions of source code must retain the above copyright
       9   *    notice, this list of conditions and the following disclaimer.
      10   * 2. Redistributions in binary form must reproduce the above copyright
      11   *    notice, this list of conditions and the following disclaimer in the
      12   *    documentation and/or other materials provided with the distribution.
      13   * 3. All advertising materials mentioning features or use of this software
      14   *    must display the following acknowledgement:
      15   *	This product includes software developed by the University of
      16   *	California, Berkeley and its contributors.
      17   * 4. Neither the name of the University nor the names of its contributors
      18   *    may be used to endorse or promote products derived from this software
      19   *    without specific prior written permission.
      20   *
      21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      25   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31   * SUCH DAMAGE.
      32   */
      33  
      34   /* 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
      35    * - added Native Language Support
      36    */
      37  
      38  #include <sys/types.h>
      39  #include <unistd.h>
      40  #include <stdio.h>
      41  #include <string.h>
      42  #include <stdlib.h>
      43  #include <errno.h>
      44  #include <err.h>
      45  #include <limits.h>
      46  #include <getopt.h>
      47  #include "hexdump.h"
      48  
      49  #include "list.h"
      50  #include "nls.h"
      51  #include "c.h"
      52  #include "colors.h"
      53  #include "strutils.h"
      54  #include "xalloc.h"
      55  #include "closestream.h"
      56  
      57  void hex_free(struct hexdump *);
      58  
      59  int
      60  parse_args(int argc, char **argv, struct hexdump *hex)
      61  {
      62  	int ch;
      63  	int colormode = UL_COLORMODE_UNDEF;
      64  	char *hex_offt = "\"%07.7_Ax\n\"";
      65  
      66  
      67  	static const struct option longopts[] = {
      68  		{"one-byte-octal", no_argument, NULL, 'b'},
      69  		{"one-byte-char", no_argument, NULL, 'c'},
      70  		{"canonical", no_argument, NULL, 'C'},
      71  		{"two-bytes-decimal", no_argument, NULL, 'd'},
      72  		{"two-bytes-octal", no_argument, NULL, 'o'},
      73  		{"two-bytes-hex", no_argument, NULL, 'x'},
      74  		{"format", required_argument, NULL, 'e'},
      75  		{"format-file", required_argument, NULL, 'f'},
      76  		{"color", optional_argument, NULL, 'L'},
      77  		{"length", required_argument, NULL, 'n'},
      78  		{"skip", required_argument, NULL, 's'},
      79  		{"no-squeezing", no_argument, NULL, 'v'},
      80  		{"help", no_argument, NULL, 'h'},
      81  		{"version", no_argument, NULL, 'V'},
      82  		{NULL, no_argument, NULL, 0}
      83  	};
      84  
      85  	while ((ch = getopt_long(argc, argv, "bcCde:f:L::n:os:vxhV", longopts, NULL)) != -1) {
      86  		switch (ch) {
      87  		case 'b':
      88  			add_fmt(hex_offt, hex);
      89  			add_fmt("\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"", hex);
      90  			break;
      91  		case 'c':
      92  			add_fmt(hex_offt, hex);
      93  			add_fmt("\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"", hex);
      94  			break;
      95  		case 'C':
      96  			add_fmt("\"%08.8_Ax\n\"", hex);
      97  			add_fmt("\"%08.8_ax  \" 8/1 \"%02x \" \"  \" 8/1 \"%02x \" ", hex);
      98  			add_fmt("\"  |\" 16/1 \"%_p\" \"|\\n\"", hex);
      99  			break;
     100  		case 'd':
     101  			add_fmt(hex_offt, hex);
     102  			add_fmt("\"%07.7_ax \" 8/2 \"  %05u \" \"\\n\"", hex);
     103  			break;
     104  		case 'e':
     105  			add_fmt(optarg, hex);
     106  			break;
     107  		case 'f':
     108  			addfile(optarg, hex);
     109  			break;
     110  		case 'L':
     111  			colormode = UL_COLORMODE_AUTO;
     112  			if (optarg)
     113  				colormode = colormode_or_err(optarg,
     114  						_("unsupported color mode"));
     115                          break;
     116  		case 'n':
     117  			hex->length = strtosize_or_err(optarg, _("failed to parse length"));
     118  			break;
     119  		case 'o':
     120  			add_fmt(hex_offt, hex);
     121  			add_fmt("\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"", hex);
     122  			break;
     123  		case 's':
     124  			hex->skip = strtosize_or_err(optarg, _("failed to parse offset"));
     125  			break;
     126  		case 'v':
     127  			vflag = ALL;
     128  			break;
     129  		case 'x':
     130  			add_fmt(hex_offt, hex);
     131  			add_fmt("\"%07.7_ax \" 8/2 \"   %04x \" \"\\n\"", hex);
     132  			break;
     133  
     134  		case 'h':
     135  			usage();
     136  		case 'V':
     137  			print_version(EXIT_SUCCESS);
     138  		default:
     139  			errtryhelp(EXIT_FAILURE);
     140  		}
     141  	}
     142  
     143  	if (list_empty(&hex->fshead)) {
     144  		if (!strcmp(program_invocation_short_name, "hd")) {
     145  			/* Canonical format */
     146  			add_fmt("\"%08.8_Ax\n\"", hex);
     147  			add_fmt("\"%08.8_ax  \" 8/1 \"%02x \" \"  \" 8/1 \"%02x \" ", hex);
     148  			add_fmt("\"  |\" 16/1 \"%_p\" \"|\\n\"", hex);
     149  		} else {
     150  			add_fmt(hex_offt, hex);
     151  			add_fmt("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"", hex);
     152  		}
     153  	}
     154  	colors_init (colormode, "hexdump");
     155  	return optind;
     156  }
     157  
     158  void __attribute__((__noreturn__)) usage(void)
     159  {
     160  	FILE *out = stdout;
     161  	fputs(USAGE_HEADER, out);
     162  	fprintf(out, _(" %s [options] <file>...\n"), program_invocation_short_name);
     163  
     164  	fputs(USAGE_SEPARATOR, out);
     165  	fputs(_("Display file contents in hexadecimal, decimal, octal, or ascii.\n"), out);
     166  
     167  	fputs(USAGE_OPTIONS, out);
     168  	fputs(_(" -b, --one-byte-octal      one-byte octal display\n"), out);
     169  	fputs(_(" -c, --one-byte-char       one-byte character display\n"), out);
     170  	fputs(_(" -C, --canonical           canonical hex+ASCII display\n"), out);
     171  	fputs(_(" -d, --two-bytes-decimal   two-byte decimal display\n"), out);
     172  	fputs(_(" -o, --two-bytes-octal     two-byte octal display\n"), out);
     173  	fputs(_(" -x, --two-bytes-hex       two-byte hexadecimal display\n"), out);
     174  	fputs(_(" -L, --color[=<mode>]      interpret color formatting specifiers\n"), out);
     175  	fprintf(out,
     176  	        "                             %s\n", USAGE_COLORS_DEFAULT);
     177  	fputs(_(" -e, --format <format>     format string to be used for displaying data\n"), out);
     178  	fputs(_(" -f, --format-file <file>  file that contains format strings\n"), out);
     179  	fputs(_(" -n, --length <length>     interpret only length bytes of input\n"), out);
     180  	fputs(_(" -s, --skip <offset>       skip offset bytes from the beginning\n"), out);
     181  	fputs(_(" -v, --no-squeezing        output identical lines\n"), out);
     182  
     183  	fputs(USAGE_SEPARATOR, out);
     184  	printf(USAGE_HELP_OPTIONS(27));
     185  
     186  	fputs(USAGE_ARGUMENTS, out);
     187  	printf(USAGE_ARG_SIZE(_("<length> and <offset>")));
     188  
     189  	printf(USAGE_MAN_TAIL("hexdump(1)"));
     190  	exit(EXIT_SUCCESS);
     191  }
     192  
     193  int main(int argc, char **argv)
     194  {
     195  	struct list_head *p;
     196  	struct hexdump_fs *tfs;
     197  	int ret;
     198  
     199  	struct hexdump *hex = xcalloc(1, sizeof (struct hexdump));
     200  	hex->length = -1;
     201  	INIT_LIST_HEAD(&hex->fshead);
     202  
     203  	setlocale(LC_ALL, "");
     204  	bindtextdomain(PACKAGE, LOCALEDIR);
     205  	textdomain(PACKAGE);
     206  	close_stdout_atexit();
     207  
     208  	argv += parse_args(argc, argv, hex);
     209  
     210  	/* figure out the data block size */
     211  	hex->blocksize = 0;
     212  	list_for_each(p, &hex->fshead) {
     213  		tfs = list_entry(p, struct hexdump_fs, fslist);
     214  		if ((tfs->bcnt = block_size(tfs)) > hex->blocksize)
     215  			hex->blocksize = tfs->bcnt;
     216  	}
     217  
     218  	/* rewrite the rules, do syntax checking */
     219  	list_for_each(p, &hex->fshead)
     220  		rewrite_rules(list_entry(p, struct hexdump_fs, fslist), hex);
     221  
     222  	next(argv, hex);
     223  	display(hex);
     224  
     225  	ret = hex->exitval;
     226  	hex_free(hex);
     227  
     228  	return ret;
     229  }
     230  
     231  void hex_free(struct hexdump *hex)
     232  {
     233  	struct list_head *p, *pn, *q, *qn, *r, *rn, *s, *sn;
     234  	struct hexdump_fs *fs;
     235  	struct hexdump_fu *fu;
     236  	struct hexdump_pr *pr;
     237  	struct hexdump_clr *clr;
     238  
     239  	list_for_each_safe(p, pn, &hex->fshead) {
     240  		fs = list_entry(p, struct hexdump_fs, fslist);
     241  		list_for_each_safe(q, qn, &fs->fulist) {
     242  			fu = list_entry(q, struct hexdump_fu, fulist);
     243  			list_for_each_safe(r, rn, &fu->prlist) {
     244  				pr = list_entry(r, struct hexdump_pr, prlist);
     245  				if (pr->colorlist) {
     246  					list_for_each_safe(s, sn, pr->colorlist) {
     247  						clr = list_entry (s, struct hexdump_clr, colorlist);
     248  						free(clr->str);
     249  						free(clr);
     250  					}
     251  				}
     252  				free(pr->fmt);
     253  				free(pr);
     254  			}
     255  			free(fu->fmt);
     256  			free(fu);
     257  		}
     258  		free(fs);
     259  	}
     260  	free (hex);
     261  }