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.
This commit is contained in:
Chris Johns
2009-06-12 05:51:43 +00:00
parent be72045b51
commit e4a3d93ab1
18 changed files with 4226 additions and 1 deletions

View File

@@ -1,3 +1,16 @@
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.
2009-06-12 Chris Johns <chrisj@rtems.org>
* libblock/include/rtems/flashdisk.h,

View File

@@ -86,7 +86,12 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \
shell/verrx.c shell/vwarn.c shell/vwarnx.c shell/warn.c shell/warnx.c \
shell/fts.c shell/print_heapinfo.c shell/main_wkspaceinfo.c \
shell/shell_script.c shell/login_prompt.c shell/login_check.c \
shell/fdisk.c shell/main_rtc.c
shell/fdisk.c shell/main_rtc.c \
shell/dd-args.c shell/main_dd.c shell/dd-conv.c shell/dd-conv_tab.c shell/dd-misc.c \
shell/dd-position.c \
shell/main_hexdump.c shell/hexdump-conv.c shell/hexdump-display.c \
shell/hexdump-odsyntax.c shell/hexdump-parse.c shell/hexsyntax.c
if LIBNETWORKING
libshell_a_SOURCES += shell/main_mount_ftp.c shell/main_mount_tftp.c \
shell/main_ifconfig.c shell/main_route.c shell/main_netstats.c \

View File

@@ -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);
}

View File

@@ -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';
}
}

View File

@@ -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 */
};

View File

@@ -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

View File

@@ -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
}

108
cpukit/libmisc/shell/dd.h Normal file
View File

@@ -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

View File

@@ -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_ */

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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 */
};

View File

@@ -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 */
};

View File

@@ -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