diff options
Diffstat (limited to 'libbb/dump.c')
-rw-r--r-- | libbb/dump.c | 517 |
1 files changed, 204 insertions, 313 deletions
diff --git a/libbb/dump.c b/libbb/dump.c index 1afad83fd..26dabe57f 100644 --- a/libbb/dump.c +++ b/libbb/dump.c | |||
@@ -25,94 +25,80 @@ | |||
25 | #include <stdlib.h> | 25 | #include <stdlib.h> |
26 | #include <string.h> | 26 | #include <string.h> |
27 | #include <ctype.h> /* for isdigit() */ | 27 | #include <ctype.h> /* for isdigit() */ |
28 | #include "dump.h" | ||
29 | #include "libbb.h" | 28 | #include "libbb.h" |
29 | #include "dump.h" | ||
30 | 30 | ||
31 | enum _vflag vflag = FIRST; | 31 | enum _vflag bb_dump_vflag = FIRST; |
32 | FS *fshead; /* head of format strings */ | 32 | FS *bb_dump_fshead; /* head of format strings */ |
33 | extern FS *fshead; /* head of format strings */ | ||
34 | extern int blocksize; | ||
35 | static FU *endfu; | 33 | static FU *endfu; |
36 | static char **_argv; | 34 | static char **_argv; |
37 | static off_t savaddress; /* saved address/offset in stream */ | 35 | static off_t savaddress; /* saved address/offset in stream */ |
38 | static off_t eaddress; /* end address */ | 36 | static off_t eaddress; /* end address */ |
39 | static off_t address; /* address/offset in stream */ | 37 | static off_t address; /* address/offset in stream */ |
40 | off_t skip; /* bytes to skip */ | 38 | off_t bb_dump_skip; /* bytes to skip */ |
41 | off_t saveaddress; | 39 | static int exitval; /* final exit value */ |
42 | int exitval; /* final exit value */ | 40 | int bb_dump_blocksize; /* data block size */ |
43 | int blocksize; /* data block size */ | 41 | int bb_dump_length = -1; /* max bytes to read */ |
44 | int length = -1; /* max bytes to read */ | 42 | |
43 | static const char index_str[] = ".#-+ 0123456789"; | ||
45 | 44 | ||
45 | static const char size_conv_str[] = | ||
46 | "\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG"; | ||
46 | 47 | ||
47 | int size(FS * fs) | 48 | static const char lcc[] = "diouxX"; |
49 | |||
50 | int bb_dump_size(FS * fs) | ||
48 | { | 51 | { |
49 | register FU *fu; | 52 | register FU *fu; |
50 | register int bcnt, cursize; | 53 | register int bcnt, cur_size; |
51 | register char *fmt; | 54 | register char *fmt; |
55 | const char *p; | ||
52 | int prec; | 56 | int prec; |
53 | 57 | ||
54 | /* figure out the data block size needed for each format unit */ | 58 | /* figure out the data block bb_dump_size needed for each format unit */ |
55 | for (cursize = 0, fu = fs->nextfu; fu; fu = fu->nextfu) { | 59 | for (cur_size = 0, fu = fs->nextfu; fu; fu = fu->nextfu) { |
56 | if (fu->bcnt) { | 60 | if (fu->bcnt) { |
57 | cursize += fu->bcnt * fu->reps; | 61 | cur_size += fu->bcnt * fu->reps; |
58 | continue; | 62 | continue; |
59 | } | 63 | } |
60 | for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) { | 64 | for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) { |
61 | if (*fmt != '%') | 65 | if (*fmt != '%') |
62 | continue; | 66 | continue; |
63 | /* | 67 | /* |
64 | * skip any special chars -- save precision in | 68 | * bb_dump_skip any special chars -- save precision in |
65 | * case it's a %s format. | 69 | * case it's a %s format. |
66 | */ | 70 | */ |
67 | while (index(".#-+ 0123456789" + 1, *++fmt)); | 71 | while (strchr(index_str + 1, *++fmt)); |
68 | if (*fmt == '.' && isdigit(*++fmt)) { | 72 | if (*fmt == '.' && isdigit(*++fmt)) { |
69 | prec = atoi(fmt); | 73 | prec = atoi(fmt); |
70 | while (isdigit(*++fmt)); | 74 | while (isdigit(*++fmt)); |
71 | } | 75 | } |
72 | switch (*fmt) { | 76 | if (!(p = strchr(size_conv_str + 12, *fmt))) { |
73 | case 'c': | 77 | if (*fmt == 's') { |
74 | bcnt += 1; | 78 | bcnt += prec; |
75 | break; | 79 | } else if (*fmt == '_') { |
76 | case 'd': | 80 | ++fmt; |
77 | case 'i': | 81 | if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) { |
78 | case 'o': | 82 | bcnt += 1; |
79 | case 'u': | 83 | } |
80 | case 'x': | ||
81 | case 'X': | ||
82 | bcnt += 4; | ||
83 | break; | ||
84 | case 'e': | ||
85 | case 'E': | ||
86 | case 'f': | ||
87 | case 'g': | ||
88 | case 'G': | ||
89 | bcnt += 8; | ||
90 | break; | ||
91 | case 's': | ||
92 | bcnt += prec; | ||
93 | break; | ||
94 | case '_': | ||
95 | switch (*++fmt) { | ||
96 | case 'c': | ||
97 | case 'p': | ||
98 | case 'u': | ||
99 | bcnt += 1; | ||
100 | break; | ||
101 | } | 84 | } |
85 | } else { | ||
86 | bcnt += size_conv_str[p - (size_conv_str + 12)]; | ||
102 | } | 87 | } |
103 | } | 88 | } |
104 | cursize += bcnt * fu->reps; | 89 | cur_size += bcnt * fu->reps; |
105 | } | 90 | } |
106 | return (cursize); | 91 | return (cur_size); |
107 | } | 92 | } |
108 | 93 | ||
109 | void rewrite(FS * fs) | 94 | static void rewrite(FS * fs) |
110 | { | 95 | { |
111 | enum { NOTOKAY, USEBCNT, USEPREC } sokay; | 96 | enum { NOTOKAY, USEBCNT, USEPREC } sokay; |
112 | register PR *pr, **nextpr = NULL; | 97 | register PR *pr, **nextpr = NULL; |
113 | register FU *fu; | 98 | register FU *fu; |
114 | register char *p1, *p2; | 99 | register char *p1, *p2; |
115 | char savech, *fmtp; | 100 | char savech, *fmtp; |
101 | const char *byte_count_str; | ||
116 | int nconv, prec = 0; | 102 | int nconv, prec = 0; |
117 | 103 | ||
118 | for (fu = fs->nextfu; fu; fu = fu->nextfu) { | 104 | for (fu = fs->nextfu; fu; fu = fu->nextfu) { |
@@ -128,7 +114,7 @@ void rewrite(FS * fs) | |||
128 | else | 114 | else |
129 | *nextpr = pr; | 115 | *nextpr = pr; |
130 | 116 | ||
131 | /* skip preceding text and up to the next % sign */ | 117 | /* bb_dump_skip preceding text and up to the next % sign */ |
132 | for (p1 = fmtp; *p1 && *p1 != '%'; ++p1); | 118 | for (p1 = fmtp; *p1 && *p1 != '%'; ++p1); |
133 | 119 | ||
134 | /* only text in the string */ | 120 | /* only text in the string */ |
@@ -144,11 +130,11 @@ void rewrite(FS * fs) | |||
144 | */ | 130 | */ |
145 | if (fu->bcnt) { | 131 | if (fu->bcnt) { |
146 | sokay = USEBCNT; | 132 | sokay = USEBCNT; |
147 | /* skip to conversion character */ | 133 | /* bb_dump_skip to conversion character */ |
148 | for (++p1; index(".#-+ 0123456789", *p1); ++p1); | 134 | for (++p1; strchr(index_str, *p1); ++p1); |
149 | } else { | 135 | } else { |
150 | /* skip any special chars, field width */ | 136 | /* bb_dump_skip any special chars, field width */ |
151 | while (index(".#-+ 0123456789" + 1, *++p1)); | 137 | while (strchr(index_str + 1, *++p1)); |
152 | if (*p1 == '.' && isdigit(*++p1)) { | 138 | if (*p1 == '.' && isdigit(*++p1)) { |
153 | sokay = USEPREC; | 139 | sokay = USEPREC; |
154 | prec = atoi(p1); | 140 | prec = atoi(p1); |
@@ -162,104 +148,59 @@ void rewrite(FS * fs) | |||
162 | /* | 148 | /* |
163 | * figure out the byte count for each conversion; | 149 | * figure out the byte count for each conversion; |
164 | * rewrite the format as necessary, set up blank- | 150 | * rewrite the format as necessary, set up blank- |
165 | * padding for end of data. | 151 | * pbb_dump_adding for end of data. |
166 | */ | 152 | */ |
167 | switch (*p1) { | 153 | |
168 | case 'c': | 154 | if (*p1 == 'c') { |
169 | pr->flags = F_CHAR; | 155 | pr->flags = F_CHAR; |
170 | switch (fu->bcnt) { | 156 | DO_BYTE_COUNT_1: |
171 | case 0: | 157 | byte_count_str = "\001"; |
172 | case 1: | 158 | DO_BYTE_COUNT: |
173 | pr->bcnt = 1; | 159 | if (fu->bcnt) { |
174 | break; | 160 | do { |
175 | default: | 161 | if (fu->bcnt == *byte_count_str) { |
176 | p1[1] = '\0'; | 162 | break; |
177 | error_msg_and_die | 163 | } |
178 | ("bad byte count for conversion character %s.", p1); | 164 | } while (*++byte_count_str); |
179 | } | 165 | } |
180 | break; | 166 | /* Unlike the original, output the remainder of the format string. */ |
181 | case 'd': | 167 | if (!*byte_count_str) { |
182 | case 'i': | 168 | bb_error_msg_and_die("bad byte count for conversion character %s.", p1); |
183 | pr->flags = F_INT; | 169 | } |
184 | goto sw1; | 170 | pr->bcnt = *byte_count_str; |
185 | case 'l': | 171 | } else if (*p1 == 'l') { |
186 | ++p2; | 172 | ++p2; |
187 | switch (p1[1]) { | 173 | ++p1; |
188 | case 'd': | 174 | DO_INT_CONV: |
189 | case 'i': | 175 | { |
190 | ++p1; | 176 | const char *e; |
177 | if (!(e = strchr(lcc, *p1))) { | ||
178 | goto DO_BAD_CONV_CHAR; | ||
179 | } | ||
191 | pr->flags = F_INT; | 180 | pr->flags = F_INT; |
192 | goto sw1; | 181 | if (e > lcc + 1) { |
193 | case 'o': | 182 | pr->flags = F_UINT; |
194 | case 'u': | 183 | } |
195 | case 'x': | 184 | byte_count_str = "\004\002\001"; |
196 | case 'X': | 185 | goto DO_BYTE_COUNT; |
197 | ++p1; | ||
198 | pr->flags = F_UINT; | ||
199 | goto sw1; | ||
200 | default: | ||
201 | p1[2] = '\0'; | ||
202 | error_msg_and_die | ||
203 | ("hexdump: bad conversion character %%%s.\n", p1); | ||
204 | } | 186 | } |
205 | /* NOTREACHED */ | 187 | /* NOTREACHED */ |
206 | case 'o': | 188 | } else if (strchr(lcc, *p1)) { |
207 | case 'u': | 189 | goto DO_INT_CONV; |
208 | case 'x': | 190 | } else if (strchr("eEfgG", *p1)) { |
209 | case 'X': | ||
210 | pr->flags = F_UINT; | ||
211 | sw1:switch (fu->bcnt) { | ||
212 | case 0: | ||
213 | case 4: | ||
214 | pr->bcnt = 4; | ||
215 | break; | ||
216 | case 1: | ||
217 | pr->bcnt = 1; | ||
218 | break; | ||
219 | case 2: | ||
220 | pr->bcnt = 2; | ||
221 | break; | ||
222 | default: | ||
223 | p1[1] = '\0'; | ||
224 | error_msg_and_die | ||
225 | ("bad byte count for conversion character %s.", p1); | ||
226 | } | ||
227 | break; | ||
228 | case 'e': | ||
229 | case 'E': | ||
230 | case 'f': | ||
231 | case 'g': | ||
232 | case 'G': | ||
233 | pr->flags = F_DBL; | 191 | pr->flags = F_DBL; |
234 | switch (fu->bcnt) { | 192 | byte_count_str = "\010\004"; |
235 | case 0: | 193 | goto DO_BYTE_COUNT; |
236 | case 8: | 194 | } else if (*p1 == 's') { |
237 | pr->bcnt = 8; | ||
238 | break; | ||
239 | case 4: | ||
240 | pr->bcnt = 4; | ||
241 | break; | ||
242 | default: | ||
243 | p1[1] = '\0'; | ||
244 | error_msg_and_die | ||
245 | ("bad byte count for conversion character %s.", p1); | ||
246 | } | ||
247 | break; | ||
248 | case 's': | ||
249 | pr->flags = F_STR; | 195 | pr->flags = F_STR; |
250 | switch (sokay) { | 196 | if (sokay == USEBCNT) { |
251 | case NOTOKAY: | ||
252 | error_msg_and_die | ||
253 | ("%%s requires a precision or a byte count."); | ||
254 | case USEBCNT: | ||
255 | pr->bcnt = fu->bcnt; | 197 | pr->bcnt = fu->bcnt; |
256 | break; | 198 | } else if (sokay == USEPREC) { |
257 | case USEPREC: | ||
258 | pr->bcnt = prec; | 199 | pr->bcnt = prec; |
259 | break; | 200 | } else { /* NOTOKAY */ |
201 | bb_error_msg_and_die("%%s requires a precision or a byte count."); | ||
260 | } | 202 | } |
261 | break; | 203 | } else if (*p1 == '_') { |
262 | case '_': | ||
263 | ++p2; | 204 | ++p2; |
264 | switch (p1[1]) { | 205 | switch (p1[1]) { |
265 | case 'A': | 206 | case 'A': |
@@ -269,51 +210,29 @@ void rewrite(FS * fs) | |||
269 | case 'a': | 210 | case 'a': |
270 | pr->flags = F_ADDRESS; | 211 | pr->flags = F_ADDRESS; |
271 | ++p2; | 212 | ++p2; |
272 | switch (p1[2]) { | 213 | if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) { |
273 | case 'd': | 214 | goto DO_BAD_CONV_CHAR; |
274 | case 'o': | ||
275 | case 'x': | ||
276 | *p1 = p1[2]; | ||
277 | break; | ||
278 | default: | ||
279 | p1[3] = '\0'; | ||
280 | error_msg_and_die | ||
281 | ("hexdump: bad conversion character %%%s.\n", p1); | ||
282 | } | 215 | } |
216 | *p1 = p1[2]; | ||
283 | break; | 217 | break; |
284 | case 'c': | 218 | case 'c': |
285 | pr->flags = F_C; | 219 | pr->flags = F_C; |
286 | /* *p1 = 'c'; set in conv_c */ | 220 | /* *p1 = 'c'; set in conv_c */ |
287 | goto sw2; | 221 | goto DO_BYTE_COUNT_1; |
288 | case 'p': | 222 | case 'p': |
289 | pr->flags = F_P; | 223 | pr->flags = F_P; |
290 | *p1 = 'c'; | 224 | *p1 = 'c'; |
291 | goto sw2; | 225 | goto DO_BYTE_COUNT_1; |
292 | case 'u': | 226 | case 'u': |
293 | pr->flags = F_U; | 227 | pr->flags = F_U; |
294 | /* *p1 = 'c'; set in conv_u */ | 228 | /* *p1 = 'c'; set in conv_u */ |
295 | sw2:switch (fu->bcnt) { | 229 | goto DO_BYTE_COUNT_1; |
296 | case 0: | ||
297 | case 1: | ||
298 | pr->bcnt = 1; | ||
299 | break; | ||
300 | default: | ||
301 | p1[2] = '\0'; | ||
302 | error_msg_and_die | ||
303 | ("bad byte count for conversion character %s.", | ||
304 | p1); | ||
305 | } | ||
306 | break; | ||
307 | default: | 230 | default: |
308 | p1[2] = '\0'; | 231 | goto DO_BAD_CONV_CHAR; |
309 | error_msg_and_die | ||
310 | ("hexdump: bad conversion character %%%s.\n", p1); | ||
311 | } | 232 | } |
312 | break; | 233 | } else { |
313 | default: | 234 | DO_BAD_CONV_CHAR: |
314 | p1[1] = '\0'; | 235 | bb_error_msg_and_die("bad conversion character %%%s.\n", p1); |
315 | error_msg_and_die("hexdump: bad conversion character %%%s.\n", | ||
316 | p1); | ||
317 | } | 236 | } |
318 | 237 | ||
319 | /* | 238 | /* |
@@ -322,16 +241,14 @@ void rewrite(FS * fs) | |||
322 | */ | 241 | */ |
323 | savech = *p2; | 242 | savech = *p2; |
324 | p1[1] = '\0'; | 243 | p1[1] = '\0'; |
325 | if (!(pr->fmt = strdup(fmtp))) | 244 | pr->fmt = bb_xstrdup(fmtp); |
326 | perror_msg_and_die("hexdump"); | ||
327 | *p2 = savech; | 245 | *p2 = savech; |
328 | pr->cchar = pr->fmt + (p1 - fmtp); | 246 | pr->cchar = pr->fmt + (p1 - fmtp); |
329 | fmtp = p2; | 247 | fmtp = p2; |
330 | 248 | ||
331 | /* only one conversion character if byte count */ | 249 | /* only one conversion character if byte count */ |
332 | if (!(pr->flags & F_ADDRESS) && fu->bcnt && nconv++) { | 250 | if (!(pr->flags & F_ADDRESS) && fu->bcnt && nconv++) { |
333 | error_msg_and_die | 251 | bb_error_msg_and_die("byte count with multiple conversion characters.\n"); |
334 | ("hexdump: byte count with multiple conversion characters.\n"); | ||
335 | } | 252 | } |
336 | } | 253 | } |
337 | /* | 254 | /* |
@@ -344,7 +261,7 @@ void rewrite(FS * fs) | |||
344 | } | 261 | } |
345 | /* | 262 | /* |
346 | * if the format string interprets any data at all, and it's | 263 | * if the format string interprets any data at all, and it's |
347 | * not the same as the blocksize, and its last format unit | 264 | * not the same as the bb_dump_blocksize, and its last format unit |
348 | * interprets any data at all, and has no iteration count, | 265 | * interprets any data at all, and has no iteration count, |
349 | * repeat it as necessary. | 266 | * repeat it as necessary. |
350 | * | 267 | * |
@@ -352,9 +269,9 @@ void rewrite(FS * fs) | |||
352 | * gets output from the last iteration of the format unit. | 269 | * gets output from the last iteration of the format unit. |
353 | */ | 270 | */ |
354 | for (fu = fs->nextfu;; fu = fu->nextfu) { | 271 | for (fu = fs->nextfu;; fu = fu->nextfu) { |
355 | if (!fu->nextfu && fs->bcnt < blocksize && | 272 | if (!fu->nextfu && fs->bcnt < bb_dump_blocksize && |
356 | !(fu->flags & F_SETREP) && fu->bcnt) | 273 | !(fu->flags & F_SETREP) && fu->bcnt) |
357 | fu->reps += (blocksize - fs->bcnt) / fu->bcnt; | 274 | fu->reps += (bb_dump_blocksize - fs->bcnt) / fu->bcnt; |
358 | if (fu->reps > 1) { | 275 | if (fu->reps > 1) { |
359 | for (pr = fu->nextpr;; pr = pr->nextpr) | 276 | for (pr = fu->nextpr;; pr = pr->nextpr) |
360 | if (!pr->nextpr) | 277 | if (!pr->nextpr) |
@@ -369,31 +286,31 @@ void rewrite(FS * fs) | |||
369 | } | 286 | } |
370 | } | 287 | } |
371 | 288 | ||
372 | static void doskip(char *fname, int statok) | 289 | static void do_skip(char *fname, int statok) |
373 | { | 290 | { |
374 | struct stat sbuf; | 291 | struct stat sbuf; |
375 | 292 | ||
376 | if (statok) { | 293 | if (statok) { |
377 | if (fstat(fileno(stdin), &sbuf)) { | 294 | if (fstat(fileno(stdin), &sbuf)) { |
378 | perror_msg_and_die("hexdump: %s", fname); | 295 | bb_perror_msg_and_die("%s", fname); |
379 | } | 296 | } |
380 | if ((!(S_ISCHR(sbuf.st_mode) || | 297 | if ((!(S_ISCHR(sbuf.st_mode) || |
381 | S_ISBLK(sbuf.st_mode) || | 298 | S_ISBLK(sbuf.st_mode) || |
382 | S_ISFIFO(sbuf.st_mode))) && skip >= sbuf.st_size) { | 299 | S_ISFIFO(sbuf.st_mode))) && bb_dump_skip >= sbuf.st_size) { |
383 | /* If size valid and skip >= size */ | 300 | /* If bb_dump_size valid and bb_dump_skip >= size */ |
384 | skip -= sbuf.st_size; | 301 | bb_dump_skip -= sbuf.st_size; |
385 | address += sbuf.st_size; | 302 | address += sbuf.st_size; |
386 | return; | 303 | return; |
387 | } | 304 | } |
388 | } | 305 | } |
389 | if (fseek(stdin, skip, SEEK_SET)) { | 306 | if (fseek(stdin, bb_dump_skip, SEEK_SET)) { |
390 | perror_msg_and_die("hexdump: %s", fname); | 307 | bb_perror_msg_and_die("%s", fname); |
391 | } | 308 | } |
392 | savaddress = address += skip; | 309 | savaddress = address += bb_dump_skip; |
393 | skip = 0; | 310 | bb_dump_skip = 0; |
394 | } | 311 | } |
395 | 312 | ||
396 | int next(char **argv) | 313 | static int next(char **argv) |
397 | { | 314 | { |
398 | static int done; | 315 | static int done; |
399 | int statok; | 316 | int statok; |
@@ -405,7 +322,7 @@ int next(char **argv) | |||
405 | for (;;) { | 322 | for (;;) { |
406 | if (*_argv) { | 323 | if (*_argv) { |
407 | if (!(freopen(*_argv, "r", stdin))) { | 324 | if (!(freopen(*_argv, "r", stdin))) { |
408 | perror_msg("%s", *_argv); | 325 | bb_perror_msg("%s", *_argv); |
409 | exitval = 1; | 326 | exitval = 1; |
410 | ++_argv; | 327 | ++_argv; |
411 | continue; | 328 | continue; |
@@ -416,11 +333,11 @@ int next(char **argv) | |||
416 | return (0); | 333 | return (0); |
417 | statok = 0; | 334 | statok = 0; |
418 | } | 335 | } |
419 | if (skip) | 336 | if (bb_dump_skip) |
420 | doskip(statok ? *_argv : "stdin", statok); | 337 | do_skip(statok ? *_argv : "stdin", statok); |
421 | if (*_argv) | 338 | if (*_argv) |
422 | ++_argv; | 339 | ++_argv; |
423 | if (!skip) | 340 | if (!bb_dump_skip) |
424 | return (1); | 341 | return (1); |
425 | } | 342 | } |
426 | /* NOTREACHED */ | 343 | /* NOTREACHED */ |
@@ -435,26 +352,26 @@ static u_char *get(void) | |||
435 | u_char *tmpp; | 352 | u_char *tmpp; |
436 | 353 | ||
437 | if (!curp) { | 354 | if (!curp) { |
438 | curp = (u_char *) xmalloc(blocksize); | 355 | curp = (u_char *) xmalloc(bb_dump_blocksize); |
439 | savp = (u_char *) xmalloc(blocksize); | 356 | savp = (u_char *) xmalloc(bb_dump_blocksize); |
440 | } else { | 357 | } else { |
441 | tmpp = curp; | 358 | tmpp = curp; |
442 | curp = savp; | 359 | curp = savp; |
443 | savp = tmpp; | 360 | savp = tmpp; |
444 | address = savaddress += blocksize; | 361 | address = savaddress += bb_dump_blocksize; |
445 | } | 362 | } |
446 | for (need = blocksize, nread = 0;;) { | 363 | for (need = bb_dump_blocksize, nread = 0;;) { |
447 | /* | 364 | /* |
448 | * if read the right number of bytes, or at EOF for one file, | 365 | * if read the right number of bytes, or at EOF for one file, |
449 | * and no other files are available, zero-pad the rest of the | 366 | * and no other files are available, zero-pad the rest of the |
450 | * block and set the end flag. | 367 | * block and set the end flag. |
451 | */ | 368 | */ |
452 | if (!length || (ateof && !next((char **) NULL))) { | 369 | if (!bb_dump_length || (ateof && !next((char **) NULL))) { |
453 | if (need == blocksize) { | 370 | if (need == bb_dump_blocksize) { |
454 | return ((u_char *) NULL); | 371 | return ((u_char *) NULL); |
455 | } | 372 | } |
456 | if (vflag != ALL && !bcmp(curp, savp, nread)) { | 373 | if (bb_dump_vflag != ALL && !bcmp(curp, savp, nread)) { |
457 | if (vflag != DUP) { | 374 | if (bb_dump_vflag != DUP) { |
458 | printf("*\n"); | 375 | printf("*\n"); |
459 | } | 376 | } |
460 | return ((u_char *) NULL); | 377 | return ((u_char *) NULL); |
@@ -464,31 +381,32 @@ static u_char *get(void) | |||
464 | return (curp); | 381 | return (curp); |
465 | } | 382 | } |
466 | n = fread((char *) curp + nread, sizeof(u_char), | 383 | n = fread((char *) curp + nread, sizeof(u_char), |
467 | length == -1 ? need : MIN(length, need), stdin); | 384 | bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin); |
468 | if (!n) { | 385 | if (!n) { |
469 | if (ferror(stdin)) { | 386 | if (ferror(stdin)) { |
470 | perror_msg("%s", _argv[-1]); | 387 | bb_perror_msg("%s", _argv[-1]); |
471 | } | 388 | } |
472 | ateof = 1; | 389 | ateof = 1; |
473 | continue; | 390 | continue; |
474 | } | 391 | } |
475 | ateof = 0; | 392 | ateof = 0; |
476 | if (length != -1) { | 393 | if (bb_dump_length != -1) { |
477 | length -= n; | 394 | bb_dump_length -= n; |
478 | } | 395 | } |
479 | if (!(need -= n)) { | 396 | if (!(need -= n)) { |
480 | if (vflag == ALL || vflag == FIRST || bcmp(curp, savp, blocksize)) { | 397 | if (bb_dump_vflag == ALL || bb_dump_vflag == FIRST |
481 | if (vflag == DUP || vflag == FIRST) { | 398 | || bcmp(curp, savp, bb_dump_blocksize)) { |
482 | vflag = WAIT; | 399 | if (bb_dump_vflag == DUP || bb_dump_vflag == FIRST) { |
400 | bb_dump_vflag = WAIT; | ||
483 | } | 401 | } |
484 | return (curp); | 402 | return (curp); |
485 | } | 403 | } |
486 | if (vflag == WAIT) { | 404 | if (bb_dump_vflag == WAIT) { |
487 | printf("*\n"); | 405 | printf("*\n"); |
488 | } | 406 | } |
489 | vflag = DUP; | 407 | bb_dump_vflag = DUP; |
490 | address = savaddress += blocksize; | 408 | address = savaddress += bb_dump_blocksize; |
491 | need = blocksize; | 409 | need = bb_dump_blocksize; |
492 | nread = 0; | 410 | nread = 0; |
493 | } else { | 411 | } else { |
494 | nread += n; | 412 | nread += n; |
@@ -507,67 +425,59 @@ static void bpad(PR * pr) | |||
507 | pr->flags = F_BPAD; | 425 | pr->flags = F_BPAD; |
508 | *pr->cchar = 's'; | 426 | *pr->cchar = 's'; |
509 | for (p1 = pr->fmt; *p1 != '%'; ++p1); | 427 | for (p1 = pr->fmt; *p1 != '%'; ++p1); |
510 | for (p2 = ++p1; *p1 && index(" -0+#", *p1); ++p1); | 428 | for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1); |
511 | while ((*p2++ = *p1++) != 0); | 429 | while ((*p2++ = *p1++) != 0); |
512 | } | 430 | } |
513 | 431 | ||
514 | void conv_c(PR * pr, u_char * p) | 432 | static const char conv_str[] = |
433 | "\0\\0\0" | ||
434 | "\007\\a\0" /* \a */ | ||
435 | "\b\\b\0" | ||
436 | "\f\\b\0" | ||
437 | "\n\\n\0" | ||
438 | "\r\\r\0" | ||
439 | "\t\\t\0" | ||
440 | "\v\\v\0" | ||
441 | "\0"; | ||
442 | |||
443 | |||
444 | static void conv_c(PR * pr, u_char * p) | ||
515 | { | 445 | { |
516 | char buf[10], *str; | 446 | const char *str = conv_str; |
517 | 447 | char buf[10]; | |
518 | switch (*p) { | 448 | |
519 | case '\0': | 449 | do { |
520 | str = "\\0"; | 450 | if (*p == *str) { |
521 | goto strpr; | 451 | ++str; |
522 | /* case '\a': */ | 452 | goto strpr; |
523 | case '\007': | 453 | } |
524 | str = "\\a"; | 454 | str += 4; |
525 | goto strpr; | 455 | } while (*str); |
526 | case '\b': | 456 | |
527 | str = "\\b"; | ||
528 | goto strpr; | ||
529 | case '\f': | ||
530 | str = "\\f"; | ||
531 | goto strpr; | ||
532 | case '\n': | ||
533 | str = "\\n"; | ||
534 | goto strpr; | ||
535 | case '\r': | ||
536 | str = "\\r"; | ||
537 | goto strpr; | ||
538 | case '\t': | ||
539 | str = "\\t"; | ||
540 | goto strpr; | ||
541 | case '\v': | ||
542 | str = "\\v"; | ||
543 | goto strpr; | ||
544 | default: | ||
545 | break; | ||
546 | } | ||
547 | if (isprint(*p)) { | 457 | if (isprint(*p)) { |
548 | *pr->cchar = 'c'; | 458 | *pr->cchar = 'c'; |
549 | (void) printf(pr->fmt, *p); | 459 | (void) printf(pr->fmt, *p); |
550 | } else { | 460 | } else { |
551 | sprintf(str = buf, "%03o", (int) *p); | 461 | sprintf(buf, "%03o", (int) *p); |
462 | str = buf; | ||
552 | strpr: | 463 | strpr: |
553 | *pr->cchar = 's'; | 464 | *pr->cchar = 's'; |
554 | printf(pr->fmt, str); | 465 | printf(pr->fmt, str); |
555 | } | 466 | } |
556 | } | 467 | } |
557 | 468 | ||
558 | void conv_u(PR * pr, u_char * p) | 469 | static void conv_u(PR * pr, u_char * p) |
559 | { | 470 | { |
560 | static char *list[] = { | 471 | static const char list[] = |
561 | "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", | 472 | "nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0" |
562 | "bs", "ht", "lf", "vt", "ff", "cr", "so", "si", | 473 | "bs\0_ht\0_lf\0_vt\0_ff\0_cr\0_so\0_si\0_" |
563 | "dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb", | 474 | "dle\0dcl\0dc2\0dc3\0dc4\0nak\0syn\0etb\0" |
564 | "can", "em", "sub", "esc", "fs", "gs", "rs", "us", | 475 | "can\0em\0_sub\0esc\0fs\0_gs\0_rs\0_us"; |
565 | }; | ||
566 | 476 | ||
567 | /* od used nl, not lf */ | 477 | /* od used nl, not lf */ |
568 | if (*p <= 0x1f) { | 478 | if (*p <= 0x1f) { |
569 | *pr->cchar = 's'; | 479 | *pr->cchar = 's'; |
570 | printf(pr->fmt, list[*p]); | 480 | printf(pr->fmt, list[4 * (int)(*p)]); |
571 | } else if (*p == 0x7f) { | 481 | } else if (*p == 0x7f) { |
572 | *pr->cchar = 's'; | 482 | *pr->cchar = 's'; |
573 | printf(pr->fmt, "del"); | 483 | printf(pr->fmt, "del"); |
@@ -580,7 +490,7 @@ void conv_u(PR * pr, u_char * p) | |||
580 | } | 490 | } |
581 | } | 491 | } |
582 | 492 | ||
583 | void display(void) | 493 | static void display(void) |
584 | { | 494 | { |
585 | /* extern FU *endfu; */ | 495 | /* extern FU *endfu; */ |
586 | register FS *fs; | 496 | register FS *fs; |
@@ -589,11 +499,11 @@ void display(void) | |||
589 | register int cnt; | 499 | register int cnt; |
590 | register u_char *bp; | 500 | register u_char *bp; |
591 | 501 | ||
592 | /* off_t saveaddress; */ | 502 | off_t saveaddress; |
593 | u_char savech = 0, *savebp; | 503 | u_char savech = 0, *savebp; |
594 | 504 | ||
595 | while ((bp = get()) != NULL) { | 505 | while ((bp = get()) != NULL) { |
596 | for (fs = fshead, savebp = bp, saveaddress = address; fs; | 506 | for (fs = bb_dump_fshead, savebp = bp, saveaddress = address; fs; |
597 | fs = fs->nextfs, bp = savebp, address = saveaddress) { | 507 | fs = fs->nextfs, bp = savebp, address = saveaddress) { |
598 | for (fu = fs->nextfu; fu; fu = fu->nextfu) { | 508 | for (fu = fs->nextfu; fu; fu = fu->nextfu) { |
599 | if (fu->flags & F_IGNORE) { | 509 | if (fu->flags & F_IGNORE) { |
@@ -707,8 +617,8 @@ void display(void) | |||
707 | } | 617 | } |
708 | if (endfu) { | 618 | if (endfu) { |
709 | /* | 619 | /* |
710 | * if eaddress not set, error or file size was multiple of | 620 | * if eaddress not set, error or file bb_dump_size was multiple of |
711 | * blocksize, and no partial block ever found. | 621 | * bb_dump_blocksize, and no partial block ever found. |
712 | */ | 622 | */ |
713 | if (!eaddress) { | 623 | if (!eaddress) { |
714 | if (!address) { | 624 | if (!address) { |
@@ -729,19 +639,19 @@ void display(void) | |||
729 | } | 639 | } |
730 | } | 640 | } |
731 | 641 | ||
732 | int dump(char **argv) | 642 | int bb_dump_dump(char **argv) |
733 | { | 643 | { |
734 | register FS *tfs; | 644 | register FS *tfs; |
735 | 645 | ||
736 | /* figure out the data block size */ | 646 | /* figure out the data block bb_dump_size */ |
737 | for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) { | 647 | for (bb_dump_blocksize = 0, tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) { |
738 | tfs->bcnt = size(tfs); | 648 | tfs->bcnt = bb_dump_size(tfs); |
739 | if (blocksize < tfs->bcnt) { | 649 | if (bb_dump_blocksize < tfs->bcnt) { |
740 | blocksize = tfs->bcnt; | 650 | bb_dump_blocksize = tfs->bcnt; |
741 | } | 651 | } |
742 | } | 652 | } |
743 | /* rewrite the rules, do syntax checking */ | 653 | /* rewrite the rules, do syntax checking */ |
744 | for (tfs = fshead; tfs; tfs = tfs->nextfs) { | 654 | for (tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) { |
745 | rewrite(tfs); | 655 | rewrite(tfs); |
746 | } | 656 | } |
747 | 657 | ||
@@ -751,21 +661,21 @@ int dump(char **argv) | |||
751 | return (exitval); | 661 | return (exitval); |
752 | } | 662 | } |
753 | 663 | ||
754 | void add(char *fmt) | 664 | void bb_dump_add(const char *fmt) |
755 | { | 665 | { |
756 | register char *p; | 666 | register const char *p; |
757 | register char *p1; | 667 | register char *p1; |
758 | register char *p2; | 668 | register char *p2; |
759 | static FS **nextfs; | 669 | static FS **nextfs; |
760 | FS *tfs; | 670 | FS *tfs; |
761 | FU *tfu, **nextfu; | 671 | FU *tfu, **nextfu; |
762 | char *savep; | 672 | const char *savep; |
763 | 673 | ||
764 | /* start new linked list of format units */ | 674 | /* start new linked list of format units */ |
765 | /* NOSTRICT */ | 675 | /* NOSTRICT */ |
766 | tfs = (FS *) xmalloc(sizeof(FS)); | 676 | tfs = (FS *) xmalloc(sizeof(FS)); |
767 | if (!fshead) { | 677 | if (!bb_dump_fshead) { |
768 | fshead = tfs; | 678 | bb_dump_fshead = tfs; |
769 | } else { | 679 | } else { |
770 | *nextfs = tfs; | 680 | *nextfs = tfs; |
771 | } | 681 | } |
@@ -774,8 +684,8 @@ void add(char *fmt) | |||
774 | 684 | ||
775 | /* take the format string and break it up into format units */ | 685 | /* take the format string and break it up into format units */ |
776 | for (p = fmt;;) { | 686 | for (p = fmt;;) { |
777 | /* skip leading white space */ | 687 | /* bb_dump_skip leading white space */ |
778 | for (; isspace(*p); ++p); | 688 | p = bb_skip_whitespace(p); |
779 | if (!*p) { | 689 | if (!*p) { |
780 | break; | 690 | break; |
781 | } | 691 | } |
@@ -791,43 +701,41 @@ void add(char *fmt) | |||
791 | if (isdigit(*p)) { | 701 | if (isdigit(*p)) { |
792 | for (savep = p; isdigit(*p); ++p); | 702 | for (savep = p; isdigit(*p); ++p); |
793 | if (!isspace(*p) && *p != '/') { | 703 | if (!isspace(*p) && *p != '/') { |
794 | error_msg_and_die("hexdump: bad format {%s}", fmt); | 704 | bb_error_msg_and_die("bad format {%s}", fmt); |
795 | } | 705 | } |
796 | /* may overwrite either white space or slash */ | 706 | /* may overwrite either white space or slash */ |
797 | tfu->reps = atoi(savep); | 707 | tfu->reps = atoi(savep); |
798 | tfu->flags = F_SETREP; | 708 | tfu->flags = F_SETREP; |
799 | /* skip trailing white space */ | 709 | /* bb_dump_skip trailing white space */ |
800 | for (++p; isspace(*p); ++p); | 710 | p = bb_skip_whitespace(++p); |
801 | } | 711 | } |
802 | 712 | ||
803 | /* skip slash and trailing white space */ | 713 | /* bb_dump_skip slash and trailing white space */ |
804 | if (*p == '/') { | 714 | if (*p == '/') { |
805 | while (isspace(*++p)); | 715 | p = bb_skip_whitespace(++p); |
806 | } | 716 | } |
807 | 717 | ||
808 | /* byte count */ | 718 | /* byte count */ |
809 | if (isdigit(*p)) { | 719 | if (isdigit(*p)) { |
810 | for (savep = p; isdigit(*p); ++p); | 720 | for (savep = p; isdigit(*p); ++p); |
811 | if (!isspace(*p)) { | 721 | if (!isspace(*p)) { |
812 | error_msg_and_die("hexdump: bad format {%s}", fmt); | 722 | bb_error_msg_and_die("bad format {%s}", fmt); |
813 | } | 723 | } |
814 | tfu->bcnt = atoi(savep); | 724 | tfu->bcnt = atoi(savep); |
815 | /* skip trailing white space */ | 725 | /* bb_dump_skip trailing white space */ |
816 | for (++p; isspace(*p); ++p); | 726 | p = bb_skip_whitespace(++p); |
817 | } | 727 | } |
818 | 728 | ||
819 | /* format */ | 729 | /* format */ |
820 | if (*p != '"') { | 730 | if (*p != '"') { |
821 | error_msg_and_die("hexdump: bad format {%s}", fmt); | 731 | bb_error_msg_and_die("bad format {%s}", fmt); |
822 | } | 732 | } |
823 | for (savep = ++p; *p != '"';) { | 733 | for (savep = ++p; *p != '"';) { |
824 | if (*p++ == 0) { | 734 | if (*p++ == 0) { |
825 | error_msg_and_die("hexdump: bad format {%s}", fmt); | 735 | bb_error_msg_and_die("bad format {%s}", fmt); |
826 | } | 736 | } |
827 | } | 737 | } |
828 | if (!(tfu->fmt = malloc(p - savep + 1))) { | 738 | tfu->fmt = xmalloc(p - savep + 1); |
829 | perror_msg_and_die("hexdump"); | ||
830 | } | ||
831 | strncpy(tfu->fmt, savep, p - savep); | 739 | strncpy(tfu->fmt, savep, p - savep); |
832 | tfu->fmt[p - savep] = '\0'; | 740 | tfu->fmt[p - savep] = '\0'; |
833 | /* escape(tfu->fmt); */ | 741 | /* escape(tfu->fmt); */ |
@@ -841,33 +749,16 @@ void add(char *fmt) | |||
841 | break; | 749 | break; |
842 | } | 750 | } |
843 | if (*p1 == '\\') { | 751 | if (*p1 == '\\') { |
844 | switch (*++p1) { | 752 | const char *cs = conv_str + 4; |
845 | case 'a': | 753 | ++p1; |
846 | /* *p2 = '\a'; */ | 754 | *p2 = *p1; |
847 | *p2 = '\007'; | 755 | do { |
848 | break; | 756 | if (*p1 == cs[2]) { |
849 | case 'b': | 757 | *p2 = cs[0]; |
850 | *p2 = '\b'; | 758 | break; |
851 | break; | 759 | } |
852 | case 'f': | 760 | cs += 4; |
853 | *p2 = '\f'; | 761 | } while (*cs); |
854 | break; | ||
855 | case 'n': | ||
856 | *p2 = '\n'; | ||
857 | break; | ||
858 | case 'r': | ||
859 | *p2 = '\r'; | ||
860 | break; | ||
861 | case 't': | ||
862 | *p2 = '\t'; | ||
863 | break; | ||
864 | case 'v': | ||
865 | *p2 = '\v'; | ||
866 | break; | ||
867 | default: | ||
868 | *p2 = *p1; | ||
869 | break; | ||
870 | } | ||
871 | } | 762 | } |
872 | } | 763 | } |
873 | 764 | ||