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 }