diff options
author | Chris Johns <chrisj@rtems.org> | 2009-06-12 05:51:43 +0000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2009-06-12 05:51:43 +0000 |
commit | e4a3d93ab1dc3779713a2c73adb721d3ab067e8c (patch) | |
tree | ca86ba3e20e254e28d0b0707cda4a465f705dd92 /cpukit/libmisc/shell | |
parent | 2009-06-12 Chris Johns <chrisj@rtems.org> (diff) | |
download | rtems-e4a3d93ab1dc3779713a2c73adb721d3ab067e8c.tar.bz2 |
2009-06-12 Chris Johns <chrisj@rtems.org>
* libmisc/shell/dd-args.c, libmisc/shell/dd-conv.c,
libmisc/shell/dd-conv_tab.c, libmisc/shell/dd-misc.c,
libmisc/shell/dd-position.c, libmisc/shell/dd.h,
libmisc/shell/extern-dd.h, libmisc/shell/hexdump-conv.c,
libmisc/shell/hexdump-display.c, libmisc/shell/hexdump-odsyntax.c,
libmisc/shell/hexdump-parse.c, libmisc/shell/hexdump.h,
libmisc/shell/hexsyntax.c, libmisc/shell/main_dd.c,
libmisc/shell/main_hexdump.c: New.
* libmisc/Makefile.am, libmisc/shell/shellconfig.h: Add dd and
hexdump commands.
Diffstat (limited to 'cpukit/libmisc/shell')
-rw-r--r-- | cpukit/libmisc/shell/dd-args.c | 503 | ||||
-rw-r--r-- | cpukit/libmisc/shell/dd-conv.c | 268 | ||||
-rw-r--r-- | cpukit/libmisc/shell/dd-conv_tab.c | 284 | ||||
-rw-r--r-- | cpukit/libmisc/shell/dd-misc.c | 108 | ||||
-rw-r--r-- | cpukit/libmisc/shell/dd-position.c | 189 | ||||
-rw-r--r-- | cpukit/libmisc/shell/dd.h | 108 | ||||
-rw-r--r-- | cpukit/libmisc/shell/extern-dd.h | 106 | ||||
-rw-r--r-- | cpukit/libmisc/shell/hexdump-conv.c | 184 | ||||
-rw-r--r-- | cpukit/libmisc/shell/hexdump-display.c | 420 | ||||
-rw-r--r-- | cpukit/libmisc/shell/hexdump-odsyntax.c | 451 | ||||
-rw-r--r-- | cpukit/libmisc/shell/hexdump-parse.c | 517 | ||||
-rw-r--r-- | cpukit/libmisc/shell/hexdump.h | 183 | ||||
-rw-r--r-- | cpukit/libmisc/shell/hexsyntax.c | 152 | ||||
-rw-r--r-- | cpukit/libmisc/shell/main_dd.c | 561 | ||||
-rw-r--r-- | cpukit/libmisc/shell/main_hexdump.c | 161 | ||||
-rw-r--r-- | cpukit/libmisc/shell/shellconfig.h | 12 |
16 files changed, 4207 insertions, 0 deletions
diff --git a/cpukit/libmisc/shell/dd-args.c b/cpukit/libmisc/shell/dd-args.c new file mode 100644 index 0000000000..707fc11cca --- /dev/null +++ b/cpukit/libmisc/shell/dd-args.c @@ -0,0 +1,503 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * 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. + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94"; +#endif +#endif /* not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/bin/dd/args.c,v 1.40 2004/08/15 19:10:05 rwatson Exp $"); + +#include <sys/types.h> + +#include <err.h> +#include <errno.h> +#include <inttypes.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +#include "dd.h" +#include "extern-dd.h" + +#define strtouq strtoul +#define strtoq strtol + +static int c_arg(const void *, const void *); +static int c_conv(const void *, const void *); +static void f_bs(rtems_shell_dd_globals* globals, char *); +static void f_cbs(rtems_shell_dd_globals* globals, char *); +static void f_conv(rtems_shell_dd_globals* globals, char *); +static void f_count(rtems_shell_dd_globals* globals, char *); +static void f_files(rtems_shell_dd_globals* globals, char *); +static void f_fillchar(rtems_shell_dd_globals* globals, char *); +static void f_ibs(rtems_shell_dd_globals* globals, char *); +static void f_if(rtems_shell_dd_globals* globals, char *); +static void f_obs(rtems_shell_dd_globals* globals, char *); +static void f_of(rtems_shell_dd_globals* globals, char *); +static void f_seek(rtems_shell_dd_globals* globals, char *); +static void f_skip(rtems_shell_dd_globals* globals, char *); +static uintmax_t get_num(rtems_shell_dd_globals* globals, const char *); +static off_t get_off_t(rtems_shell_dd_globals* globals, const char *); + +static const struct arg { + const char *name; + void (*f)(rtems_shell_dd_globals* globals, char *); + u_int set, noset; +} args[] = { + { "bs", f_bs, C_BS, C_BS|C_IBS|C_OBS|C_OSYNC }, + { "cbs", f_cbs, C_CBS, C_CBS }, + { "conv", f_conv, 0, 0 }, + { "count", f_count, C_COUNT, C_COUNT }, + { "files", f_files, C_FILES, C_FILES }, + { "fillchar", f_fillchar, C_FILL, C_FILL }, + { "ibs", f_ibs, C_IBS, C_BS|C_IBS }, + { "if", f_if, C_IF, C_IF }, + { "iseek", f_skip, C_SKIP, C_SKIP }, + { "obs", f_obs, C_OBS, C_BS|C_OBS }, + { "of", f_of, C_OF, C_OF }, + { "oseek", f_seek, C_SEEK, C_SEEK }, + { "seek", f_seek, C_SEEK, C_SEEK }, + { "skip", f_skip, C_SKIP, C_SKIP }, +}; + +static char *oper; + +/* + * args -- parse JCL syntax of dd. + */ +void +jcl(rtems_shell_dd_globals* globals, char **argv) +{ + struct arg *ap, tmp; + char *arg; + + oper = NULL; + + in.dbsz = out.dbsz = 512; + + while ((oper = *++argv) != NULL) { +// if ((oper = strdup(oper)) == NULL) +// errx(exit_jump, 1, "unable to allocate space for the argument \"%s\"", *argv); + if ((arg = strchr(oper, '=')) == NULL) + errx(exit_jump, 1, "unknown operand %s", oper); + *arg++ = '\0'; + if (!*arg) + errx(exit_jump, 1, "no value specified for %s", oper); + tmp.name = oper; + if (!(ap = (struct arg *)bsearch(&tmp, args, + sizeof(args)/sizeof(struct arg), sizeof(struct arg), + c_arg))) + errx(exit_jump, 1, "unknown operand %s", tmp.name); + if (ddflags & ap->noset) + errx(exit_jump, 1, "%s: illegal argument combination or already set", + tmp.name); + ddflags |= ap->set; + ap->f(globals, arg); + } + + /* Final sanity checks. */ + + if (ddflags & C_BS) { + /* + * Bs is turned off by any conversion -- we assume the user + * just wanted to set both the input and output block sizes + * and didn't want the bs semantics, so we don't warn. + */ + if (ddflags & (C_BLOCK | C_LCASE | C_SWAB | C_UCASE | + C_UNBLOCK)) + ddflags &= ~C_BS; + + /* Bs supersedes ibs and obs. */ + if (ddflags & C_BS && ddflags & (C_IBS | C_OBS)) + warnx("bs supersedes ibs and obs"); + } + + /* + * Ascii/ebcdic and cbs implies block/unblock. + * Block/unblock requires cbs and vice-versa. + */ + if (ddflags & (C_BLOCK | C_UNBLOCK)) { + if (!(ddflags & C_CBS)) + errx(exit_jump, 1, "record operations require cbs"); + if (cbsz == 0) + errx(exit_jump, 1, "cbs cannot be zero"); + cfunc = ddflags & C_BLOCK ? block : unblock; + } else if (ddflags & C_CBS) { + if (ddflags & (C_ASCII | C_EBCDIC)) { + if (ddflags & C_ASCII) { + ddflags |= C_UNBLOCK; + cfunc = unblock; + } else { + ddflags |= C_BLOCK; + cfunc = block; + } + } else + errx(exit_jump, 1, "cbs meaningless if not doing record operations"); + } else + cfunc = def; + + /* + * Bail out if the calculation of a file offset would overflow. + */ + if (in.offset > OFF_MAX / (ssize_t)in.dbsz || + out.offset > OFF_MAX / (ssize_t)out.dbsz) + errx(exit_jump, 1, "seek offsets cannot be larger than %jd", + (intmax_t)OFF_MAX); +} + +static int +c_arg(const void *a, const void *b) +{ + + return (strcmp(((const struct arg *)a)->name, + ((const struct arg *)b)->name)); +} + +static void +f_bs(rtems_shell_dd_globals* globals, char *arg) +{ + uintmax_t res; + + res = get_num(globals, arg); + if (res < 1 || res > SSIZE_MAX) + errx(exit_jump, 1, "bs must be between 1 and %jd", (intmax_t)SSIZE_MAX); + in.dbsz = out.dbsz = (size_t)res; +} + +static void +f_cbs(rtems_shell_dd_globals* globals, char *arg) +{ + uintmax_t res; + + res = get_num(globals, arg); + if (res < 1 || res > SSIZE_MAX) + errx(exit_jump, 1, "cbs must be between 1 and %jd", (intmax_t)SSIZE_MAX); + cbsz = (size_t)res; +} + +static void +f_count(rtems_shell_dd_globals* globals, char *arg) +{ + intmax_t res; + + res = (intmax_t)get_num(globals, arg); + if (res < 0) + errx(exit_jump, 1, "count cannot be negative"); + if (res == 0) + cpy_cnt = (uintmax_t)-1; + else + cpy_cnt = (uintmax_t)res; +} + +static void +f_files(rtems_shell_dd_globals* globals, char *arg) +{ + + files_cnt = get_num(globals, arg); + if (files_cnt < 1) + errx(exit_jump, 1, "files must be between 1 and %jd", (uintmax_t)-1); +} + +static void +f_fillchar(rtems_shell_dd_globals* globals, char *arg) +{ + + if (strlen(arg) != 1) + errx(exit_jump, 1, "need exactly one fill char"); + + fill_char = arg[0]; +} + +static void +f_ibs(rtems_shell_dd_globals* globals, char *arg) +{ + uintmax_t res; + + if (!(ddflags & C_BS)) { + res = get_num(globals, arg); + if (res < 1 || res > SSIZE_MAX) + errx(exit_jump, 1, "ibs must be between 1 and %jd", + (intmax_t)SSIZE_MAX); + in.dbsz = (size_t)res; + } +} + +static void +f_if(rtems_shell_dd_globals* globals, char *arg) +{ + + in.name = strdup(arg); +} + +static void +f_obs(rtems_shell_dd_globals* globals, char *arg) +{ + uintmax_t res; + + if (!(ddflags & C_BS)) { + res = get_num(globals, arg); + if (res < 1 || res > SSIZE_MAX) + errx(exit_jump, 1, "obs must be between 1 and %jd", + (intmax_t)SSIZE_MAX); + out.dbsz = (size_t)res; + } +} + +static void +f_of(rtems_shell_dd_globals* globals, char *arg) +{ + + out.name = strdup(arg); +} + +static void +f_seek(rtems_shell_dd_globals* globals, char *arg) +{ + + out.offset = get_off_t(globals, arg); +} + +static void +f_skip(rtems_shell_dd_globals* globals, char *arg) +{ + + in.offset = get_off_t(globals, arg); +} + +static const struct conv { + const char *name; + u_int set, noset; + const u_char *ctab_; +} clist[] = { + { "ascii", C_ASCII, C_EBCDIC, e2a_POSIX }, + { "block", C_BLOCK, C_UNBLOCK, NULL }, + { "ebcdic", C_EBCDIC, C_ASCII, a2e_POSIX }, + { "ibm", C_EBCDIC, C_ASCII, a2ibm_POSIX }, + { "lcase", C_LCASE, C_UCASE, NULL }, + { "noerror", C_NOERROR, 0, NULL }, + { "notrunc", C_NOTRUNC, 0, NULL }, + { "oldascii", C_ASCII, C_EBCDIC, e2a_32V }, + { "oldebcdic", C_EBCDIC, C_ASCII, a2e_32V }, + { "oldibm", C_EBCDIC, C_ASCII, a2ibm_32V }, + { "osync", C_OSYNC, C_BS, NULL }, + { "pareven", C_PAREVEN, C_PARODD|C_PARSET|C_PARNONE, NULL}, + { "parnone", C_PARNONE, C_PARODD|C_PARSET|C_PAREVEN, NULL}, + { "parodd", C_PARODD, C_PAREVEN|C_PARSET|C_PARNONE, NULL}, + { "parset", C_PARSET, C_PARODD|C_PAREVEN|C_PARNONE, NULL}, + { "sparse", C_SPARSE, 0, NULL }, + { "swab", C_SWAB, 0, NULL }, + { "sync", C_SYNC, 0, NULL }, + { "ucase", C_UCASE, C_LCASE, NULL }, + { "unblock", C_UNBLOCK, C_BLOCK, NULL }, +}; + +static void +f_conv(rtems_shell_dd_globals* globals, char *arg) +{ + struct conv *cp, tmp; + + while (arg != NULL) { + tmp.name = strsep(&arg, ","); + cp = bsearch(&tmp, clist, sizeof(clist) / sizeof(struct conv), + sizeof(struct conv), c_conv); + if (cp == NULL) + errx(exit_jump, 1, "unknown conversion %s", tmp.name); + if (ddflags & cp->noset) + errx(exit_jump, 1, "%s: illegal conversion combination", tmp.name); + ddflags |= cp->set; + if (cp->ctab_) + ctab = cp->ctab_; + } +} + +static int +c_conv(const void *a, const void *b) +{ + + return (strcmp(((const struct conv *)a)->name, + ((const struct conv *)b)->name)); +} + +/* + * Convert an expression of the following forms to a uintmax_t. + * 1) A positive decimal number. + * 2) A positive decimal number followed by a 'b' or 'B' (mult by 512). + * 3) A positive decimal number followed by a 'k' or 'K' (mult by 1 << 10). + * 4) A positive decimal number followed by a 'm' or 'M' (mult by 1 << 20). + * 5) A positive decimal number followed by a 'g' or 'G' (mult by 1 << 30). + * 5) A positive decimal number followed by a 'w' or 'W' (mult by sizeof int). + * 6) Two or more positive decimal numbers (with/without [BbKkMmGgWw]) + * separated by 'x' or 'X' (also '*' for backwards compatibility), + * specifying the product of the indicated values. + */ +static uintmax_t +get_num(rtems_shell_dd_globals* globals, const char *val) +{ + uintmax_t num, mult, prevnum; + char *expr; + + errno = 0; + num = strtouq(val, &expr, 0); + if (errno != 0) /* Overflow or underflow. */ + err(exit_jump, 1, "%s", oper); + + if (expr == val) /* No valid digits. */ + errx(exit_jump, 1, "%s: illegal numeric value", oper); + + mult = 0; + switch (*expr) { + case 'B': + case 'b': + mult = 512; + break; + case 'K': + case 'k': + mult = 1 << 10; + break; + case 'M': + case 'm': + mult = 1 << 20; + break; + case 'G': + case 'g': + mult = 1 << 30; + break; + case 'W': + case 'w': + mult = sizeof(int); + break; + default: + ; + } + + if (mult != 0) { + prevnum = num; + num *= mult; + /* Check for overflow. */ + if (num / mult != prevnum) + goto erange; + expr++; + } + + switch (*expr) { + case '\0': + break; + case '*': /* Backward compatible. */ + case 'X': + case 'x': + mult = get_num(globals, expr + 1); + prevnum = num; + num *= mult; + if (num / mult == prevnum) + break; +erange: + errx(exit_jump, 1, "%s: %s", oper, strerror(ERANGE)); + default: + errx(exit_jump, 1, "%s: illegal numeric value", oper); + } + return (num); +} + +/* + * Convert an expression of the following forms to an off_t. This is the + * same as get_num(), but it uses signed numbers. + * + * The major problem here is that an off_t may not necessarily be a intmax_t. + */ +static off_t +get_off_t(rtems_shell_dd_globals* globals, const char *val) +{ + intmax_t num, mult, prevnum; + char *expr; + + errno = 0; + num = strtoq(val, &expr, 0); + if (errno != 0) /* Overflow or underflow. */ + err(exit_jump, 1, "%s", oper); + + if (expr == val) /* No valid digits. */ + errx(exit_jump, 1, "%s: illegal numeric value", oper); + + mult = 0; + switch (*expr) { + case 'B': + case 'b': + mult = 512; + break; + case 'K': + case 'k': + mult = 1 << 10; + break; + case 'M': + case 'm': + mult = 1 << 20; + break; + case 'G': + case 'g': + mult = 1 << 30; + break; + case 'W': + case 'w': + mult = sizeof(int); + break; + } + + if (mult != 0) { + prevnum = num; + num *= mult; + /* Check for overflow. */ + if ((prevnum > 0) != (num > 0) || num / mult != prevnum) + goto erange; + expr++; + } + + switch (*expr) { + case '\0': + break; + case '*': /* Backward compatible. */ + case 'X': + case 'x': + mult = (intmax_t)get_off_t(globals, expr + 1); + prevnum = num; + num *= mult; + if ((prevnum > 0) == (num > 0) && num / mult == prevnum) + break; +erange: + errx(exit_jump, 1, "%s: %s", oper, strerror(ERANGE)); + default: + errx(exit_jump, 1, "%s: illegal numeric value", oper); + } + return (num); +} diff --git a/cpukit/libmisc/shell/dd-conv.c b/cpukit/libmisc/shell/dd-conv.c new file mode 100644 index 0000000000..99ffa631c3 --- /dev/null +++ b/cpukit/libmisc/shell/dd-conv.c @@ -0,0 +1,268 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * 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. + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94"; +#endif +#endif /* not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/bin/dd/conv.c,v 1.19 2004/04/06 20:06:45 markm Exp $"); + +#include <sys/param.h> + +#include <err.h> +#include <inttypes.h> +#include <string.h> + +#include "dd.h" +#include "extern-dd.h" + +/* + * def -- + * Copy input to output. Input is buffered until reaches obs, and then + * output until less than obs remains. Only a single buffer is used. + * Worst case buffer calculation is (ibs + obs - 1). + */ +void +def(rtems_shell_dd_globals* globals) +{ + u_char *inp; + const u_char *t; + size_t cnt; + + if ((t = ctab) != NULL) + for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp) + *inp = t[*inp]; + + /* Make the output buffer look right. */ + out.dbp = in.dbp; + out.dbcnt = in.dbcnt; + + if (in.dbcnt >= out.dbsz) { + /* If the output buffer is full, write it. */ + dd_out(globals, 0); + + /* + * Ddout copies the leftover output to the beginning of + * the buffer and resets the output buffer. Reset the + * input buffer to match it. + */ + in.dbp = out.dbp; + in.dbcnt = out.dbcnt; + } +} + +void +def_close(rtems_shell_dd_globals* globals) +{ + /* Just update the count, everything is already in the buffer. */ + if (in.dbcnt) + out.dbcnt = in.dbcnt; +} + +/* + * Copy variable length newline terminated records with a max size cbsz + * bytes to output. Records less than cbs are padded with spaces. + * + * max in buffer: MAX(ibs, cbsz) + * max out buffer: obs + cbsz + */ +void +block(rtems_shell_dd_globals* globals) +{ + u_char *inp, *outp; + const u_char *t; + size_t cnt, maxlen; + static int intrunc; + int ch; + + /* + * Record truncation can cross block boundaries. If currently in a + * truncation state, keep tossing characters until reach a newline. + * Start at the beginning of the buffer, as the input buffer is always + * left empty. + */ + if (intrunc) { + for (inp = in.db, cnt = in.dbrcnt; cnt && *inp++ != '\n'; --cnt) + ; + if (!cnt) { + in.dbcnt = 0; + in.dbp = in.db; + return; + } + intrunc = 0; + /* Adjust the input buffer numbers. */ + in.dbcnt = cnt - 1; + in.dbp = inp + cnt - 1; + } + + /* + * Copy records (max cbsz size chunks) into the output buffer. The + * translation is done as we copy into the output buffer. + */ + ch = 0; + for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) { + maxlen = MIN(cbsz, in.dbcnt); + if ((t = ctab) != NULL) + for (cnt = 0; cnt < maxlen && (ch = *inp++) != '\n'; + ++cnt) + *outp++ = t[ch]; + else + for (cnt = 0; cnt < maxlen && (ch = *inp++) != '\n'; + ++cnt) + *outp++ = ch; + /* + * Check for short record without a newline. Reassemble the + * input block. + */ + if (ch != '\n' && in.dbcnt < cbsz) { + (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt); + break; + } + + /* Adjust the input buffer numbers. */ + in.dbcnt -= cnt; + if (ch == '\n') + --in.dbcnt; + + /* Pad short records with spaces. */ + if (cnt < cbsz) + (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt); + else { + /* + * If the next character wouldn't have ended the + * block, it's a truncation. + */ + if (!in.dbcnt || *inp != '\n') + ++st.trunc; + + /* Toss characters to a newline. */ + for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt) + ; + if (!in.dbcnt) + intrunc = 1; + else + --in.dbcnt; + } + + /* Adjust output buffer numbers. */ + out.dbp += cbsz; + if ((out.dbcnt += cbsz) >= out.dbsz) + dd_out(globals, 0); + outp = out.dbp; + } + in.dbp = in.db + in.dbcnt; +} + +void +block_close(rtems_shell_dd_globals* globals) +{ + /* + * Copy any remaining data into the output buffer and pad to a record. + * Don't worry about truncation or translation, the input buffer is + * always empty when truncating, and no characters have been added for + * translation. The bottom line is that anything left in the input + * buffer is a truncated record. Anything left in the output buffer + * just wasn't big enough. + */ + if (in.dbcnt) { + ++st.trunc; + (void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt); + (void)memset(out.dbp + in.dbcnt, ctab ? ctab[' '] : ' ', + cbsz - in.dbcnt); + out.dbcnt += cbsz; + } +} + +/* + * Convert fixed length (cbsz) records to variable length. Deletes any + * trailing blanks and appends a newline. + * + * max in buffer: MAX(ibs, cbsz) + cbsz + * max out buffer: obs + cbsz + */ +void +unblock(rtems_shell_dd_globals* globals) +{ + u_char *inp; + const u_char *t; + size_t cnt; + + /* Translation and case conversion. */ + if ((t = ctab) != NULL) + for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp) + *inp = t[*inp]; + /* + * Copy records (max cbsz size chunks) into the output buffer. The + * translation has to already be done or we might not recognize the + * spaces. + */ + for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) { + for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t) + ; + if (t >= inp) { + cnt = t - inp + 1; + (void)memmove(out.dbp, inp, cnt); + out.dbp += cnt; + out.dbcnt += cnt; + } + *out.dbp++ = '\n'; + if (++out.dbcnt >= out.dbsz) + dd_out(globals, 0); + } + if (in.dbcnt) + (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt); + in.dbp = in.db + in.dbcnt; +} + +void +unblock_close(rtems_shell_dd_globals* globals) +{ + u_char *t; + size_t cnt; + + if (in.dbcnt) { + warnx("%s: short input record", in.name); + for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t) + ; + if (t >= in.db) { + cnt = t - in.db + 1; + (void)memmove(out.dbp, in.db, cnt); + out.dbp += cnt; + out.dbcnt += cnt; + } + ++out.dbcnt; + *out.dbp++ = '\n'; + } +} diff --git a/cpukit/libmisc/shell/dd-conv_tab.c b/cpukit/libmisc/shell/dd-conv_tab.c new file mode 100644 index 0000000000..e29abb67ba --- /dev/null +++ b/cpukit/libmisc/shell/dd-conv_tab.c @@ -0,0 +1,284 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * 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. + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)conv_tab.c 8.1 (Berkeley) 5/31/93"; +#endif +#endif /* not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/bin/dd/conv_tab.c,v 1.12 2004/04/06 20:06:45 markm Exp $"); + +#include <sys/types.h> + +/* + * There are currently six tables: + * + * ebcdic -> ascii 32V conv=oldascii + * ascii -> ebcdic 32V conv=oldebcdic + * ascii -> ibm ebcdic 32V conv=oldibm + * + * ebcdic -> ascii POSIX/S5 conv=ascii + * ascii -> ebcdic POSIX/S5 conv=ebcdic + * ascii -> ibm ebcdic POSIX/S5 conv=ibm + * + * Other tables are built from these if multiple conversions are being + * done. + * + * Tables used for conversions to/from IBM and EBCDIC to support an extension + * to POSIX P1003.2/D11. The tables referencing POSIX contain data extracted + * from tables 4-3 and 4-4 in P1003.2/Draft 11. The historic tables were + * constructed by running against a file with all possible byte values. + * + * More information can be obtained in "Correspondences of 8-Bit and Hollerith + * Codes for Computer Environments-A USASI Tutorial", Communications of the + * ACM, Volume 11, Number 11, November 1968, pp. 783-789. + */ + +u_char casetab[256]; + +/* EBCDIC to ASCII -- 32V compatible. */ +const u_char e2a_32V[] = { + 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */ + 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */ + 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */ + 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */ + 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */ + 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */ + 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */ + 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */ + 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */ + 0247, 0250, 0133, 0056, 0074, 0050, 0053, 0041, /* 0110 */ + 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */ + 0260, 0261, 0135, 0044, 0052, 0051, 0073, 0136, /* 0130 */ + 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */ + 0270, 0271, 0174, 0054, 0045, 0137, 0076, 0077, /* 0150 */ + 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */ + 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */ + 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */ + 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */ + 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */ + 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320, /* 0230 */ + 0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */ + 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327, /* 0250 */ + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */ + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, /* 0270 */ + 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */ + 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */ + 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */ + 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */ + 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */ + 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */ + 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */ + 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ +}; + +/* ASCII to EBCDIC -- 32V compatible. */ +const u_char a2e_32V[] = { + 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ + 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ + 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ + 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ + 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ + 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ + 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ + 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ + 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ + 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ + 0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155, /* 0130 */ + 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ + 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ + 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ + 0247, 0250, 0251, 0300, 0152, 0320, 0241, 0007, /* 0170 */ + 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ + 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ + 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ + 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ + 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ + 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ + 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ + 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ + 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ + 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */ + 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */ + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */ + 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ + 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ + 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ +}; + +/* ASCII to IBM EBCDIC -- 32V compatible. */ +const u_char a2ibm_32V[] = { + 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ + 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ + 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ + 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ + 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ + 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ + 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ + 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ + 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ + 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ + 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */ + 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ + 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ + 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ + 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */ + 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ + 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ + 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ + 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ + 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ + 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ + 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ + 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ + 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ + 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */ + 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */ + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */ + 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ + 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ + 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ +}; + +/* EBCDIC to ASCII -- POSIX and System V compatible. */ +const u_char e2a_POSIX[] = { + 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */ + 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */ + 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */ + 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */ + 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */ + 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */ + 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */ + 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */ + 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */ + 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174, /* 0110 */ + 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */ + 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176, /* 0130 */ + 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */ + 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077, /* 0150 */ + 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */ + 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */ + 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */ + 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */ + 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */ + 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320, /* 0230 */ + 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */ + 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327, /* 0250 */ + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */ + 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347, /* 0270 */ + 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */ + 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */ + 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */ + 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */ + 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */ + 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */ + 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */ + 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ +}; + +/* ASCII to EBCDIC -- POSIX and System V compatible. */ +const u_char a2e_POSIX[] = { + 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ + 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ + 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ + 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ + 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ + 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ + 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ + 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ + 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ + 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ + 0347, 0350, 0351, 0255, 0340, 0275, 0232, 0155, /* 0130 */ + 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ + 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ + 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ + 0247, 0250, 0251, 0300, 0117, 0320, 0137, 0007, /* 0170 */ + 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ + 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ + 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ + 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ + 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ + 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ + 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ + 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ + 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ + 0216, 0217, 0220, 0152, 0233, 0234, 0235, 0236, /* 0310 */ + 0237, 0240, 0252, 0253, 0254, 0112, 0256, 0257, /* 0320 */ + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ + 0270, 0271, 0272, 0273, 0274, 0241, 0276, 0277, /* 0340 */ + 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ + 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ + 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ +}; + +/* ASCII to IBM EBCDIC -- POSIX and System V compatible. */ +const u_char a2ibm_POSIX[] = { + 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ + 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ + 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ + 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ + 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ + 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ + 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ + 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ + 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ + 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ + 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */ + 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ + 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ + 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ + 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */ + 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ + 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ + 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ + 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ + 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ + 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ + 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ + 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ + 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ + 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */ + 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */ + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */ + 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ + 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ + 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ +}; diff --git a/cpukit/libmisc/shell/dd-misc.c b/cpukit/libmisc/shell/dd-misc.c new file mode 100644 index 0000000000..2b90d7c79c --- /dev/null +++ b/cpukit/libmisc/shell/dd-misc.c @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * 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. + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94"; +#endif +#endif /* not lint */ +#if 0 +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/bin/dd/misc.c,v 1.27 2004/04/06 20:06:46 markm Exp $"); +#endif + +#include <sys/types.h> +#include <sys/time.h> + +#include <errno.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "dd.h" +#include "extern-dd.h" + +void +summary(rtems_shell_dd_globals* globals) +{ + struct timeval tv; + double secs; + char buf[100]; + + (void)gettimeofday(&tv, (struct timezone *)NULL); + secs = tv.tv_sec + tv.tv_usec * 1e-6 - st.start; + if (secs < 1e-6) + secs = 1e-6; + /* Use snprintf(3) so that we don't reenter stdio(3). */ + (void)snprintf(buf, sizeof(buf), + "%ju+%ju records in\n%ju+%ju records out\n", + st.in_full, st.in_part, st.out_full, st.out_part); + (void)write(STDERR_FILENO, buf, strlen(buf)); + if (st.swab) { + (void)snprintf(buf, sizeof(buf), "%ju odd length swab %s\n", + st.swab, (st.swab == 1) ? "block" : "blocks"); + (void)write(STDERR_FILENO, buf, strlen(buf)); + } + if (st.trunc) { + (void)snprintf(buf, sizeof(buf), "%ju truncated %s\n", + st.trunc, (st.trunc == 1) ? "block" : "blocks"); + (void)write(STDERR_FILENO, buf, strlen(buf)); + } + (void)snprintf(buf, sizeof(buf), + "%ju bytes transferred in %.6f secs (%.0f bytes/sec)\n", + st.bytes, secs, st.bytes / secs); + (void)write(STDERR_FILENO, buf, strlen(buf)); +} + +/* ARGSUSED */ +void +summaryx(rtems_shell_dd_globals* globals, int __unused) +{ + int save_errno = errno; + + summary(globals); + errno = save_errno; +} + +#if RTEMS_REMOVED +/* ARGSUSED */ +void +terminate(int sig) +{ + + summary(); + _exit(sig == 0 ? 0 : 1); +} +#endif diff --git a/cpukit/libmisc/shell/dd-position.c b/cpukit/libmisc/shell/dd-position.c new file mode 100644 index 0000000000..bcd9046c15 --- /dev/null +++ b/cpukit/libmisc/shell/dd-position.c @@ -0,0 +1,189 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * 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. + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94"; +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/bin/dd/position.c,v 1.23 2004/04/06 20:06:46 markm Exp $"); +#endif +#endif /* not lint */ + +#include <sys/types.h> +#if RTEMS_REMOVED +#include <sys/mtio.h> +#endif + +#include <err.h> +#include <errno.h> +#include <inttypes.h> +#include <unistd.h> + +#include "dd.h" +#include "extern-dd.h" + +/* + * Position input/output data streams before starting the copy. Device type + * dependent. Seekable devices use lseek, and the rest position by reading. + * Seeking past the end of file can cause null blocks to be written to the + * output. + */ +void +pos_in(rtems_shell_dd_globals* globals) +{ + off_t cnt; + int warned; + ssize_t nr; + size_t bcnt; + + /* If known to be seekable, try to seek on it. */ + if (in.flags & ISSEEK) { + errno = 0; + if (lseek(in.fd, in.offset * in.dbsz, SEEK_CUR) == -1 && + errno != 0) + err(exit_jump, 1, "%s", in.name); + return; + } + + /* Don't try to read a really weird amount (like negative). */ + if (in.offset < 0) + errx(exit_jump, 1, "%s: illegal offset", "iseek/skip"); + + /* + * Read the data. If a pipe, read until satisfy the number of bytes + * being skipped. No differentiation for reading complete and partial + * blocks for other devices. + */ + for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) { + if ((nr = read(in.fd, in.db, bcnt)) > 0) { + if (in.flags & ISPIPE) { + if (!(bcnt -= nr)) { + bcnt = in.dbsz; + --cnt; + } + } else + --cnt; + continue; + } + + if (nr == 0) { + if (files_cnt > 1) { + --files_cnt; + continue; + } + errx(exit_jump, 1, "skip reached end of input"); + } + + /* + * Input error -- either EOF with no more files, or I/O error. + * If noerror not set die. POSIX requires that the warning + * message be followed by an I/O display. + */ + if (ddflags & C_NOERROR) { + if (!warned) { + warn("%s", in.name); + warned = 1; + summary(globals); + } + continue; + } + err(exit_jump, 1, "%s", in.name); + } +} + +void +pos_out(rtems_shell_dd_globals* globals) +{ +#if RTEMS_REMOVED + struct mtop t_op; + off_t cnt; + ssize_t n; +#endif + + /* + * If not a tape, try seeking on the file. Seeking on a pipe is + * going to fail, but don't protect the user -- they shouldn't + * have specified the seek operand. + */ + if (out.flags & (ISSEEK | ISPIPE)) { + errno = 0; + if (lseek(out.fd, out.offset * out.dbsz, SEEK_CUR) == -1 && + errno != 0) + err(exit_jump, 1, "%s", out.name); + return; + } + + /* Don't try to read a really weird amount (like negative). */ + if (out.offset < 0) + errx(exit_jump, 1, "%s: illegal offset", "oseek/seek"); + +#if RTEMS_REMOVED + /* If no read access, try using mtio. */ + if (out.flags & NOREAD) { + t_op.mt_op = MTFSR; + t_op.mt_count = out.offset; + + if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) + err(1, "%s", out.name); + return; + } + + /* Read it. */ + for (cnt = 0; cnt < out.offset; ++cnt) { + if ((n = read(out.fd, out.db, out.dbsz)) > 0) + continue; + + if (n == -1) + err(1, "%s", out.name); + + /* + * If reach EOF, fill with NUL characters; first, back up over + * the EOF mark. Note, cnt has not yet been incremented, so + * the EOF read does not count as a seek'd block. + */ + t_op.mt_op = MTBSR; + t_op.mt_count = 1; + if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) + err(1, "%s", out.name); + + while (cnt++ < out.offset) { + n = write(out.fd, out.db, out.dbsz); + if (n == -1) + err(1, "%s", out.name); + if ((size_t)n != out.dbsz) + errx(1, "%s: write failure", out.name); + } + break; + } +#endif +} diff --git a/cpukit/libmisc/shell/dd.h b/cpukit/libmisc/shell/dd.h new file mode 100644 index 0000000000..dc80765d48 --- /dev/null +++ b/cpukit/libmisc/shell/dd.h @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * 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. + * 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. + * + * @(#)dd.h 8.3 (Berkeley) 4/2/94 + * $FreeBSD: src/bin/dd/dd.h,v 1.22 2004/08/15 19:10:05 rwatson Exp $ + */ + +#ifndef _DD_H_ +#define _DD_H_ + +#include <stddef.h> + +#define OFF_MAX LONG_MAX + +/* Input/output stream state. */ +typedef struct { + u_char *db; /* buffer address */ + u_char *dbp; /* current buffer I/O address */ + /* XXX ssize_t? */ + size_t dbcnt; /* current buffer byte count */ + size_t dbrcnt; /* last read byte count */ + size_t dbsz; /* buffer size */ + +#define ISCHR 0x01 /* character device (warn on short) */ +#define ISPIPE 0x02 /* pipe-like (see position.c) */ +#define ISTAPE 0x04 /* tape */ +#define ISSEEK 0x08 /* valid to seek on */ +#define NOREAD 0x10 /* not readable */ +#define ISTRUNC 0x20 /* valid to ftruncate() */ + u_int flags; + + const char *name; /* name */ + int fd; /* file descriptor */ + off_t offset; /* # of blocks to skip */ +} IO; + +typedef struct { + uintmax_t in_full; /* # of full input blocks */ + uintmax_t in_part; /* # of partial input blocks */ + uintmax_t out_full; /* # of full output blocks */ + uintmax_t out_part; /* # of partial output blocks */ + uintmax_t trunc; /* # of truncated records */ + uintmax_t swab; /* # of odd-length swab blocks */ + uintmax_t bytes; /* # of bytes written */ + double start; /* start time of dd */ +} STAT; + +/* Flags (in ddflags). */ +#define C_ASCII 0x00001 +#define C_BLOCK 0x00002 +#define C_BS 0x00004 +#define C_CBS 0x00008 +#define C_COUNT 0x00010 +#define C_EBCDIC 0x00020 +#define C_FILES 0x00040 +#define C_IBS 0x00080 +#define C_IF 0x00100 +#define C_LCASE 0x00200 +#define C_NOERROR 0x00400 +#define C_NOTRUNC 0x00800 +#define C_OBS 0x01000 +#define C_OF 0x02000 +#define C_OSYNC 0x04000 +#define C_PAREVEN 0x08000 +#define C_PARNONE 0x100000 +#define C_PARODD 0x200000 +#define C_PARSET 0x400000 +#define C_SEEK 0x800000 +#define C_SKIP 0x1000000 +#define C_SPARSE 0x2000000 +#define C_SWAB 0x4000000 +#define C_SYNC 0x8000000 +#define C_UCASE 0x10000000 +#define C_UNBLOCK 0x20000000 +#define C_FILL 0x40000000 + +#define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET) + +#endif diff --git a/cpukit/libmisc/shell/extern-dd.h b/cpukit/libmisc/shell/extern-dd.h new file mode 100644 index 0000000000..25f9c02030 --- /dev/null +++ b/cpukit/libmisc/shell/extern-dd.h @@ -0,0 +1,106 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * 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. + * 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. + * + * @(#)extern.h 8.3 (Berkeley) 4/2/94 + * $FreeBSD: src/bin/dd/extern.h,v 1.15 2004/08/15 19:10:05 rwatson Exp $ + */ + +#ifndef _EXTERN_DD_H_ +#define _EXTERN_DD_H_ + +#include <setjmp.h> + +typedef struct rtems_shell_dd_globals_t { + IO in, out; /* input/output state */ + STAT st; /* statistics */ + void (*cfunc)(struct rtems_shell_dd_globals_t* globals); /* conversion function */ + uintmax_t cpy_cnt; /* # of blocks to copy */ + u_int ddflags; /* conversion options */ + size_t cbsz; /* conversion block size */ + uintmax_t files_cnt; /* # of files to copy */ + const u_char *ctab; /* conversion table */ + char fill_char; /* Character to fill with if defined */ + u_char casetab[256]; + int exit_code; + jmp_buf exit_jmp; +} rtems_shell_dd_globals; + +#define in globals->in +#define out globals->out +#define st globals->st +#define cfunc globals->cfunc +#define cpy_cnt globals->cpy_cnt +#define ddflags globals->ddflags +#define cbsz globals->cbsz +#define files_cnt globals->files_cnt +#define casetab globals->casetab +#define ctab globals->ctab +#define fill_char globals->fill_char +#define exit_jump &(globals->exit_jmp) + +#define block rtems_shell_dd_block +#define block_close rtems_shell_dd_block_close +#define dd_out rtems_shell_dd_dd_out +#define def rtems_shell_dd_def +#define def_close rtems_shell_dd_def_close +#define jcl rtems_shell_dd_jcl +#define pos_in rtems_shell_dd_pos_in +#define pos_out rtems_shell_dd_pos_out +#define summary rtems_shell_dd_summary +#define summaryx rtems_shell_dd_summaryx +#define terminate rtems_shell_dd_terminate +#define unblock rtems_shell_dd_unblock +#define unblock_close rtems_shell_dd_unblock_close + +void block(rtems_shell_dd_globals* ); +void block_close(rtems_shell_dd_globals* ); +void dd_out(rtems_shell_dd_globals* , int); +void def(rtems_shell_dd_globals* globals); +void def_close(rtems_shell_dd_globals* ); +void jcl(rtems_shell_dd_globals* , char **); +void pos_in(rtems_shell_dd_globals* ); +void pos_out(rtems_shell_dd_globals* ); +void summary(rtems_shell_dd_globals* ); +void summaryx(rtems_shell_dd_globals* , int); +void terminate(int); +void unblock(rtems_shell_dd_globals* globals); +void unblock_close(rtems_shell_dd_globals* globals); + +const u_char a2e_32V[256], a2e_POSIX[256]; +const u_char e2a_32V[256], e2a_POSIX[256]; +const u_char a2ibm_32V[256], a2ibm_POSIX[256]; + +void rtems_shell_dd_exit(rtems_shell_dd_globals* globals, int code); + +#define exit(ec) rtems_shell_dd_exit(globals, ec) + +#endif /* !_EXTERN_H_ */ diff --git a/cpukit/libmisc/shell/hexdump-conv.c b/cpukit/libmisc/shell/hexdump-conv.c new file mode 100644 index 0000000000..89f240fc33 --- /dev/null +++ b/cpukit/libmisc/shell/hexdump-conv.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 1989, 1993 + * 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. + */ + +#ifndef lint +static const char sccsid[] = "@(#)conv.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/hexdump/conv.c,v 1.9 2006/07/31 14:17:04 jkoshy Exp $"); + +#include <sys/types.h> + +#include <assert.h> +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> +#include <wctype.h> +#include "hexdump.h" + +void +conv_c(rtems_shell_hexdump_globals* globals, PR *pr, u_char *p, size_t bufsize) +{ + char buf[10]; + char const *str; + wchar_t wc; + size_t clen, oclen; + int converr, pad, width; + char peekbuf[MB_LEN_MAX]; + + printf("MB_LEN_MAX=%i\n", MB_LEN_MAX); + return; + if (pr->mbleft > 0) { + str = "**"; + pr->mbleft--; + goto strpr; + } + + 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; + } + /* + * Multibyte characters are disabled for hexdump(1) for backwards + * compatibility and consistency (none of its other output formats + * recognize them correctly). + */ + converr = 0; + if (odmode && MB_CUR_MAX > 1) { + oclen = 0; +retry: + clen = mbrtowc(&wc, (char*)p, bufsize, &pr->mbstate); + if (clen == 0) + clen = 1; + else if (clen == (size_t)-1 || (clen == (size_t)-2 && + buf == peekbuf)) { + memset(&pr->mbstate, 0, sizeof(pr->mbstate)); + wc = *p; + clen = 1; + converr = 1; + } else if (clen == (size_t)-2) { + /* + * Incomplete character; peek ahead and see if we + * can complete it. + */ + oclen = bufsize; + bufsize = peek(globals, p = (u_char*)peekbuf, MB_CUR_MAX); + goto retry; + } + clen += oclen; + } else { + wc = *p; + clen = 1; + } + if (!converr && iswprint(wc)) { + if (!odmode) { + *pr->cchar = 'c'; + (void)printf(pr->fmt, (int)wc); + } else { + *pr->cchar = 'C'; + assert(strcmp(pr->fmt, "%3C") == 0); + width = wcwidth(wc); + assert(width >= 0); + pad = 3 - width; + if (pad < 0) + pad = 0; + (void)printf("%*s%C", pad, "", wc); + pr->mbleft = clen - 1; + } + } else { + (void)sprintf(buf, "%03o", (int)*p); + str = buf; +strpr: *pr->cchar = 's'; + (void)printf(pr->fmt, str); + } +} + +void +conv_u(rtems_shell_hexdump_globals* globals, PR *pr, u_char *p) +{ + static char const * 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'; + if (odmode && *p == 0x0a) + (void)printf(pr->fmt, "nl"); + else + (void)printf(pr->fmt, list[*p]); + } else if (*p == 0x7f) { + *pr->cchar = 's'; + (void)printf(pr->fmt, "del"); + } else if (odmode && *p == 0x20) { /* od replaced space with sp */ + *pr->cchar = 's'; + (void)printf(pr->fmt, " sp"); + } else if (isprint(*p)) { + *pr->cchar = 'c'; + (void)printf(pr->fmt, *p); + } else { + *pr->cchar = 'x'; + (void)printf(pr->fmt, (int)*p); + } +} diff --git a/cpukit/libmisc/shell/hexdump-display.c b/cpukit/libmisc/shell/hexdump-display.c new file mode 100644 index 0000000000..61499e7c57 --- /dev/null +++ b/cpukit/libmisc/shell/hexdump-display.c @@ -0,0 +1,420 @@ +/* + * Copyright (c) 1989, 1993 + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)display.c 8.1 (Berkeley) 6/6/93"; +#endif +#endif /* not lint */ +#if 0 +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/hexdump/display.c,v 1.22 2004/08/04 02:47:32 tjr Exp $"); +#endif + +#include <sys/param.h> +#include <sys/stat.h> + +#include <stdint.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "hexdump.h" + +#if RTEMS_REMOVED +enum _vflag vflag = FIRST; + +static off_t address; /* address/offset in stream */ +static off_t eaddress; /* end address */ +#endif + +static void print(rtems_shell_hexdump_globals*, PR *, u_char *); + +void +display(rtems_shell_hexdump_globals* globals) +{ + FS *fs; + FU *fu; + PR *pr; + int cnt; + u_char *bp; + off_t saveaddress; + u_char savech, *savebp; + + savech = 0; + while ((bp = get(globals))) + 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(globals, pr, bp); + 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, (quad_t)eaddress); + break; + case F_TEXT: + (void)printf("%s", pr->fmt); + break; + } + } +} + +static void +print(rtems_shell_hexdump_globals* globals, PR *pr, u_char *bp) +{ + long double ldbl; + double f8; + float f4; + int16_t s2; + int8_t s8; + int32_t s4; + u_int16_t u2; + u_int32_t u4; + u_int64_t u8; + + switch(pr->flags) { + case F_ADDRESS: + (void)printf(pr->fmt, (quad_t)address); + break; + case F_BPAD: + (void)printf(pr->fmt, ""); + break; + case F_C: + conv_c(globals, pr, bp, eaddress ? eaddress - address : + blocksize - address % blocksize); + break; + case F_CHAR: + (void)printf(pr->fmt, *bp); + break; + case F_DBL: + switch(pr->bcnt) { + case 4: + bcopy(bp, &f4, sizeof(f4)); + (void)printf(pr->fmt, f4); + break; + case 8: + bcopy(bp, &f8, sizeof(f8)); + (void)printf(pr->fmt, f8); + break; + default: + if (pr->bcnt == sizeof(long double)) { + bcopy(bp, &ldbl, sizeof(ldbl)); + (void)printf(pr->fmt, ldbl); + } + break; + } + break; + case F_INT: + switch(pr->bcnt) { + case 1: + (void)printf(pr->fmt, (quad_t)(signed char)*bp); + break; + case 2: + bcopy(bp, &s2, sizeof(s2)); + (void)printf(pr->fmt, (quad_t)s2); + break; + case 4: + bcopy(bp, &s4, sizeof(s4)); + (void)printf(pr->fmt, (quad_t)s4); + break; + case 8: + bcopy(bp, &s8, sizeof(s8)); + (void)printf(pr->fmt, s8); + break; + } + break; + case F_P: + (void)printf(pr->fmt, isprint(*bp) ? *bp : '.'); + break; + case F_STR: + (void)printf(pr->fmt, (char *)bp); + break; + case F_TEXT: + (void)printf("%s", pr->fmt); + break; + case F_U: + conv_u(globals, pr, bp); + break; + case F_UINT: + switch(pr->bcnt) { + case 1: + (void)printf(pr->fmt, (u_quad_t)*bp); + break; + case 2: + bcopy(bp, &u2, sizeof(u2)); + (void)printf(pr->fmt, (u_quad_t)u2); + break; + case 4: + bcopy(bp, &u4, sizeof(u4)); + (void)printf(pr->fmt, (u_quad_t)u4); + break; + case 8: + bcopy(bp, &u8, sizeof(u8)); + (void)printf(pr->fmt, u8); + break; + } + break; + } +} + +void +bpad(PR *pr) +{ + static char const *spec = " -0+#"; + 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[0] = 's'; + pr->cchar[1] = '\0'; + for (p1 = pr->fmt; *p1 != '%'; ++p1); + for (p2 = ++p1; *p1 && index(spec, *p1); ++p1); + while ((*p2++ = *p1++)); +} + +static char **_argv; + +u_char * +get(rtems_shell_hexdump_globals* globals) +{ +#if RTEMS_REMOVED + static int ateof = 1; + static u_char *curp, *savp; +#endif + int n; + int need, nread; + int valid_save = 0; + u_char *tmpp; + + if (!curp) { + if ((curp = calloc(1, blocksize)) == NULL) + err(exit_jump, 1, NULL); + if ((savp = calloc(1, blocksize)) == NULL) + err(exit_jump, 1, NULL); + } else { + tmpp = curp; + curp = savp; + savp = tmpp; + address += blocksize; + valid_save = 1; + } + 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(globals, (char **)NULL))) { + if (odmode && address < skip) + errx(exit_jump, 1, "cannot skip past end of input"); + if (need == blocksize) + return((u_char *)NULL); + /* + * XXX bcmp() is not quite right in the presence + * of multibyte characters. + */ + if (vflag != ALL && + valid_save && + bcmp(curp, savp, nread) == 0) { + if (vflag != DUP) + (void)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), hdstdin); + if (!n) { + if (ferror(hdstdin)) + warn("%s", _argv[-1]); + ateof = 1; + continue; + } + ateof = 0; + if (length != -1) + length -= n; + if (!(need -= n)) { + /* + * XXX bcmp() is not quite right in the presence + * of multibyte characters. + */ + if (vflag == ALL || vflag == FIRST || + valid_save == 0 || + bcmp(curp, savp, blocksize) != 0) { + if (vflag == DUP || vflag == FIRST) + vflag = WAIT; + return(curp); + } + if (vflag == WAIT) + (void)printf("*\n"); + vflag = DUP; + address += blocksize; + need = blocksize; + nread = 0; + } + else + nread += n; + } +} + +size_t +peek(rtems_shell_hexdump_globals* globals, u_char *buf, size_t nbytes) +{ + size_t n, nread; + int c; + + if (length != -1 && nbytes > (unsigned int)length) + nbytes = length; + nread = 0; + while (nread < nbytes && (c = getchar()) != EOF) { + *buf++ = c; + nread++; + } + n = nread; + while (n-- > 0) { + c = *--buf; + ungetc(c, hdstdin); + } + return (nread); +} + +int +next(rtems_shell_hexdump_globals* globals, char **argv) +{ +#if RTEMS_REMOVED + static int done; +#endif + int statok; + + if (argv) { + _argv = argv; + return(1); + } + for (;;) { + if (*_argv) { + done = 1; + if (!hdstdin) { + hdstdin = malloc(sizeof(FILE)); + if (!hdstdin) + { + errno = ENOMEM; + err(exit_jump, 1, "file name allocation"); + } + } + if (!(hdstdin = fopen(*_argv, "r"))) { + warn("%s", *_argv); + exitval = 1; + ++_argv; + continue; + } + statok = 1; + } else { + errno = ECANCELED; + err(exit_jump, 1, "no file (stdin no supported)"); + if (done++) + return(0); + statok = 0; + } + if (skip) + doskip(globals, statok ? *_argv : "stdin", statok); + if (*_argv) + ++_argv; + if (!skip) + return(1); + } + /* NOTREACHED */ +} + +void +doskip(rtems_shell_hexdump_globals* globals, const char *fname, int statok) +{ + int cnt; + struct stat sb; + + if (statok) { + if (fstat(fileno(hdstdin), &sb)) + err(exit_jump, 1, "%s", fname); + if (S_ISREG(sb.st_mode) && skip >= sb.st_size) { + address += sb.st_size; + skip -= sb.st_size; + return; + } + } + if (S_ISREG(sb.st_mode)) { + if (fseeko(hdstdin, skip, SEEK_SET)) + err(exit_jump, 1, "%s", fname); + address += skip; + skip = 0; + } else { + for (cnt = 0; cnt < skip; ++cnt) + if (getchar() == EOF) + break; + address += cnt; + skip -= cnt; + } +} diff --git a/cpukit/libmisc/shell/hexdump-odsyntax.c b/cpukit/libmisc/shell/hexdump-odsyntax.c new file mode 100644 index 0000000000..db67ae53e9 --- /dev/null +++ b/cpukit/libmisc/shell/hexdump-odsyntax.c @@ -0,0 +1,451 @@ +/*- + * Copyright (c) 1990, 1993 + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)odsyntax.c 8.2 (Berkeley) 5/4/95"; +#endif /* not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/hexdump/odsyntax.c,v 1.17 2004/07/22 13:14:42 johan Exp $"); +#endif + +#include <sys/types.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <float.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "hexdump.h" + +#define __need_getopt_newlib +#include <getopt.h> + +#define PADDING " " + +#if RTEMS_REMOVED +int odmode; +#endif + +static void odadd(rtems_shell_hexdump_globals*, const char *); +static void odformat(rtems_shell_hexdump_globals*, const char *); +static const char *odformatfp(rtems_shell_hexdump_globals*, char, const char *); +static const char *odformatint(rtems_shell_hexdump_globals*, char, const char *); +static void odoffset(rtems_shell_hexdump_globals*, int, char ***); +static void odusage(rtems_shell_hexdump_globals*); + +void +oldsyntax(rtems_shell_hexdump_globals* globals, int argc, char ***argvp) +{ + static char empty[] = "", padding[] = PADDING; + int ch; + char **argv, *end; + + struct getopt_data getopt_reent; + memset(&getopt_reent, 0, sizeof(getopt_data)); + + /* Add initial (default) address format. -A may change it later. */ +#define TYPE_OFFSET 7 + add(globals, "\"%07.7_Ao\n\""); + add(globals, "\"%07.7_ao \""); + + odmode = 1; + argv = *argvp; + while ((ch = getopt_r(argc, argv, "A:aBbcDdeFfHhIij:LlN:Oost:vXx", &getopt_reent)) != -1) + switch (ch) { + case 'A': + switch (*optarg) { + case 'd': case 'o': case 'x': + fshead->nextfu->fmt[TYPE_OFFSET] = *optarg; + fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = + *optarg; + break; + case 'n': + fshead->nextfu->fmt = empty; + fshead->nextfs->nextfu->fmt = padding; + break; + default: + errx(exit_jump, 1, "%s: invalid address base", optarg); + } + break; + case 'a': + odformat(globals, "a"); + break; + case 'B': + case 'o': + odformat(globals, "o2"); + break; + case 'b': + odformat(globals, "o1"); + break; + case 'c': + odformat(globals, "c"); + break; + case 'd': + odformat(globals, "u2"); + break; + case 'D': + odformat(globals, "u4"); + break; + case 'e': /* undocumented in od */ + case 'F': + odformat(globals, "fD"); + break; + case 'f': + odformat(globals, "fF"); + break; + case 'H': + case 'X': + odformat(globals, "x4"); + break; + case 'h': + case 'x': + odformat(globals, "x2"); + break; + case 'I': + case 'L': + case 'l': + odformat(globals, "dL"); + break; + case 'i': + odformat(globals, "dI"); + break; + case 'j': + errno = 0; + skip = strtoll(optarg, &end, 0); + if (*end == 'b') + skip *= 512; + else if (*end == 'k') + skip *= 1024; + else if (*end == 'm') + skip *= 1048576L; + if (errno != 0 || skip < 0 || strlen(end) > 1) + errx(exit_jump, 1, "%s: invalid skip amount", optarg); + break; + case 'N': + if ((length = atoi(optarg)) <= 0) + errx(exit_jump, 1, "%s: invalid length", optarg); + break; + case 'O': + odformat(globals, "o4"); + break; + case 's': + odformat(globals, "d2"); + break; + case 't': + odformat(globals, optarg); + break; + case 'v': + vflag = ALL; + break; + case '?': + default: + odusage(globals); + } + + if (fshead->nextfs->nextfs == NULL) + odformat(globals, "oS"); + + argc -= getopt_reent.optind; + *argvp += getopt_reent.optind; + + if (argc) + odoffset(globals, argc, argvp); +} + +static void +odusage(rtems_shell_hexdump_globals* globals) +{ + + fprintf(stderr, +"usage: od [-aBbcDdeFfHhIiLlOosvXx] [-A base] [-j skip] [-N length] [-t type]\n"); + fprintf(stderr, +" [[+]offset[.][Bb]] [file ...]\n"); + exit(1); +} + +static void +odoffset(rtems_shell_hexdump_globals* globals, int argc, char ***argvp) +{ + char *p, *num, *end; + int base; + + /* + * 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 assume it's a file if the offset is bad. + */ + p = argc == 1 ? (*argvp)[0] : (*argvp)[1]; + + if (*p != '+' && (argc < 2 || + (!isdigit(p[0]) && (p[0] != 'x' || !isxdigit(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' && isxdigit(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; isxdigit(*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 = strtoll(num, &end, base ? base : 8); + + /* if end isn't the same as p, we got a non-octal digit */ + if (end != p) { + skip = 0; + return; + } + + if (*p) { + if (*p == 'B') { + skip *= 1024; + ++p; + } else if (*p == 'b') { + skip *= 512; + ++p; + } + } + + if (*p) { + skip = 0; + return; + } + + /* + * 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. + */ + 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'; + } + + /* Terminate file list. */ + (*argvp)[1] = NULL; +} + +static void +odformat(rtems_shell_hexdump_globals* globals, const char *fmt) +{ + char fchar; + + while (*fmt != '\0') { + switch ((fchar = *fmt++)) { + case 'a': + odadd(globals, "16/1 \"%3_u \" \"\\n\""); + break; + case 'c': + odadd(globals, "16/1 \"%3_c \" \"\\n\""); + break; + case 'o': case 'u': case 'd': case 'x': + fmt = odformatint(globals, fchar, fmt); + break; + case 'f': + fmt = odformatfp(globals, fchar, fmt); + break; + default: + errx(exit_jump, 1, "%c: unrecognised format character", fchar); + } + } +} +#define __unused + +static const char * +odformatfp(rtems_shell_hexdump_globals* globals, char fchar __unused, const char *fmt) +{ + size_t isize; + int digits; + char *end, *hdfmt; + + isize = sizeof(double); + switch (*fmt) { + case 'F': + isize = sizeof(float); + fmt++; + break; + case 'D': + isize = sizeof(double); + fmt++; + break; + case 'L': + isize = sizeof(long double); + fmt++; + break; + default: + if (isdigit((unsigned char)*fmt)) { + errno = 0; + isize = (size_t)strtoul(fmt, &end, 10); + if (errno != 0 || isize == 0) + errx(exit_jump, 1, "%s: invalid size", fmt); + fmt = (const char *)end; + } + } + switch (isize) { + case sizeof(float): + digits = FLT_DIG; + break; + case sizeof(double): + digits = DBL_DIG; + break; + default: + if (isize == sizeof(long double)) + digits = LDBL_DIG; + else + errx(exit_jump, 1, "unsupported floating point size %lu", + (u_long)isize); + } + + asprintf(&hdfmt, "%lu/%lu \" %%%d.%de \" \"\\n\"", + 16UL / (u_long)isize, (u_long)isize, digits + 8, digits); + if (hdfmt == NULL) + err(exit_jump, 1, NULL); + odadd(globals, hdfmt); + free(hdfmt); + + return (fmt); +} + +static const char * +odformatint(rtems_shell_hexdump_globals* globals, char fchar, const char *fmt) +{ + unsigned long long n; + size_t isize; + int digits; + char *end, *hdfmt; + + isize = sizeof(int); + switch (*fmt) { + case 'C': + isize = sizeof(char); + fmt++; + break; + case 'I': + isize = sizeof(int); + fmt++; + break; + case 'L': + isize = sizeof(long); + fmt++; + break; + case 'S': + isize = sizeof(short); + fmt++; + break; + default: + if (isdigit((unsigned char)*fmt)) { + errno = 0; + isize = (size_t)strtoul(fmt, &end, 10); + if (errno != 0 || isize == 0) + errx(exit_jump, 1, "%s: invalid size", fmt); + if (isize != sizeof(char) && isize != sizeof(short) && + isize != sizeof(int) && isize != sizeof(long)) + errx(exit_jump, 1, "unsupported int size %lu", + (u_long)isize); + fmt = (const char *)end; + } + } + + /* + * Calculate the maximum number of digits we need to + * fit the number. Overestimate for decimal with log + * base 8. We need one extra space for signed numbers + * to store the sign. + */ + n = (1ULL << (8 * isize)) - 1; + digits = 0; + while (n != 0) { + digits++; + n >>= (fchar == 'x') ? 4 : 3; + } + if (fchar == 'd') + digits++; + asprintf(&hdfmt, "%lu/%lu \"%*s%%%s%d%c\" \"\\n\"", + 16UL / (u_long)isize, (u_long)isize, (int)(4 * isize - digits), + "", (fchar == 'd' || fchar == 'u') ? "" : "0", digits, fchar); + if (hdfmt == NULL) + err(exit_jump, 1, NULL); + odadd(globals, hdfmt); + free(hdfmt); + + return (fmt); +} + +static void +odadd(rtems_shell_hexdump_globals* globals, const char *fmt) +{ + static int needpad; + + if (needpad) + add(globals, "\""PADDING"\""); + add(globals, fmt); + needpad = 1; +} diff --git a/cpukit/libmisc/shell/hexdump-parse.c b/cpukit/libmisc/shell/hexdump-parse.c new file mode 100644 index 0000000000..1fc06c0efa --- /dev/null +++ b/cpukit/libmisc/shell/hexdump-parse.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 1989, 1993 + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93"; +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/hexdump/parse.c,v 1.14 2006/08/09 19:12:10 maxim Exp $"); +#endif +#endif /* not lint */ + +#include <sys/types.h> + +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include "hexdump.h" + +#if RTEMS_REMOVED +FU *endfu; /* format at end-of-data */ +#endif + +void +addfile(rtems_shell_hexdump_globals* globals, char *name) +{ + unsigned char *p; + FILE *fp; + int ch; + char buf[2048 + 1]; + + if ((fp = fopen(name, "r")) == NULL) + err(exit_jump, 1, "%s", name); + while (fgets(buf, sizeof(buf), fp)) { + if (!(p = (unsigned char*)index(buf, '\n'))) { + warnx("line too long"); + while ((ch = getchar()) != '\n' && ch != EOF); + continue; + } + *p = '\0'; + for (p = (unsigned char*) buf; *p && isspace(*p); ++p); + if (!*p || *p == '#') + continue; + add(globals, (char*)p); + } + (void)fclose(fp); +} + +void +add(rtems_shell_hexdump_globals* globals, const char *fmt) +{ + unsigned const char *p, *savep; + static FS **nextfs; + FS *tfs; + FU *tfu, **nextfu; + + /* start new linked list of format units */ + if ((tfs = calloc(1, sizeof(FS))) == NULL) + err(exit_jump, 1, NULL); + 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 = (unsigned const char*)fmt;;) { + /* skip leading white space */ + for (; isspace(*p); ++p); + if (!*p) + break; + + /* allocate a new format unit and link it in */ + if ((tfu = calloc(1, sizeof(FU))) == NULL) + err(exit_jump, 1, NULL); + *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 != '/') + badfmt(globals, fmt); + /* may overwrite either white space or slash */ + tfu->reps = atoi((char*)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)) + badfmt(globals, fmt); + tfu->bcnt = atoi((char*)savep); + /* skip trailing white space */ + for (++p; isspace(*p); ++p); + } + + /* format */ + if (*p != '"') + badfmt(globals, fmt); + for (savep = ++p; *p != '"';) + if (*p++ == 0) + badfmt(globals, fmt); + if (!(tfu->fmt = malloc(p - savep + 1))) + err(exit_jump, 1, NULL); + (void) strncpy(tfu->fmt, (char*)savep, p - savep); + tfu->fmt[p - savep] = '\0'; + escape(tfu->fmt); + p++; + } +} + +static const char *spec = ".#-+ 0123456789"; + +int +size(rtems_shell_hexdump_globals* globals, FS *fs) +{ + FU *fu; + int bcnt, cursize; + unsigned 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 = (unsigned char*) fu->fmt; *fmt; ++fmt) { + if (*fmt != '%') + continue; + /* + * skip any special chars -- save precision in + * case it's a %s format. + */ + while (index(spec + 1, *++fmt)); + if (*fmt == '.' && isdigit(*++fmt)) { + prec = atoi((char*)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(rtems_shell_hexdump_globals* globals, FS *fs) +{ + enum { NOTOKAY, USEBCNT, USEPREC } sokay; + PR *pr, **nextpr; + FU *fu; + unsigned char *p1, *p2, *fmtp; + char savech, cs[3]; + int nconv, prec; + size_t len; + + nextpr = NULL; + 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 = (unsigned char*)fu->fmt; *fmtp; nextpr = &pr->nextpr) { + if ((pr = calloc(1, sizeof(PR))) == NULL) + err(exit_jump, 1, NULL); + 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 = (char*)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(spec, *p1); ++p1); + } else { + /* Skip any special chars, field width. */ + while (index(spec + 1, *++p1)); + if (*p1 == '.' && isdigit(*++p1)) { + sokay = USEPREC; + prec = atoi((char*)p1); + while (isdigit(*++p1)); + } else + sokay = NOTOKAY; + } + + p2 = p1 + 1; /* Set end pointer. */ + cs[0] = *p1; /* Set conversion string. */ + cs[1] = '\0'; + + /* + * Figure out the byte count for each conversion; + * rewrite the format as necessary, set up blank- + * padding for end of data. + */ + switch(cs[0]) { + case 'c': + pr->flags = F_CHAR; + switch(fu->bcnt) { + case 0: case 1: + pr->bcnt = 1; + break; + default: + p1[1] = '\0'; + badcnt(globals, (char*)p1); + } + break; + case 'd': case 'i': + pr->flags = F_INT; + goto isint; + case 'o': case 'u': case 'x': case 'X': + pr->flags = F_UINT; +isint: cs[2] = '\0'; + cs[1] = cs[0]; + cs[0] = 'q'; + 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'; + badcnt(globals, (char*)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: + if (fu->bcnt == sizeof(long double)) { + cs[2] = '\0'; + cs[1] = cs[0]; + cs[0] = 'L'; + pr->bcnt = sizeof(long double); + } else { + p1[1] = '\0'; + badcnt(globals, (char*)p1); + } + } + break; + case 's': + pr->flags = F_STR; + switch(sokay) { + case NOTOKAY: + badsfmt(globals); + 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': + cs[0] = 'q'; + cs[1] = p1[2]; + cs[2] = '\0'; + break; + default: + p1[3] = '\0'; + badconv(globals, (char*)p1); + } + break; + case 'c': + pr->flags = F_C; + /* cs[0] = 'c'; set in conv_c */ + goto isint2; + case 'p': + pr->flags = F_P; + cs[0] = 'c'; + goto isint2; + case 'u': + pr->flags = F_U; + /* cs[0] = 'c'; set in conv_u */ +isint2: switch(fu->bcnt) { + case 0: case 1: + pr->bcnt = 1; + break; + default: + p1[2] = '\0'; + badcnt(globals, (char*)p1); + } + break; + default: + p1[2] = '\0'; + badconv(globals, (char*)p1); + } + break; + default: + p1[1] = '\0'; + badconv(globals, (char*)p1); + } + + /* + * Copy to PR format string, set conversion character + * pointer, update original. + */ + savech = *p2; + p1[0] = '\0'; + len = strlen((char*)fmtp) + strlen(cs) + 1; + if ((pr->fmt = calloc(1, len)) == NULL) + err(exit_jump, 1, NULL); + snprintf(pr->fmt, len, "%s%s", fmtp, cs); + *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++) + errx(exit_jump, 1, "byte count with multiple conversion characters"); + } + /* + * 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 = 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 = (unsigned char*)pr->fmt, p2 = NULL; *p1; ++p1) + p2 = isspace(*p1) ? p1 : NULL; + if (p2) + pr->nospace = (char*)p2; + } + } +#ifdef DEBUG + for (fu = fs->nextfu; fu; fu = fu->nextfu) { + (void)printf("fmt:"); + for (pr = fu->nextpr; pr; pr = pr->nextpr) + (void)printf(" {%s}", pr->fmt); + (void)printf("\n"); + } +#endif +} + +void +escape(char *p1) +{ + char *p2; + + /* 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; + } + } +} + +void +badcnt(rtems_shell_hexdump_globals* globals, char *s) +{ + errx(exit_jump, 1, "%s: bad byte count", s); +} + +void +badsfmt(rtems_shell_hexdump_globals* globals) +{ + errx(exit_jump, 1, "%%s: requires a precision or a byte count"); +} + +void +badfmt(rtems_shell_hexdump_globals* globals, const char *fmt) +{ + errx(exit_jump, 1, "\"%s\": bad format", fmt); +} + +void +badconv(rtems_shell_hexdump_globals* globals, char *ch) +{ + errx(exit_jump, 1, "%%%s: bad conversion character", ch); +} diff --git a/cpukit/libmisc/shell/hexdump.h b/cpukit/libmisc/shell/hexdump.h new file mode 100644 index 0000000000..5b0e61b966 --- /dev/null +++ b/cpukit/libmisc/shell/hexdump.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 1989, 1993 + * 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. + * + * @(#)hexdump.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: src/usr.bin/hexdump/hexdump.h,v 1.9 2004/07/11 01:11:12 tjr Exp $ + */ + +#include <wchar.h> + +typedef struct _pr { + struct _pr *nextpr; /* next print unit */ +#define F_ADDRESS 0x001 /* print offset */ +#define F_BPAD 0x002 /* blank pad */ +#define F_C 0x004 /* %_c */ +#define F_CHAR 0x008 /* %c */ +#define F_DBL 0x010 /* %[EefGf] */ +#define F_INT 0x020 /* %[di] */ +#define F_P 0x040 /* %_p */ +#define F_STR 0x080 /* %s */ +#define F_U 0x100 /* %_u */ +#define F_UINT 0x200 /* %[ouXx] */ +#define F_TEXT 0x400 /* no conversions */ + u_int flags; /* flag values */ + int bcnt; /* byte count */ + char *cchar; /* conversion character */ + char *fmt; /* printf format */ + char *nospace; /* no whitespace version */ + int mbleft; /* bytes left of multibyte char. */ + mbstate_t mbstate; /* conversion state */ +} PR; + +typedef struct _fu { + struct _fu *nextfu; /* next format unit */ + struct _pr *nextpr; /* next print unit */ +#define F_IGNORE 0x01 /* %_A */ +#define F_SETREP 0x02 /* rep count set, not default */ + u_int flags; /* flag values */ + int reps; /* repetition count */ + int bcnt; /* byte count */ + char *fmt; /* format string */ +} FU; + +typedef struct _fs { /* format strings */ + struct _fs *nextfs; /* linked list of format strings */ + struct _fu *nextfu; /* linked list of format units */ + int bcnt; +} FS; + +#if 0 +extern FS *fshead; /* head of format strings list */ +extern FU *endfu; /* format at end-of-data */ +extern int blocksize; /* data block size */ +extern int exitval; /* final exit value */ +extern int odmode; /* are we acting as od(1)? */ +extern int length; /* amount of data to read */ +extern off_t skip; /* amount of data to skip at start */ +enum _vflag { ALL, DUP, FIRST, WAIT }; /* -v values */ +extern enum _vflag vflag; +#endif + +#include <setjmp.h> +#include <stdio.h> + +enum _vflag { ALL, DUP, FIRST, WAIT }; /* -v values */ +typedef struct rtems_shell_hexdump_globals_t { + FS *fshead; /* head of format strings list */ + FU *endfu; /* format at end-of-data */ + int blocksize; /* data block size */ + int exitval; /* final exit value */ + int odmode; /* are we acting as od(1)? */ + int length; /* amount of data to read */ + off_t skip; /* amount of data to skip at start */ + enum _vflag vflag; + + off_t address; + off_t eaddress; + int ateof; + u_char *curp; + u_char *savp; + int done; + + FILE* hdstdin; + + int exit_code; + jmp_buf exit_jmp; +} rtems_shell_hexdump_globals; + +#define fshead globals->fshead +#define endfu globals->endfu +#define blocksize globals->blocksize +#define exitval globals->exitval +#define odmode globals->odmode +#define length globals->length +#define skip globals->skip +#define vflag globals->vflag + +#define address globals->address +#define eaddress globals->eaddress +#define ateof globals->ateof +#define curp globals->curp +#define savp globals->savp +#define done globals->done + +#define hdstdin globals->hdstdin + +#define exit_jump &(globals->exit_jmp) + +#define add rtems_shell_hexdump_add +#define addfile rtems_shell_hexdump_addfile +#define badcnt rtems_shell_hexdump_badcnt +#define badconv rtems_shell_hexdump_badconv +#define badfmt rtems_shell_hexdump_badfmt +#define badsfmt rtems_shell_hexdump_badsfmt +#define bpad rtems_shell_hexdump_bpad +#define conv_c rtems_shell_hexdump_conv_c +#define conv_u rtems_shell_hexdump_conv_u +#define display rtems_shell_hexdump_display +#define doskip rtems_shell_hexdump_doskip +#define escape rtems_shell_hexdump_escape +#define get rtems_shell_hexdump_get +#define newsyntax rtems_shell_hexdump_newsyntax +#define next rtems_shell_hexdump_next +#define nomem rtems_shell_hexdump_nomem +#define oldsyntax rtems_shell_hexdump_oldsyntax +#define peek rtems_shell_hexdump_peek +#define rewrite rtems_shell_hexdump_rewrite +#define size rtems_shell_hexdump_size +#define usage rtems_shell_hexdump_usage + +void add(rtems_shell_hexdump_globals*, const char *); +void addfile(rtems_shell_hexdump_globals*, char *); +void badcnt(rtems_shell_hexdump_globals*, char *); +void badconv(rtems_shell_hexdump_globals*, char *); +void badfmt(rtems_shell_hexdump_globals*, const char *); +void badsfmt(rtems_shell_hexdump_globals*); +void bpad(PR *); +void conv_c(rtems_shell_hexdump_globals*, PR *, u_char *, size_t); +void conv_u(rtems_shell_hexdump_globals*, PR *, u_char *); +void display(rtems_shell_hexdump_globals*); +void doskip(rtems_shell_hexdump_globals*, const char *, int); +void escape(char *); +u_char *get(rtems_shell_hexdump_globals*); +void newsyntax(rtems_shell_hexdump_globals*, int, char ***); +int next(rtems_shell_hexdump_globals*, char **); +void nomem(void); +void oldsyntax(rtems_shell_hexdump_globals*, int, char ***); +size_t peek(rtems_shell_hexdump_globals*, u_char *, size_t); +void rewrite(rtems_shell_hexdump_globals*, FS *); +int size(rtems_shell_hexdump_globals*, FS *); +void usage(rtems_shell_hexdump_globals*); + +#define exit(ec) rtems_shell_hexdump_exit(globals, ec) + +void rtems_shell_hexdump_exit(rtems_shell_hexdump_globals* globals, int code); diff --git a/cpukit/libmisc/shell/hexsyntax.c b/cpukit/libmisc/shell/hexsyntax.c new file mode 100644 index 0000000000..664508bc9e --- /dev/null +++ b/cpukit/libmisc/shell/hexsyntax.c @@ -0,0 +1,152 @@ +/*- + * Copyright (c) 1990, 1993 + * 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. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)hexsyntax.c 8.2 (Berkeley) 5/4/95"; +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/hexdump/hexsyntax.c,v 1.12 2002/09/04 23:29:01 dwmalone Exp $"); +#endif +#endif /* not lint */ + +#include <sys/types.h> + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "hexdump.h" + +#define __need_getopt_newlib +#include <getopt.h> + +#if RTEMS_REMOVED +off_t skip; /* bytes to skip */ +#endif + +void +newsyntax(rtems_shell_hexdump_globals* globals, int argc, char ***argvp) +{ + int ch; + char *p, **argv; + + struct getopt_data getopt_reent; + memset(&getopt_reent, 0, sizeof(getopt_data)); + + argv = *argvp; + if ((p = rindex(argv[0], 'h')) != NULL && + strcmp(p, "hd") == 0) { + /* "Canonical" format, implies -C. */ + add(globals, "\"%08.8_Ax\n\""); + add(globals, "\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" "); + add(globals, "\" |\" 16/1 \"%_p\" \"|\\n\""); + } + while ((ch = getopt_r(argc, argv, "bcCde:f:n:os:vx", &getopt_reent)) != -1) + switch (ch) { + case 'b': + add(globals, "\"%07.7_Ax\n\""); + add(globals, "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\""); + break; + case 'c': + add(globals, "\"%07.7_Ax\n\""); + add(globals, "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\""); + break; + case 'C': + add(globals, "\"%08.8_Ax\n\""); + add(globals, "\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" "); + add(globals, "\" |\" 16/1 \"%_p\" \"|\\n\""); + break; + case 'd': + add(globals, "\"%07.7_Ax\n\""); + add(globals, "\"%07.7_ax \" 8/2 \" %05u \" \"\\n\""); + break; + case 'e': + add(globals, getopt_reent.optarg); + break; + case 'f': + addfile(globals, getopt_reent.optarg); + break; + case 'n': + if ((length = atoi(getopt_reent.optarg)) < 0) + errx(exit_jump, 1, "%s: bad length value", getopt_reent.optarg); + break; + case 'o': + add(globals, "\"%07.7_Ax\n\""); + add(globals, "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\""); + break; + case 's': + if ((skip = strtoll(getopt_reent.optarg, &p, 0)) < 0) + errx(exit_jump, 1, "%s: bad skip value", getopt_reent.optarg); + 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(globals, "\"%07.7_Ax\n\""); + add(globals, "\"%07.7_ax \" 8/2 \" %04x \" \"\\n\""); + break; + case '?': + usage(globals); + } + + if (!fshead) { + add(globals, "\"%07.7_Ax\n\""); + add(globals, "\"%07.7_ax \" 8/2 \"%04x \" \"\\n\""); + } + + *argvp += getopt_reent.optind; +} + +void +usage(rtems_shell_hexdump_globals* globals) +{ + (void)fprintf(stderr, "%s\n%s\n%s\n%s\n", +"usage: hexdump [-bcCdovx] [-e fmt] [-f fmt_file] [-n length]", +" [-s skip] [file ...]", +" hd [-bcdovx] [-e fmt] [-f fmt_file] [-n length]", +" [-s skip] [file ...]"); + exit(1); +} diff --git a/cpukit/libmisc/shell/main_dd.c b/cpukit/libmisc/shell/main_dd.c new file mode 100644 index 0000000000..1f08a8373a --- /dev/null +++ b/cpukit/libmisc/shell/main_dd.c @@ -0,0 +1,561 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * 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. + * 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. + */ + +#if 0 +#ifndef lint +static char const copyright[] = +"@(#) Copyright (c) 1991, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94"; +#endif /* not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/bin/dd/dd.c,v 1.43 2004/08/15 19:10:05 rwatson Exp $"); +#endif + +#include <rtems.h> +#include <rtems/shell.h> +#include <rtems/shellconfig.h> + +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/conf.h> +#if RTEMS_REMOVED +#include <sys/disklabel.h> +#endif +#include <sys/filio.h> +#include <sys/time.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <inttypes.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "dd.h" +#include "extern-dd.h" + +#define DEFFILEMODE 0 + +static void dd_close(rtems_shell_dd_globals* globals); +static void dd_in(rtems_shell_dd_globals* globals); +static void getfdtype(rtems_shell_dd_globals* globals, IO *); +static void setup(rtems_shell_dd_globals* globals); + +#if RTEMS_REMOVED +IO in, out; /* input/output state */ +STAT st; /* statistics */ +void (*cfunc)(void); /* conversion function */ +uintmax_t cpy_cnt; /* # of blocks to copy */ +static off_t pending = 0; /* pending seek if sparse */ +u_int ddflags = 0; /* conversion options */ +size_t cbsz; /* conversion block size */ +uintmax_t files_cnt = 1; /* # of files to copy */ +const u_char *ctab; /* conversion table */ +char fill_char; /* Character to fill with if defined */ +#endif + +static off_t pending = 0; /* pending seek if sparse */ + +void +rtems_shell_dd_exit (rtems_shell_dd_globals* globals, int code) +{ + globals->exit_code = code; + longjmp (globals->exit_jmp, 1); +} + +static int main_dd(rtems_shell_dd_globals* globals, int argc, char *argv[]); + +int +rtems_shell_main_dd(int argc, char *argv[]) +{ + rtems_shell_dd_globals dd_globals; + rtems_shell_dd_globals* globals = &dd_globals; + memset (globals, 0, sizeof (dd_globals)); + pending = 0; + ddflags = 0; + files_cnt = 1; + dd_globals.exit_code = 1; + if (setjmp (dd_globals.exit_jmp) == 0) + dd_globals.exit_code = main_dd (globals, argc, argv); + if (in.fd) + close(in.fd); + if (out.fd) + close(out.fd); + if (in.name) + free((void*)in.name); + if (out.name) + free((void*)out.name); + if (in.db) + free(in.db); + if (out.db && (in.db != out.db)) + free(out.db); + return dd_globals.exit_code; +} + +int +main_dd(rtems_shell_dd_globals* globals, int argc __unused, char *argv[]) +{ + (void)setlocale(LC_CTYPE, ""); + jcl(globals, argv); + setup(globals); + +#if RTEMS_REMOVED + (void)signal(SIGINFO, summaryx); + (void)signal(SIGINT, terminate); + + atexit(summary); +#endif + + while (files_cnt--) + dd_in(globals); + + dd_close(globals); + exit(0); + /* NOTREACHED */ + return 0; +} + +static int +parity(u_char c) +{ + int i; + + i = c ^ (c >> 1) ^ (c >> 2) ^ (c >> 3) ^ + (c >> 4) ^ (c >> 5) ^ (c >> 6) ^ (c >> 7); + return (i & 1); +} + +static void +setup(rtems_shell_dd_globals* globals) +{ + u_int cnt; + struct timeval tv; + + if (in.name == NULL) { + in.name = "stdin"; + in.fd = STDIN_FILENO; + } else { + in.fd = open(in.name, O_RDONLY, 0); + if (in.fd == -1) + err(exit_jump, 1, "%s", in.name); + } + + getfdtype(globals, &in); + + if (files_cnt > 1 && !(in.flags & ISTAPE)) + errx(exit_jump, 1, "files is not supported for non-tape devices"); + + if (out.name == NULL) { + /* No way to check for read access here. */ + out.fd = STDOUT_FILENO; + out.name = "stdout"; + } else { +#define OFLAGS \ + (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC)) + out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE); + /* + * May not have read access, so try again with write only. + * Without read we may have a problem if output also does + * not support seeks. + */ + if (out.fd == -1) { + out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE); + out.flags |= NOREAD; + } + if (out.fd == -1) + err(exit_jump, 1, "%s", out.name); + } + + getfdtype(globals, &out); + + /* + * Allocate space for the input and output buffers. If not doing + * record oriented I/O, only need a single buffer. + */ + if (!(ddflags & (C_BLOCK | C_UNBLOCK))) { + if ((in.db = malloc(out.dbsz + in.dbsz - 1)) == NULL) + err(exit_jump, 1, "input buffer"); + out.db = in.db; + } else if ((in.db = malloc(MAX(in.dbsz, cbsz) + cbsz)) == NULL || + (out.db = malloc(out.dbsz + cbsz)) == NULL) + err(exit_jump, 1, "output buffer"); + in.dbp = in.db; + out.dbp = out.db; + + /* Position the input/output streams. */ + if (in.offset) + pos_in(globals); + if (out.offset) + pos_out(globals); + + /* + * Truncate the output file. If it fails on a type of output file + * that it should _not_ fail on, error out. + */ + if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK) && + out.flags & ISTRUNC) + if (ftruncate(out.fd, out.offset * out.dbsz) == -1) + err(exit_jump, 1, "truncating %s", out.name); + + if (ddflags & (C_LCASE | C_UCASE | C_ASCII | C_EBCDIC | C_PARITY)) { + if (ctab != NULL) { + for (cnt = 0; cnt <= 0377; ++cnt) + casetab[cnt] = ctab[cnt]; + } else { + for (cnt = 0; cnt <= 0377; ++cnt) + casetab[cnt] = cnt; + } + if ((ddflags & C_PARITY) && !(ddflags & C_ASCII)) { + /* + * If the input is not EBCDIC, and we do parity + * processing, strip input parity. + */ + for (cnt = 200; cnt <= 0377; ++cnt) + casetab[cnt] = casetab[cnt & 0x7f]; + } + if (ddflags & C_LCASE) { + for (cnt = 0; cnt <= 0377; ++cnt) + casetab[cnt] = tolower(casetab[cnt]); + } else if (ddflags & C_UCASE) { + for (cnt = 0; cnt <= 0377; ++cnt) + casetab[cnt] = toupper(casetab[cnt]); + } + if ((ddflags & C_PARITY)) { + /* + * This should strictly speaking be a no-op, but I + * wonder what funny LANG settings could get us. + */ + for (cnt = 0; cnt <= 0377; ++cnt) + casetab[cnt] = casetab[cnt] & 0x7f; + } + if ((ddflags & C_PARSET)) { + for (cnt = 0; cnt <= 0377; ++cnt) + casetab[cnt] = casetab[cnt] | 0x80; + } + if ((ddflags & C_PAREVEN)) { + for (cnt = 0; cnt <= 0377; ++cnt) + if (parity(casetab[cnt])) + casetab[cnt] = casetab[cnt] | 0x80; + } + if ((ddflags & C_PARODD)) { + for (cnt = 0; cnt <= 0377; ++cnt) + if (!parity(casetab[cnt])) + casetab[cnt] = casetab[cnt] | 0x80; + } + + ctab = casetab; + } + + (void)gettimeofday(&tv, (struct timezone *)NULL); + st.start = tv.tv_sec + tv.tv_usec * 1e-6; +} + +static void +getfdtype(rtems_shell_dd_globals* globals, IO *io) +{ + struct stat sb; +#if RTEMS_REMOVED + int type; +#endif + + if (fstat(io->fd, &sb) == -1) + err(exit_jump, 1, "%s", io->name); + if (S_ISREG(sb.st_mode)) + io->flags |= ISTRUNC; +#if RTEMS_REMOVED + if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) { + if (ioctl(io->fd, FIODTYPE, &type) == -1) { + err(exit_jump, 1, "%s", io->name); + } else { + if (type & D_TAPE) + io->flags |= ISTAPE; + else if (type & (D_DISK | D_MEM)) + io->flags |= ISSEEK; + if (S_ISCHR(sb.st_mode) && (type & D_TAPE) == 0) + io->flags |= ISCHR; + } + return; + } +#else + io->flags |= ISSEEK; +#endif + errno = 0; + if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) + io->flags |= ISPIPE; + else + io->flags |= ISSEEK; +} + +static void +dd_in(rtems_shell_dd_globals* globals) +{ + ssize_t n; + + for (;;) { + switch (cpy_cnt) { + case -1: /* count=0 was specified */ + return; + case 0: + break; + default: + if (st.in_full + st.in_part >= (uintmax_t)cpy_cnt) + return; + break; + } + + /* + * Zero the buffer first if sync; if doing block operations, + * use spaces. + */ + if (ddflags & C_SYNC) { + if (ddflags & C_FILL) + memset(in.dbp, fill_char, in.dbsz); + else if (ddflags & (C_BLOCK | C_UNBLOCK)) + memset(in.dbp, ' ', in.dbsz); + else + memset(in.dbp, 0, in.dbsz); + } + + n = read(in.fd, in.dbp, in.dbsz); + if (n == 0) { + in.dbrcnt = 0; + return; + } + + /* Read error. */ + if (n == -1) { + /* + * If noerror not specified, die. POSIX requires that + * the warning message be followed by an I/O display. + */ + if (!(ddflags & C_NOERROR)) + err(exit_jump, 1, "%s", in.name); + warn("%s", in.name); + summary(globals); + + /* + * If it's a seekable file descriptor, seek past the + * error. If your OS doesn't do the right thing for + * raw disks this section should be modified to re-read + * in sector size chunks. + */ + if (in.flags & ISSEEK && + lseek(in.fd, (off_t)in.dbsz, SEEK_CUR)) + warn("%s", in.name); + + /* If sync not specified, omit block and continue. */ + if (!(ddflags & C_SYNC)) + continue; + + /* Read errors count as full blocks. */ + in.dbcnt += in.dbrcnt = in.dbsz; + ++st.in_full; + + /* Handle full input blocks. */ + } else if ((size_t)n == in.dbsz) { + in.dbcnt += in.dbrcnt = n; + ++st.in_full; + + /* Handle partial input blocks. */ + } else { + /* If sync, use the entire block. */ + if (ddflags & C_SYNC) + in.dbcnt += in.dbrcnt = in.dbsz; + else + in.dbcnt += in.dbrcnt = n; + ++st.in_part; + } + + /* + * POSIX states that if bs is set and no other conversions + * than noerror, notrunc or sync are specified, the block + * is output without buffering as it is read. + */ + if (ddflags & C_BS) { + out.dbcnt = in.dbcnt; + dd_out(globals, 1); + in.dbcnt = 0; + continue; + } + + if (ddflags & C_SWAB) { + if ((n = in.dbrcnt) & 1) { + ++st.swab; + --n; + } + swab(in.dbp, in.dbp, (size_t)n); + } + + in.dbp += in.dbrcnt; + (*cfunc)(globals); + } +} + +/* + * Clean up any remaining I/O and flush output. If necessary, the output file + * is truncated. + */ +static void +dd_close(rtems_shell_dd_globals* globals) +{ + if (cfunc == def) + def_close(globals); + else if (cfunc == block) + block_close(globals); + else if (cfunc == unblock) + unblock_close(globals); + if (ddflags & C_OSYNC && out.dbcnt && out.dbcnt < out.dbsz) { + if (ddflags & C_FILL) + memset(out.dbp, fill_char, out.dbsz - out.dbcnt); + else if (ddflags & (C_BLOCK | C_UNBLOCK)) + memset(out.dbp, ' ', out.dbsz - out.dbcnt); + else + memset(out.dbp, 0, out.dbsz - out.dbcnt); + out.dbcnt = out.dbsz; + } + if (out.dbcnt || pending) + dd_out(globals, 1); +} + +void +dd_out(rtems_shell_dd_globals* globals, int force) +{ + u_char *outp; + size_t cnt, i, n; + ssize_t nw; + static int warned; + int sparse; + + /* + * Write one or more blocks out. The common case is writing a full + * output block in a single write; increment the full block stats. + * Otherwise, we're into partial block writes. If a partial write, + * and it's a character device, just warn. If a tape device, quit. + * + * The partial writes represent two cases. 1: Where the input block + * was less than expected so the output block was less than expected. + * 2: Where the input block was the right size but we were forced to + * write the block in multiple chunks. The original versions of dd(1) + * never wrote a block in more than a single write, so the latter case + * never happened. + * + * One special case is if we're forced to do the write -- in that case + * we play games with the buffer size, and it's usually a partial write. + */ + outp = out.db; + for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) { + for (cnt = n;; cnt -= nw) { + sparse = 0; + if (ddflags & C_SPARSE) { + sparse = 1; /* Is buffer sparse? */ + for (i = 0; i < cnt; i++) + if (outp[i] != 0) { + sparse = 0; + break; + } + } + if (sparse && !force) { + pending += cnt; + nw = cnt; + } else { + if (pending != 0) { + if (force) + pending--; + if (lseek(out.fd, pending, SEEK_CUR) == + -1) + err(exit_jump, 2, "%s: seek error creating sparse file", + out.name); + if (force) + write(out.fd, outp, 1); + pending = 0; + } + if (cnt) + nw = write(out.fd, outp, cnt); + else + return; + } + + if (nw <= 0) { + if (nw == 0) + errx(exit_jump, 1, "%s: end of device", out.name); + if (errno != EINTR) + err(exit_jump, 1, "%s", out.name); + nw = 0; + } + outp += nw; + st.bytes += nw; + if ((size_t)nw == n) { + if (n != out.dbsz) + ++st.out_part; + else + ++st.out_full; + break; + } + ++st.out_part; + if ((size_t)nw == cnt) + break; + if (out.flags & ISTAPE) + errx(exit_jump, 1, "%s: short write on tape device", + out.name); + if (out.flags & ISCHR && !warned) { + warned = 1; + warnx("%s: short write on character device", + out.name); + } + } + if ((out.dbcnt -= n) < out.dbsz) + break; + } + + /* Reassemble the output block. */ + if (out.dbcnt) + (void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt); + out.dbp = out.db + out.dbcnt; +} + +rtems_shell_cmd_t rtems_shell_DD_Command = { + "dd", /* name */ + "dd [OPERAND]...", /* usage */ + "files", /* topic */ + rtems_shell_main_dd, /* command */ + NULL, /* alias */ + NULL /* next */ +}; diff --git a/cpukit/libmisc/shell/main_hexdump.c b/cpukit/libmisc/shell/main_hexdump.c new file mode 100644 index 0000000000..87656102fe --- /dev/null +++ b/cpukit/libmisc/shell/main_hexdump.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1989, 1993 + * 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. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)hexdump.c 8.1 (Berkeley) 6/6/93"; +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/hexdump/hexdump.c,v 1.7 2002/09/04 23:29:01 dwmalone Exp $"); +#endif +#endif /* not lint */ + +#include <rtems.h> +#include <rtems/shell.h> +#include <rtems/shellconfig.h> + +#include <sys/types.h> +#include <locale.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "hexdump.h" + +#if RTEMS_REMOVED +FS *fshead; /* head of format strings */ +int blocksize; /* data block size */ +int exitval; /* final exit value */ +int length = -1; /* max bytes to read */ +#endif + +void +rtems_shell_hexdump_exit (rtems_shell_hexdump_globals* globals, int code) +{ + globals->exit_code = code; + longjmp (globals->exit_jmp, 1); +} + +static int main_hexdump(rtems_shell_hexdump_globals* globals, int argc, char *argv[]); + +int +rtems_shell_main_hexdump(int argc, char *argv[]) +{ + rtems_shell_hexdump_globals hexdump_globals; + rtems_shell_hexdump_globals* globals = &hexdump_globals; + memset (globals, 0, sizeof (hexdump_globals)); + vflag = FIRST; + ateof = 1; + hexdump_globals.exit_code = 1; + if (setjmp (hexdump_globals.exit_jmp) == 0) + hexdump_globals.exit_code = main_hexdump (globals, argc, argv); + if (curp) + free (curp); + if (savp) + free (savp); + while (fshead) + { + FS* nextfs = fshead->nextfs; + while (fshead->nextfu) + { + FU* nextfu = fshead->nextfu->nextfu; + if (fshead->nextfu->fmt) + free(fshead->nextfu->fmt); + while (fshead->nextfu->nextpr) + { + PR* nextpr = fshead->nextfu->nextpr->nextpr; + if (((fshead->nextfu->nextpr->flags & F_TEXT) == 0) && + fshead->nextfu->nextpr->fmt) + free(fshead->nextfu->nextpr->fmt); + free(fshead->nextfu->nextpr); + fshead->nextfu->nextpr = nextpr; + } + free(fshead->nextfu); + fshead->nextfu = nextfu; + } + free(fshead); + fshead = nextfs; + } + if (hdstdin) + { + fclose (hdstdin); + free (hdstdin); + } + return hexdump_globals.exit_code; +} + +int +main_hexdump(rtems_shell_hexdump_globals* globals, int argc, char *argv[]) +{ + FS *tfs; + char *p; + +#if RTEMS_REMOVED + (void)setlocale(LC_ALL, ""); +#endif + + if (!(p = rindex(argv[0], 'o')) || strcmp(p, "od")) + newsyntax(globals, argc, &argv); + else + oldsyntax(globals, argc, &argv); + + /* figure out the data block size */ + for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) { + tfs->bcnt = size(globals, tfs); + if (blocksize < tfs->bcnt) + blocksize = tfs->bcnt; + } + /* rewrite the rules, do syntax checking */ + for (tfs = fshead; tfs; tfs = tfs->nextfs) + rewrite(globals, tfs); + + (void)next(globals, argv); + display(globals); + exit(exitval); + return exitval; +} + +rtems_shell_cmd_t rtems_shell_HEXDUMP_Command = { + "hexdump", /* name */ + "hexdump [-bcCdovx] [-e fmt] [-f fmt_file] [-n length]\n" /* usage */ + " [-s skip] [file ...]", + "files", /* topic */ + rtems_shell_main_hexdump, /* command */ + NULL, /* alias */ + NULL /* next */ +}; + diff --git a/cpukit/libmisc/shell/shellconfig.h b/cpukit/libmisc/shell/shellconfig.h index d7179b5629..2de3a38f7c 100644 --- a/cpukit/libmisc/shell/shellconfig.h +++ b/cpukit/libmisc/shell/shellconfig.h @@ -54,6 +54,8 @@ extern rtems_shell_cmd_t rtems_shell_MOUNT_Command; extern rtems_shell_cmd_t rtems_shell_UNMOUNT_Command; extern rtems_shell_cmd_t rtems_shell_BLKSYNC_Command; extern rtems_shell_cmd_t rtems_shell_FDISK_Command; +extern rtems_shell_cmd_t rtems_shell_DD_Command; +extern rtems_shell_cmd_t rtems_shell_HEXDUMP_Command; extern rtems_shell_cmd_t rtems_shell_RTC_Command; @@ -307,6 +309,16 @@ extern rtems_shell_filesystems_t *rtems_shell_Mount_filesystems[]; defined(CONFIGURE_SHELL_COMMAND_FDISK) &rtems_shell_FDISK_Command, #endif + #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \ + !defined(CONFIGURE_SHELL_NO_COMMAND_DD)) || \ + defined(CONFIGURE_SHELL_COMMAND_DD) + &rtems_shell_DD_Command, + #endif + #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \ + !defined(CONFIGURE_SHELL_NO_COMMAND_HEXDUMP)) || \ + defined(CONFIGURE_SHELL_COMMAND_HEXDUMP) + &rtems_shell_HEXDUMP_Command, + #endif /* * RTEMS Related commands |