1*44704f69SBart Van Assche /*
2*44704f69SBart Van Assche * Copyright (c) 2004-2019 Douglas Gilbert.
3*44704f69SBart Van Assche * All rights reserved.
4*44704f69SBart Van Assche * Use of this source code is governed by a BSD-style
5*44704f69SBart Van Assche * license that can be found in the BSD_LICENSE file.
6*44704f69SBart Van Assche *
7*44704f69SBart Van Assche * SPDX-License-Identifier: BSD-2-Clause
8*44704f69SBart Van Assche */
9*44704f69SBart Van Assche
10*44704f69SBart Van Assche #include <stdlib.h>
11*44704f69SBart Van Assche #include <stdio.h>
12*44704f69SBart Van Assche #include <stdint.h>
13*44704f69SBart Van Assche #include <unistd.h>
14*44704f69SBart Van Assche #include <sys/types.h>
15*44704f69SBart Van Assche #include <sys/stat.h>
16*44704f69SBart Van Assche #include <fcntl.h>
17*44704f69SBart Van Assche #include <string.h>
18*44704f69SBart Van Assche #include <ctype.h>
19*44704f69SBart Van Assche #include <errno.h>
20*44704f69SBart Van Assche #define __STDC_FORMAT_MACROS 1
21*44704f69SBart Van Assche #include <inttypes.h>
22*44704f69SBart Van Assche
23*44704f69SBart Van Assche #define DEF_BYTES_PER_LINE 16
24*44704f69SBart Van Assche
25*44704f69SBart Van Assche static int bytes_per_line = DEF_BYTES_PER_LINE;
26*44704f69SBart Van Assche
27*44704f69SBart Van Assche static const char * version_str = "1.11 20190527";
28*44704f69SBart Van Assche
29*44704f69SBart Van Assche #define CHARS_PER_HEX_BYTE 3
30*44704f69SBart Van Assche #define BINARY_START_COL 6
31*44704f69SBart Van Assche #define MAX_LINE_LENGTH 257
32*44704f69SBart Van Assche
33*44704f69SBart Van Assche
34*44704f69SBart Van Assche #ifdef SG_LIB_MINGW
35*44704f69SBart Van Assche /* Non Unix OSes distinguish between text and binary files.
36*44704f69SBart Van Assche Set text mode on fd. Does nothing in Unix. Returns negative number on
37*44704f69SBart Van Assche failure. */
38*44704f69SBart Van Assche int
sg_set_text_mode(int fd)39*44704f69SBart Van Assche sg_set_text_mode(int fd)
40*44704f69SBart Van Assche {
41*44704f69SBart Van Assche return setmode(fd, O_TEXT);
42*44704f69SBart Van Assche }
43*44704f69SBart Van Assche
44*44704f69SBart Van Assche /* Set binary mode on fd. Does nothing in Unix. Returns negative number on
45*44704f69SBart Van Assche failure. */
46*44704f69SBart Van Assche int
sg_set_binary_mode(int fd)47*44704f69SBart Van Assche sg_set_binary_mode(int fd)
48*44704f69SBart Van Assche {
49*44704f69SBart Van Assche return setmode(fd, O_BINARY);
50*44704f69SBart Van Assche }
51*44704f69SBart Van Assche
52*44704f69SBart Van Assche #else
53*44704f69SBart Van Assche /* For Unix the following functions are dummies. */
54*44704f69SBart Van Assche int
sg_set_text_mode(int fd)55*44704f69SBart Van Assche sg_set_text_mode(int fd)
56*44704f69SBart Van Assche {
57*44704f69SBart Van Assche return fd; /* fd should be >= 0 */
58*44704f69SBart Van Assche }
59*44704f69SBart Van Assche
60*44704f69SBart Van Assche int
sg_set_binary_mode(int fd)61*44704f69SBart Van Assche sg_set_binary_mode(int fd)
62*44704f69SBart Van Assche {
63*44704f69SBart Van Assche return fd;
64*44704f69SBart Van Assche }
65*44704f69SBart Van Assche #endif
66*44704f69SBart Van Assche
67*44704f69SBart Van Assche /* Returns the number of times 'ch' is found in string 's' given the
68*44704f69SBart Van Assche * string's length. */
69*44704f69SBart Van Assche static int
num_chs_in_str(const char * s,int slen,int ch)70*44704f69SBart Van Assche num_chs_in_str(const char * s, int slen, int ch)
71*44704f69SBart Van Assche {
72*44704f69SBart Van Assche int res = 0;
73*44704f69SBart Van Assche
74*44704f69SBart Van Assche while (--slen >= 0) {
75*44704f69SBart Van Assche if (ch == s[slen])
76*44704f69SBart Van Assche ++res;
77*44704f69SBart Van Assche }
78*44704f69SBart Van Assche return res;
79*44704f69SBart Van Assche }
80*44704f69SBart Van Assche
81*44704f69SBart Van Assche /* If the number in 'buf' can be decoded or the multiplier is unknown
82*44704f69SBart Van Assche * then -1LL is returned. Accepts a hex prefix (0x or 0X) or a decimal
83*44704f69SBart Van Assche * multiplier suffix (as per GNU's dd (since 2002: SI and IEC 60027-2)).
84*44704f69SBart Van Assche * Main (SI) multipliers supported: K, M, G, T, P. Ignore leading spaces
85*44704f69SBart Van Assche * and tabs; accept comma, hyphen, space, tab and hash as terminator. */
86*44704f69SBart Van Assche int64_t
sg_get_llnum(const char * buf)87*44704f69SBart Van Assche sg_get_llnum(const char * buf)
88*44704f69SBart Van Assche {
89*44704f69SBart Van Assche int res, len, n;
90*44704f69SBart Van Assche int64_t num, ll;
91*44704f69SBart Van Assche uint64_t unum;
92*44704f69SBart Van Assche char * cp;
93*44704f69SBart Van Assche const char * b;
94*44704f69SBart Van Assche char c = 'c';
95*44704f69SBart Van Assche char c2 = '\0'; /* keep static checker happy */
96*44704f69SBart Van Assche char c3 = '\0'; /* keep static checker happy */
97*44704f69SBart Van Assche char lb[32];
98*44704f69SBart Van Assche
99*44704f69SBart Van Assche if ((NULL == buf) || ('\0' == buf[0]))
100*44704f69SBart Van Assche return -1LL;
101*44704f69SBart Van Assche len = strlen(buf);
102*44704f69SBart Van Assche n = strspn(buf, " \t");
103*44704f69SBart Van Assche if (n > 0) {
104*44704f69SBart Van Assche if (n == len)
105*44704f69SBart Van Assche return -1LL;
106*44704f69SBart Van Assche buf += n;
107*44704f69SBart Van Assche len -= n;
108*44704f69SBart Van Assche }
109*44704f69SBart Van Assche /* following hack to keep C++ happy */
110*44704f69SBart Van Assche cp = strpbrk((char *)buf, " \t,#-");
111*44704f69SBart Van Assche if (cp) {
112*44704f69SBart Van Assche len = cp - buf;
113*44704f69SBart Van Assche n = (int)sizeof(lb) - 1;
114*44704f69SBart Van Assche len = (len < n) ? len : n;
115*44704f69SBart Van Assche memcpy(lb, buf, len);
116*44704f69SBart Van Assche lb[len] = '\0';
117*44704f69SBart Van Assche b = lb;
118*44704f69SBart Van Assche } else
119*44704f69SBart Van Assche b = buf;
120*44704f69SBart Van Assche if (('0' == b[0]) && (('x' == b[1]) || ('X' == b[1]))) {
121*44704f69SBart Van Assche res = sscanf(b + 2, "%" SCNx64 , &unum);
122*44704f69SBart Van Assche num = unum;
123*44704f69SBart Van Assche } else if ('H' == toupper((int)b[len - 1])) {
124*44704f69SBart Van Assche res = sscanf(b, "%" SCNx64 , &unum);
125*44704f69SBart Van Assche num = unum;
126*44704f69SBart Van Assche } else
127*44704f69SBart Van Assche res = sscanf(b, "%" SCNd64 "%c%c%c", &num, &c, &c2, &c3);
128*44704f69SBart Van Assche if (res < 1)
129*44704f69SBart Van Assche return -1LL;
130*44704f69SBart Van Assche else if (1 == res)
131*44704f69SBart Van Assche return num;
132*44704f69SBart Van Assche else {
133*44704f69SBart Van Assche if (res > 2)
134*44704f69SBart Van Assche c2 = toupper((int)c2);
135*44704f69SBart Van Assche if (res > 3)
136*44704f69SBart Van Assche c3 = toupper((int)c3);
137*44704f69SBart Van Assche switch (toupper((int)c)) {
138*44704f69SBart Van Assche case 'C':
139*44704f69SBart Van Assche return num;
140*44704f69SBart Van Assche case 'W':
141*44704f69SBart Van Assche return num * 2;
142*44704f69SBart Van Assche case 'B':
143*44704f69SBart Van Assche return num * 512;
144*44704f69SBart Van Assche case 'K':
145*44704f69SBart Van Assche if (2 == res)
146*44704f69SBart Van Assche return num * 1024;
147*44704f69SBart Van Assche if (('B' == c2) || ('D' == c2))
148*44704f69SBart Van Assche return num * 1000;
149*44704f69SBart Van Assche if (('I' == c2) && (4 == res) && ('B' == c3))
150*44704f69SBart Van Assche return num * 1024;
151*44704f69SBart Van Assche return -1LL;
152*44704f69SBart Van Assche case 'M':
153*44704f69SBart Van Assche if (2 == res)
154*44704f69SBart Van Assche return num * 1048576;
155*44704f69SBart Van Assche if (('B' == c2) || ('D' == c2))
156*44704f69SBart Van Assche return num * 1000000;
157*44704f69SBart Van Assche if (('I' == c2) && (4 == res) && ('B' == c3))
158*44704f69SBart Van Assche return num * 1048576;
159*44704f69SBart Van Assche return -1LL;
160*44704f69SBart Van Assche case 'G':
161*44704f69SBart Van Assche if (2 == res)
162*44704f69SBart Van Assche return num * 1073741824;
163*44704f69SBart Van Assche if (('B' == c2) || ('D' == c2))
164*44704f69SBart Van Assche return num * 1000000000;
165*44704f69SBart Van Assche if (('I' == c2) && (4 == res) && ('B' == c3))
166*44704f69SBart Van Assche return num * 1073741824;
167*44704f69SBart Van Assche return -1LL;
168*44704f69SBart Van Assche case 'T':
169*44704f69SBart Van Assche if (2 == res)
170*44704f69SBart Van Assche return num * 1099511627776LL;
171*44704f69SBart Van Assche if (('B' == c2) || ('D' == c2))
172*44704f69SBart Van Assche return num * 1000000000000LL;
173*44704f69SBart Van Assche if (('I' == c2) && (4 == res) && ('B' == c3))
174*44704f69SBart Van Assche return num * 1099511627776LL;
175*44704f69SBart Van Assche return -1LL;
176*44704f69SBart Van Assche case 'P':
177*44704f69SBart Van Assche if (2 == res)
178*44704f69SBart Van Assche return num * 1099511627776LL * 1024;
179*44704f69SBart Van Assche if (('B' == c2) || ('D' == c2))
180*44704f69SBart Van Assche return num * 1000000000000LL * 1000;
181*44704f69SBart Van Assche if (('I' == c2) && (4 == res) && ('B' == c3))
182*44704f69SBart Van Assche return num * 1099511627776LL * 1024;
183*44704f69SBart Van Assche return -1LL;
184*44704f69SBart Van Assche case 'X':
185*44704f69SBart Van Assche cp = (char *)strchr(b, 'x');
186*44704f69SBart Van Assche if (NULL == cp)
187*44704f69SBart Van Assche cp = (char *)strchr(b, 'X');
188*44704f69SBart Van Assche if (cp) {
189*44704f69SBart Van Assche ll = sg_get_llnum(cp + 1);
190*44704f69SBart Van Assche if (-1LL != ll)
191*44704f69SBart Van Assche return num * ll;
192*44704f69SBart Van Assche }
193*44704f69SBart Van Assche return -1LL;
194*44704f69SBart Van Assche default:
195*44704f69SBart Van Assche fprintf(stderr, "unrecognized multiplier\n");
196*44704f69SBart Van Assche return -1LL;
197*44704f69SBart Van Assche }
198*44704f69SBart Van Assche }
199*44704f69SBart Van Assche }
200*44704f69SBart Van Assche
201*44704f69SBart Van Assche static void
dStrHex(const char * str,int len,long start,int noAddr)202*44704f69SBart Van Assche dStrHex(const char* str, int len, long start, int noAddr)
203*44704f69SBart Van Assche {
204*44704f69SBart Van Assche const char* p = str;
205*44704f69SBart Van Assche unsigned char c;
206*44704f69SBart Van Assche char buff[MAX_LINE_LENGTH];
207*44704f69SBart Van Assche long a = start;
208*44704f69SBart Van Assche int bpstart, cpstart;
209*44704f69SBart Van Assche int j, k, line_length, nl, cpos, bpos, midline_space;
210*44704f69SBart Van Assche
211*44704f69SBart Van Assche if (noAddr) {
212*44704f69SBart Van Assche bpstart = 0;
213*44704f69SBart Van Assche cpstart = ((CHARS_PER_HEX_BYTE * bytes_per_line) + 1) + 5;
214*44704f69SBart Van Assche } else {
215*44704f69SBart Van Assche bpstart = BINARY_START_COL;
216*44704f69SBart Van Assche cpstart = BINARY_START_COL +
217*44704f69SBart Van Assche ((CHARS_PER_HEX_BYTE * bytes_per_line) + 1) + 5;
218*44704f69SBart Van Assche }
219*44704f69SBart Van Assche cpos = cpstart;
220*44704f69SBart Van Assche bpos = bpstart;
221*44704f69SBart Van Assche midline_space = ((bytes_per_line + 1) / 2);
222*44704f69SBart Van Assche
223*44704f69SBart Van Assche if (len <= 0)
224*44704f69SBart Van Assche return;
225*44704f69SBart Van Assche line_length = BINARY_START_COL +
226*44704f69SBart Van Assche (bytes_per_line * (1 + CHARS_PER_HEX_BYTE)) + 7;
227*44704f69SBart Van Assche if (line_length >= MAX_LINE_LENGTH) {
228*44704f69SBart Van Assche fprintf(stderr, "bytes_per_line causes maximum line length of %d "
229*44704f69SBart Van Assche "to be exceeded\n", MAX_LINE_LENGTH);
230*44704f69SBart Van Assche return;
231*44704f69SBart Van Assche }
232*44704f69SBart Van Assche memset(buff, ' ', line_length);
233*44704f69SBart Van Assche buff[line_length] = '\0';
234*44704f69SBart Van Assche if (0 == noAddr) {
235*44704f69SBart Van Assche k = sprintf(buff + 1, "%.2lx", a);
236*44704f69SBart Van Assche buff[k + 1] = ' ';
237*44704f69SBart Van Assche }
238*44704f69SBart Van Assche
239*44704f69SBart Van Assche for(j = 0; j < len; j++) {
240*44704f69SBart Van Assche nl = (0 == (j % bytes_per_line));
241*44704f69SBart Van Assche if ((j > 0) && nl) {
242*44704f69SBart Van Assche printf("%s\n", buff);
243*44704f69SBart Van Assche bpos = bpstart;
244*44704f69SBart Van Assche cpos = cpstart;
245*44704f69SBart Van Assche a += bytes_per_line;
246*44704f69SBart Van Assche memset(buff,' ', line_length);
247*44704f69SBart Van Assche if (0 == noAddr) {
248*44704f69SBart Van Assche k = sprintf(buff + 1, "%.2lx", a);
249*44704f69SBart Van Assche buff[k + 1] = ' ';
250*44704f69SBart Van Assche }
251*44704f69SBart Van Assche }
252*44704f69SBart Van Assche c = *p++;
253*44704f69SBart Van Assche bpos += (nl && noAddr) ? 0 : CHARS_PER_HEX_BYTE;
254*44704f69SBart Van Assche if ((bytes_per_line > 4) && ((j % bytes_per_line) == midline_space))
255*44704f69SBart Van Assche bpos++;
256*44704f69SBart Van Assche sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c);
257*44704f69SBart Van Assche buff[bpos + 2] = ' ';
258*44704f69SBart Van Assche if ((c < ' ') || (c >= 0x7f))
259*44704f69SBart Van Assche c='.';
260*44704f69SBart Van Assche buff[cpos++] = c;
261*44704f69SBart Van Assche }
262*44704f69SBart Van Assche if (cpos > cpstart)
263*44704f69SBart Van Assche printf("%s\n", buff);
264*44704f69SBart Van Assche }
265*44704f69SBart Van Assche
266*44704f69SBart Van Assche static void
dStrHexOnly(const char * str,int len,long start,int noAddr)267*44704f69SBart Van Assche dStrHexOnly(const char* str, int len, long start, int noAddr)
268*44704f69SBart Van Assche {
269*44704f69SBart Van Assche const char* p = str;
270*44704f69SBart Van Assche unsigned char c;
271*44704f69SBart Van Assche char buff[MAX_LINE_LENGTH];
272*44704f69SBart Van Assche long a = start;
273*44704f69SBart Van Assche int bpstart, bpos, nl;
274*44704f69SBart Van Assche int midline_space = ((bytes_per_line + 1) / 2);
275*44704f69SBart Van Assche int j, k, line_length;
276*44704f69SBart Van Assche
277*44704f69SBart Van Assche if (len <= 0)
278*44704f69SBart Van Assche return;
279*44704f69SBart Van Assche bpstart = (noAddr ? 0 : BINARY_START_COL);
280*44704f69SBart Van Assche bpos = bpstart;
281*44704f69SBart Van Assche line_length = (noAddr ? 0 : BINARY_START_COL) +
282*44704f69SBart Van Assche (bytes_per_line * CHARS_PER_HEX_BYTE) + 4;
283*44704f69SBart Van Assche if (line_length >= MAX_LINE_LENGTH) {
284*44704f69SBart Van Assche fprintf(stderr, "bytes_per_line causes maximum line length of %d "
285*44704f69SBart Van Assche "to be exceeded\n", MAX_LINE_LENGTH);
286*44704f69SBart Van Assche return;
287*44704f69SBart Van Assche }
288*44704f69SBart Van Assche memset(buff, ' ', line_length);
289*44704f69SBart Van Assche buff[line_length] = '\0';
290*44704f69SBart Van Assche if (0 == noAddr) {
291*44704f69SBart Van Assche k = sprintf(buff + 1, "%.2lx", a);
292*44704f69SBart Van Assche buff[k + 1] = ' ';
293*44704f69SBart Van Assche }
294*44704f69SBart Van Assche
295*44704f69SBart Van Assche for(j = 0; j < len; j++) {
296*44704f69SBart Van Assche nl = (0 == (j % bytes_per_line));
297*44704f69SBart Van Assche if ((j > 0) && nl) {
298*44704f69SBart Van Assche printf("%s\n", buff);
299*44704f69SBart Van Assche bpos = bpstart;
300*44704f69SBart Van Assche a += bytes_per_line;
301*44704f69SBart Van Assche memset(buff,' ', line_length);
302*44704f69SBart Van Assche if (0 == noAddr) {
303*44704f69SBart Van Assche k = sprintf(buff + 1, "%.2lx", a);
304*44704f69SBart Van Assche buff[k + 1] = ' ';
305*44704f69SBart Van Assche }
306*44704f69SBart Van Assche }
307*44704f69SBart Van Assche c = *p++;
308*44704f69SBart Van Assche bpos += (nl && noAddr) ? 0 : CHARS_PER_HEX_BYTE;
309*44704f69SBart Van Assche if ((bytes_per_line > 4) && ((j % bytes_per_line) == midline_space))
310*44704f69SBart Van Assche bpos++;
311*44704f69SBart Van Assche sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c);
312*44704f69SBart Van Assche buff[bpos + 2] = ' ';
313*44704f69SBart Van Assche }
314*44704f69SBart Van Assche if (bpos > bpstart)
315*44704f69SBart Van Assche printf("%s\n", buff);
316*44704f69SBart Van Assche }
317*44704f69SBart Van Assche
318*44704f69SBart Van Assche static void
usage()319*44704f69SBart Van Assche usage()
320*44704f69SBart Van Assche {
321*44704f69SBart Van Assche fprintf(stderr, "Usage: hxascdmp [-1] [-2] [-b=<n>] [-h] [-H] [-N] "
322*44704f69SBart Van Assche "[-o=<off>] [-q]\n"
323*44704f69SBart Van Assche " [-V] [-?] [<file>+]\n");
324*44704f69SBart Van Assche fprintf(stderr, " where:\n");
325*44704f69SBart Van Assche fprintf(stderr, " -1 print first byte in hex, prepend '0x' "
326*44704f69SBart Van Assche "if '-H' given\n");
327*44704f69SBart Van Assche fprintf(stderr, " -2 like '-1' but print first two bytes\n");
328*44704f69SBart Van Assche fprintf(stderr, " -b=<n> bytes per line to display "
329*44704f69SBart Van Assche "(def: 16)\n");
330*44704f69SBart Van Assche fprintf(stderr, " -h print this usage message\n");
331*44704f69SBart Van Assche fprintf(stderr, " -H print hex only (i.e. no ASCII "
332*44704f69SBart Van Assche "to right)\n");
333*44704f69SBart Van Assche fprintf(stderr, " -N no address, start in first column\n");
334*44704f69SBart Van Assche fprintf(stderr, " -o=<off> start decoding at byte <off>. Suffix "
335*44704f69SBart Van Assche "multipliers allowed\n");
336*44704f69SBart Van Assche fprintf(stderr, " -q quiet: suppress output of header "
337*44704f69SBart Van Assche "info\n");
338*44704f69SBart Van Assche fprintf(stderr, " -V print version string then exits\n");
339*44704f69SBart Van Assche fprintf(stderr, " -? print this usage message\n");
340*44704f69SBart Van Assche fprintf(stderr, " <file>+ reads file(s) and outputs each "
341*44704f69SBart Van Assche "as hex ASCII\n");
342*44704f69SBart Van Assche fprintf(stderr, " if no <file> then reads stdin\n\n");
343*44704f69SBart Van Assche fprintf(stderr, "Sends hex ASCII dump of stdin/file to stdout\n");
344*44704f69SBart Van Assche }
345*44704f69SBart Van Assche
346*44704f69SBart Van Assche int
main(int argc,const char ** argv)347*44704f69SBart Van Assche main(int argc, const char ** argv)
348*44704f69SBart Van Assche {
349*44704f69SBart Van Assche char buff[8192];
350*44704f69SBart Van Assche int num = 8192;
351*44704f69SBart Van Assche long start = 0;
352*44704f69SBart Van Assche int64_t offset = 0;
353*44704f69SBart Van Assche int res, k, u, len, n;
354*44704f69SBart Van Assche int inFile = STDIN_FILENO;
355*44704f69SBart Van Assche int doHelp = 0;
356*44704f69SBart Van Assche int doHex = 0;
357*44704f69SBart Van Assche int noAddr = 0;
358*44704f69SBart Van Assche int doVersion = 0;
359*44704f69SBart Van Assche int hasFilename = 0;
360*44704f69SBart Van Assche int quiet = 0;
361*44704f69SBart Van Assche int print1 = 0;
362*44704f69SBart Van Assche int print2 = 0;
363*44704f69SBart Van Assche int ret = 0;
364*44704f69SBart Van Assche const char * cp;
365*44704f69SBart Van Assche
366*44704f69SBart Van Assche for (k = 1; k < argc; k++) {
367*44704f69SBart Van Assche cp = argv[k];
368*44704f69SBart Van Assche len = strlen(cp);
369*44704f69SBart Van Assche if (0 == strncmp("-b=", cp, 3)) {
370*44704f69SBart Van Assche res = sscanf(cp + 3, "%d", &u);
371*44704f69SBart Van Assche if ((1 != res) || (u < 1)) {
372*44704f69SBart Van Assche fprintf(stderr, "Bad value after '-b=' option\n");
373*44704f69SBart Van Assche usage();
374*44704f69SBart Van Assche return 1;
375*44704f69SBart Van Assche }
376*44704f69SBart Van Assche bytes_per_line = u;
377*44704f69SBart Van Assche } else if (0 == strncmp("-o=", cp, 3)) {
378*44704f69SBart Van Assche int64_t off = sg_get_llnum(cp + 3);
379*44704f69SBart Van Assche
380*44704f69SBart Van Assche if (off == -1) {
381*44704f69SBart Van Assche fprintf(stderr, "Bad value after '-o=' option\n");
382*44704f69SBart Van Assche usage();
383*44704f69SBart Van Assche return 1;
384*44704f69SBart Van Assche }
385*44704f69SBart Van Assche offset = off;
386*44704f69SBart Van Assche } else if ((len > 1) && ('-' == cp[0]) && ('-' != cp[1])) {
387*44704f69SBart Van Assche res = 0;
388*44704f69SBart Van Assche n = num_chs_in_str(cp + 1, len - 1, '1');
389*44704f69SBart Van Assche print1 += n;
390*44704f69SBart Van Assche res += n;
391*44704f69SBart Van Assche n = num_chs_in_str(cp + 1, len - 1, '2');
392*44704f69SBart Van Assche print2 += n;
393*44704f69SBart Van Assche res += n;
394*44704f69SBart Van Assche n = num_chs_in_str(cp + 1, len - 1, 'h');
395*44704f69SBart Van Assche doHelp += n;
396*44704f69SBart Van Assche res += n;
397*44704f69SBart Van Assche n = num_chs_in_str(cp + 1, len - 1, 'H');
398*44704f69SBart Van Assche doHex += n;
399*44704f69SBart Van Assche res += n;
400*44704f69SBart Van Assche n = num_chs_in_str(cp + 1, len - 1, 'N');
401*44704f69SBart Van Assche noAddr += n;
402*44704f69SBart Van Assche res += n;
403*44704f69SBart Van Assche n = num_chs_in_str(cp + 1, len - 1, 'q');
404*44704f69SBart Van Assche quiet += n;
405*44704f69SBart Van Assche res += n;
406*44704f69SBart Van Assche n = num_chs_in_str(cp + 1, len - 1, 'V');
407*44704f69SBart Van Assche doVersion += n;
408*44704f69SBart Van Assche res += n;
409*44704f69SBart Van Assche n = num_chs_in_str(cp + 1, len - 1, '?');
410*44704f69SBart Van Assche doHelp += n;
411*44704f69SBart Van Assche res += n;
412*44704f69SBart Van Assche if (0 == res) {
413*44704f69SBart Van Assche fprintf(stderr, "No option recognized in str: %s\n", cp);
414*44704f69SBart Van Assche usage();
415*44704f69SBart Van Assche return 1;
416*44704f69SBart Van Assche }
417*44704f69SBart Van Assche } else if (0 == strcmp("-?", argv[k]))
418*44704f69SBart Van Assche ++doHelp;
419*44704f69SBart Van Assche else if (*argv[k] == '-') {
420*44704f69SBart Van Assche fprintf(stderr, "unknown switch: %s\n", argv[k]);
421*44704f69SBart Van Assche usage();
422*44704f69SBart Van Assche return 1;
423*44704f69SBart Van Assche } else {
424*44704f69SBart Van Assche hasFilename = 1;
425*44704f69SBart Van Assche break;
426*44704f69SBart Van Assche }
427*44704f69SBart Van Assche if (print2)
428*44704f69SBart Van Assche print1 += print2 + print2;
429*44704f69SBart Van Assche }
430*44704f69SBart Van Assche if (doVersion) {
431*44704f69SBart Van Assche printf("%s\n", version_str);
432*44704f69SBart Van Assche return 0;
433*44704f69SBart Van Assche }
434*44704f69SBart Van Assche if (doHelp) {
435*44704f69SBart Van Assche usage();
436*44704f69SBart Van Assche return 0;
437*44704f69SBart Van Assche }
438*44704f69SBart Van Assche
439*44704f69SBart Van Assche /* Make sure num to fetch is integral multiple of bytes_per_line */
440*44704f69SBart Van Assche if (0 != (num % bytes_per_line))
441*44704f69SBart Van Assche num = (num / bytes_per_line) * bytes_per_line;
442*44704f69SBart Van Assche
443*44704f69SBart Van Assche if (hasFilename) {
444*44704f69SBart Van Assche for ( ; k < argc; k++)
445*44704f69SBart Van Assche {
446*44704f69SBart Van Assche inFile = open(argv[k], O_RDONLY);
447*44704f69SBart Van Assche if (inFile < 0) {
448*44704f69SBart Van Assche fprintf(stderr, "Couldn't open file: %s\n", argv[k]);
449*44704f69SBart Van Assche ret = 1;
450*44704f69SBart Van Assche } else {
451*44704f69SBart Van Assche sg_set_binary_mode(inFile);
452*44704f69SBart Van Assche if (offset > 0) {
453*44704f69SBart Van Assche int err;
454*44704f69SBart Van Assche int64_t off_res;
455*44704f69SBart Van Assche
456*44704f69SBart Van Assche off_res = lseek(inFile, offset, SEEK_SET);
457*44704f69SBart Van Assche if (off_res < 0) {
458*44704f69SBart Van Assche err = errno;
459*44704f69SBart Van Assche fprintf(stderr, "failed moving filepos: wanted=%"
460*44704f69SBart Van Assche PRId64 " [0x%" PRIx64 "]\nlseek error: %s\n",
461*44704f69SBart Van Assche offset, offset, strerror(err));
462*44704f69SBart Van Assche goto fini1;
463*44704f69SBart Van Assche }
464*44704f69SBart Van Assche start = offset;
465*44704f69SBart Van Assche } else
466*44704f69SBart Van Assche start = 0;
467*44704f69SBart Van Assche if (! (doHex || quiet || print1))
468*44704f69SBart Van Assche printf("ASCII hex dump of file: %s\n", argv[k]);
469*44704f69SBart Van Assche while ((res = read(inFile, buff, num)) > 0) {
470*44704f69SBart Van Assche if (print1) {
471*44704f69SBart Van Assche if (1 == print1) {
472*44704f69SBart Van Assche if (doHex)
473*44704f69SBart Van Assche printf("0x%02x\n", (uint8_t)(buff[0]));
474*44704f69SBart Van Assche else
475*44704f69SBart Van Assche printf("%02x\n", (uint8_t)(buff[0]));
476*44704f69SBart Van Assche } else {
477*44704f69SBart Van Assche uint16_t us;
478*44704f69SBart Van Assche
479*44704f69SBart Van Assche memcpy(&us, buff, 2);
480*44704f69SBart Van Assche if (doHex)
481*44704f69SBart Van Assche printf("0x%04x\n", us);
482*44704f69SBart Van Assche else
483*44704f69SBart Van Assche printf("%04x\n", us);
484*44704f69SBart Van Assche }
485*44704f69SBart Van Assche break;
486*44704f69SBart Van Assche }
487*44704f69SBart Van Assche if (doHex)
488*44704f69SBart Van Assche dStrHexOnly(buff, res, start, noAddr);
489*44704f69SBart Van Assche else
490*44704f69SBart Van Assche dStrHex(buff, res, start, noAddr);
491*44704f69SBart Van Assche start += (long)res;
492*44704f69SBart Van Assche }
493*44704f69SBart Van Assche }
494*44704f69SBart Van Assche fini1:
495*44704f69SBart Van Assche close(inFile);
496*44704f69SBart Van Assche }
497*44704f69SBart Van Assche } else {
498*44704f69SBart Van Assche sg_set_binary_mode(inFile);
499*44704f69SBart Van Assche if (offset > 0) {
500*44704f69SBart Van Assche start = offset;
501*44704f69SBart Van Assche do { /* eat up offset bytes */
502*44704f69SBart Van Assche if ((res = read(inFile, buff,
503*44704f69SBart Van Assche (num > offset ? offset : num))) > 0)
504*44704f69SBart Van Assche offset -= res;
505*44704f69SBart Van Assche else {
506*44704f69SBart Van Assche fprintf(stderr, "offset read() error: %s\n",
507*44704f69SBart Van Assche strerror(errno));
508*44704f69SBart Van Assche break;
509*44704f69SBart Van Assche }
510*44704f69SBart Van Assche } while (offset > 0);
511*44704f69SBart Van Assche }
512*44704f69SBart Van Assche while ((res = read(inFile, buff, num)) > 0) {
513*44704f69SBart Van Assche if (doHex)
514*44704f69SBart Van Assche dStrHexOnly(buff, res, start, noAddr);
515*44704f69SBart Van Assche else
516*44704f69SBart Van Assche dStrHex(buff, res, start, noAddr);
517*44704f69SBart Van Assche start += (long)res;
518*44704f69SBart Van Assche }
519*44704f69SBart Van Assche }
520*44704f69SBart Van Assche return ret;
521*44704f69SBart Van Assche }
522