summaryrefslogtreecommitdiffstats
path: root/cpukit/libmisc/shell
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libmisc/shell')
-rw-r--r--cpukit/libmisc/shell/README27
-rw-r--r--cpukit/libmisc/shell/cat_file.c37
-rw-r--r--cpukit/libmisc/shell/cmds.c77
-rw-r--r--cpukit/libmisc/shell/cmp-ls.c204
-rw-r--r--cpukit/libmisc/shell/dd-args.c507
-rw-r--r--cpukit/libmisc/shell/dd-conv.c272
-rw-r--r--cpukit/libmisc/shell/dd-conv_tab.c288
-rw-r--r--cpukit/libmisc/shell/dd-misc.c112
-rw-r--r--cpukit/libmisc/shell/dd-position.c193
-rw-r--r--cpukit/libmisc/shell/dd.h108
-rw-r--r--cpukit/libmisc/shell/err.c64
-rw-r--r--cpukit/libmisc/shell/err.h84
-rw-r--r--cpukit/libmisc/shell/errx.c64
-rw-r--r--cpukit/libmisc/shell/extern-cp.h91
-rw-r--r--cpukit/libmisc/shell/extern-dd.h106
-rw-r--r--cpukit/libmisc/shell/extern-ls.h192
-rw-r--r--cpukit/libmisc/shell/fdisk.c280
-rw-r--r--cpukit/libmisc/shell/filemode.c154
-rw-r--r--cpukit/libmisc/shell/fts.c1244
-rw-r--r--cpukit/libmisc/shell/fts.h146
-rw-r--r--cpukit/libmisc/shell/hexdump-conv.c186
-rw-r--r--cpukit/libmisc/shell/hexdump-display.c431
-rw-r--r--cpukit/libmisc/shell/hexdump-odsyntax.c451
-rw-r--r--cpukit/libmisc/shell/hexdump-parse.c531
-rw-r--r--cpukit/libmisc/shell/hexdump.h183
-rw-r--r--cpukit/libmisc/shell/hexsyntax.c158
-rw-r--r--cpukit/libmisc/shell/internal.h37
-rw-r--r--cpukit/libmisc/shell/login_check.c62
-rw-r--r--cpukit/libmisc/shell/login_prompt.c209
-rw-r--r--cpukit/libmisc/shell/main_alias.c45
-rw-r--r--cpukit/libmisc/shell/main_blksync.c77
-rw-r--r--cpukit/libmisc/shell/main_cat.c60
-rw-r--r--cpukit/libmisc/shell/main_cd.c26
-rw-r--r--cpukit/libmisc/shell/main_chdir.c54
-rw-r--r--cpukit/libmisc/shell/main_chmod.c70
-rw-r--r--cpukit/libmisc/shell/main_chroot.c53
-rw-r--r--cpukit/libmisc/shell/main_cp.c555
-rw-r--r--cpukit/libmisc/shell/main_cpuuse.c61
-rw-r--r--cpukit/libmisc/shell/main_date.c80
-rw-r--r--cpukit/libmisc/shell/main_dd.c565
-rw-r--r--cpukit/libmisc/shell/main_debugrfs.c35
-rw-r--r--cpukit/libmisc/shell/main_dir.c26
-rw-r--r--cpukit/libmisc/shell/main_echo.c142
-rw-r--r--cpukit/libmisc/shell/main_exit.c26
-rw-r--r--cpukit/libmisc/shell/main_getenv.c49
-rw-r--r--cpukit/libmisc/shell/main_halt.c40
-rw-r--r--cpukit/libmisc/shell/main_help.c152
-rw-r--r--cpukit/libmisc/shell/main_hexdump.c168
-rw-r--r--cpukit/libmisc/shell/main_id.c67
-rw-r--r--cpukit/libmisc/shell/main_ifconfig.c243
-rw-r--r--cpukit/libmisc/shell/main_ln.c309
-rw-r--r--cpukit/libmisc/shell/main_logoff.c44
-rw-r--r--cpukit/libmisc/shell/main_ls.c776
-rw-r--r--cpukit/libmisc/shell/main_mallocinfo.c63
-rw-r--r--cpukit/libmisc/shell/main_mdump.c96
-rw-r--r--cpukit/libmisc/shell/main_medit.c79
-rw-r--r--cpukit/libmisc/shell/main_mfill.c77
-rw-r--r--cpukit/libmisc/shell/main_mkdir.c55
-rw-r--r--cpukit/libmisc/shell/main_mknod.c463
-rw-r--r--cpukit/libmisc/shell/main_mkrfs.c35
-rw-r--r--cpukit/libmisc/shell/main_mmove.c79
-rw-r--r--cpukit/libmisc/shell/main_mount.c133
-rw-r--r--cpukit/libmisc/shell/main_mount_nfs.c70
-rw-r--r--cpukit/libmisc/shell/main_msdosfmt.c185
-rw-r--r--cpukit/libmisc/shell/main_mv.c491
-rw-r--r--cpukit/libmisc/shell/main_mwdump.c95
-rw-r--r--cpukit/libmisc/shell/main_netstats.c138
-rw-r--r--cpukit/libmisc/shell/main_perioduse.c63
-rw-r--r--cpukit/libmisc/shell/main_pwd.c45
-rw-r--r--cpukit/libmisc/shell/main_rm.c709
-rw-r--r--cpukit/libmisc/shell/main_rmdir.c51
-rw-r--r--cpukit/libmisc/shell/main_route.c153
-rw-r--r--cpukit/libmisc/shell/main_rtc.c173
-rw-r--r--cpukit/libmisc/shell/main_setenv.c72
-rw-r--r--cpukit/libmisc/shell/main_sleep.c74
-rw-r--r--cpukit/libmisc/shell/main_stackuse.c44
-rw-r--r--cpukit/libmisc/shell/main_time.c84
-rw-r--r--cpukit/libmisc/shell/main_tty.c44
-rw-r--r--cpukit/libmisc/shell/main_umask.c62
-rw-r--r--cpukit/libmisc/shell/main_unmount.c74
-rw-r--r--cpukit/libmisc/shell/main_unsetenv.c43
-rw-r--r--cpukit/libmisc/shell/main_whoami.c48
-rw-r--r--cpukit/libmisc/shell/main_wkspaceinfo.c59
-rw-r--r--cpukit/libmisc/shell/mknod-pack_dev.c300
-rw-r--r--cpukit/libmisc/shell/mknod-pack_dev.h52
-rw-r--r--cpukit/libmisc/shell/pathnames-mv.h40
-rw-r--r--cpukit/libmisc/shell/print-ls.c492
-rw-r--r--cpukit/libmisc/shell/print_heapinfo.c37
-rw-r--r--cpukit/libmisc/shell/pwcache.c120
-rw-r--r--cpukit/libmisc/shell/shell.c987
-rw-r--r--cpukit/libmisc/shell/shell.h292
-rw-r--r--cpukit/libmisc/shell/shell_cmdset.c234
-rw-r--r--cpukit/libmisc/shell/shell_getchar.c176
-rw-r--r--cpukit/libmisc/shell/shell_getprompt.c49
-rw-r--r--cpukit/libmisc/shell/shell_makeargs.c68
-rw-r--r--cpukit/libmisc/shell/shell_script.c351
-rw-r--r--cpukit/libmisc/shell/shellconfig.c21
-rw-r--r--cpukit/libmisc/shell/shellconfig.h438
-rw-r--r--cpukit/libmisc/shell/utils-cp.c496
-rw-r--r--cpukit/libmisc/shell/utils-ls.c117
-rw-r--r--cpukit/libmisc/shell/verr.c75
-rw-r--r--cpukit/libmisc/shell/verrx.c68
-rw-r--r--cpukit/libmisc/shell/vis.c387
-rw-r--r--cpukit/libmisc/shell/vis.h91
-rw-r--r--cpukit/libmisc/shell/vwarn.c74
-rw-r--r--cpukit/libmisc/shell/vwarnx.c67
-rw-r--r--cpukit/libmisc/shell/warn.c64
-rw-r--r--cpukit/libmisc/shell/warnx.c64
-rw-r--r--cpukit/libmisc/shell/write_file.c43
109 files changed, 19281 insertions, 0 deletions
diff --git a/cpukit/libmisc/shell/README b/cpukit/libmisc/shell/README
new file mode 100644
index 0000000000..9798becc37
--- /dev/null
+++ b/cpukit/libmisc/shell/README
@@ -0,0 +1,27 @@
+#
+# $Id$
+#
+
+This directory contains a shell user extension
+primary features:
+
+ + create a user shell terminal task.
+
+This code has not been extensively tested. It is provided as a tool
+for RTEMS users to open more shell terminal.
+Suggestions and comments are appreciated.
+
+NOTES:
+
+1. printf() & getchar() works but you can't use
+ 0,1,2 like fildes. You need to use fileno(stdin),fileno(stdout),...
+
+2. You only need a termios dev to start a new session, add your new commands
+ and enjoy it.
+
+3. Telnetd daemon uses this (browse libnetworking/rtems_telnetd)
+ Enjoy it.
+
+FUTURE:
+
+1. Adding new commands in cmds.c to give file manegement to shell.
diff --git a/cpukit/libmisc/shell/cat_file.c b/cpukit/libmisc/shell/cat_file.c
new file mode 100644
index 0000000000..1a5efb4418
--- /dev/null
+++ b/cpukit/libmisc/shell/cat_file.c
@@ -0,0 +1,37 @@
+/*
+ * CAT Command Implementation
+ *
+ * Author:
+ * WORK: fernando.ruiz@ctv.es
+ * HOME: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+int rtems_shell_cat_file(FILE * out,const char * name) {
+ FILE * fd;
+ int c;
+
+ if (out) {
+ fd = fopen(name,"r");
+ if (!fd) {
+ return -1;
+ }
+ while ((c=fgetc(fd))!=EOF)
+ fputc(c,out);
+ fclose(fd);
+ }
+ return 0;
+}
+
+
diff --git a/cpukit/libmisc/shell/cmds.c b/cpukit/libmisc/shell/cmds.c
new file mode 100644
index 0000000000..e8d6c581df
--- /dev/null
+++ b/cpukit/libmisc/shell/cmds.c
@@ -0,0 +1,77 @@
+/*
+ * XXX -- Just monitor commands until those can be integrated better
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+/*-----------------------------------------------------------*
+ * with this you can call at all the rtems monitor commands.
+ * Not all work fine but you can show the rtems status and more.
+ *-----------------------------------------------------------*/
+int rtems_shell_main_monitor(int argc, char **argv) {
+ const rtems_monitor_command_entry_t *command = NULL;
+
+ if (argc < 1) {
+ return 1;
+ }
+
+ command = rtems_monitor_command_lookup(argv [0]);
+
+ if (command == NULL) {
+ return 1;
+ }
+
+ command->command_function(argc, argv, &command->command_arg, 0);
+
+ return 0;
+}
+
+static bool rtems_shell_register_command(const rtems_monitor_command_entry_t *e, void *arg __attribute__((unused)))
+{
+ /* Exclude EXIT (alias quit)*/
+ if (strcmp("exit", e->command) != 0) {
+ rtems_shell_cmd_t *shell_cmd =
+ (rtems_shell_cmd_t *) malloc(sizeof(rtems_shell_cmd_t));
+
+ if (shell_cmd != NULL) {
+ shell_cmd->name = e->command;
+ shell_cmd->topic = "monitor";
+ shell_cmd->usage = e->usage;
+ shell_cmd->command = rtems_shell_main_monitor;
+ shell_cmd->alias = NULL;
+ shell_cmd->next = NULL;
+
+ if (rtems_shell_add_cmd_struct(shell_cmd) == NULL) {
+ free(shell_cmd);
+ }
+ }
+ }
+
+ return true;
+}
+
+void rtems_shell_register_monitor_commands(void)
+{
+ rtems_monitor_command_iterate(rtems_shell_register_command, NULL);
+}
diff --git a/cpukit/libmisc/shell/cmp-ls.c b/cpukit/libmisc/shell/cmp-ls.c
new file mode 100644
index 0000000000..793e607fe1
--- /dev/null
+++ b/cpukit/libmisc/shell/cmp-ls.c
@@ -0,0 +1,204 @@
+/* $NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Fischbein.
+ *
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if 0
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cmp.c 8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fts.h>
+#include <string.h>
+
+#include "extern-ls.h"
+
+#if defined(__rtems__) || defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) || \
+ defined(_XOPEN_SOURCE) || defined(__NetBSD__)
+#define ATIMENSEC_CMP(x, op, y) ((x)->st_atime op (y)->st_atime)
+#define CTIMENSEC_CMP(x, op, y) ((x)->st_ctime op (y)->st_ctime)
+#define MTIMENSEC_CMP(x, op, y) ((x)->st_mtime op (y)->st_mtime)
+#else
+#define ATIMENSEC_CMP(x, op, y) \
+ ((x)->st_atime.tv_nsec op (y)->st_atime.tv_nsec)
+#define CTIMENSEC_CMP(x, op, y) \
+ ((x)->st_ctime.tv_nsec op (y)->st_ctime.tv_nsec)
+#define MTIMENSEC_CMP(x, op, y) \
+ ((x)->st_mtime.tv_nsec op (y)->st_mtime.tv_nsec)
+#endif
+
+int
+namecmp(const FTSENT *a, const FTSENT *b)
+{
+
+ return (strcmp(a->fts_name, b->fts_name));
+}
+
+int
+revnamecmp(const FTSENT *a, const FTSENT *b)
+{
+
+ return (strcmp(b->fts_name, a->fts_name));
+}
+
+int
+modcmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
+ return (1);
+ else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime)
+ return (-1);
+ else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (1);
+ else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (-1);
+ else
+ return (namecmp(a, b));
+}
+
+int
+revmodcmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
+ return (-1);
+ else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime)
+ return (1);
+ else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (-1);
+ else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (1);
+ else
+ return (revnamecmp(a, b));
+}
+
+int
+acccmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_atime > a->fts_statp->st_atime)
+ return (1);
+ else if (b->fts_statp->st_atime < a->fts_statp->st_atime)
+ return (-1);
+ else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (1);
+ else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (-1);
+ else
+ return (namecmp(a, b));
+}
+
+int
+revacccmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_atime > a->fts_statp->st_atime)
+ return (-1);
+ else if (b->fts_statp->st_atime < a->fts_statp->st_atime)
+ return (1);
+ else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (-1);
+ else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (1);
+ else
+ return (revnamecmp(a, b));
+}
+
+int
+statcmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
+ return (1);
+ else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime)
+ return (-1);
+ else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (1);
+ else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (-1);
+ else
+ return (namecmp(a, b));
+}
+
+int
+revstatcmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
+ return (-1);
+ else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime)
+ return (1);
+ else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
+ return (-1);
+ else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
+ return (1);
+ else
+ return (revnamecmp(a, b));
+}
+
+int
+sizecmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_size > a->fts_statp->st_size)
+ return (1);
+ if (b->fts_statp->st_size < a->fts_statp->st_size)
+ return (-1);
+ else
+ return (namecmp(a, b));
+}
+
+int
+revsizecmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if (b->fts_statp->st_size > a->fts_statp->st_size)
+ return (-1);
+ if (b->fts_statp->st_size < a->fts_statp->st_size)
+ return (1);
+ else
+ return (revnamecmp(a, b));
+}
diff --git a/cpukit/libmisc/shell/dd-args.c b/cpukit/libmisc/shell/dd-args.c
new file mode 100644
index 0000000000..a271287166
--- /dev/null
+++ b/cpukit/libmisc/shell/dd-args.c
@@ -0,0 +1,507 @@
+/*-
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 *);
+ uint_least32_t 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;
+ uint_least32_t 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 = UINT32_C(512);
+ break;
+ case 'K':
+ case 'k':
+ mult = UINT32_C(1) << 10;
+ break;
+ case 'M':
+ case 'm':
+ mult = UINT32_C(1) << 20;
+ break;
+ case 'G':
+ case 'g':
+ mult = UINT32_C(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 = UINT32_C(512);
+ break;
+ case 'K':
+ case 'k':
+ mult = UINT32_C(1) << 10;
+ break;
+ case 'M':
+ case 'm':
+ mult = UINT32_C(1) << 20;
+ break;
+ case 'G':
+ case 'g':
+ mult = UINT32_C(1) << 30;
+ break;
+ case 'W':
+ case 'w':
+ mult = sizeof(int);
+ break;
+ }
+
+ if (mult != 0) {
+ prevnum = num;
+ num *= mult;
+ /* Check for overflow. */
+ if ((prevnum > 0) != (num > 0) || num / mult != prevnum)
+ goto erange;
+ expr++;
+ }
+
+ switch (*expr) {
+ case '\0':
+ break;
+ case '*': /* Backward compatible. */
+ case 'X':
+ case 'x':
+ mult = (intmax_t)get_off_t(globals, expr + 1);
+ prevnum = num;
+ num *= mult;
+ if ((prevnum > 0) == (num > 0) && num / mult == prevnum)
+ break;
+erange:
+ errx(exit_jump, 1, "%s: %s", oper, strerror(ERANGE));
+ default:
+ errx(exit_jump, 1, "%s: illegal numeric value", oper);
+ }
+ return (num);
+}
diff --git a/cpukit/libmisc/shell/dd-conv.c b/cpukit/libmisc/shell/dd-conv.c
new file mode 100644
index 0000000000..81dba4798b
--- /dev/null
+++ b/cpukit/libmisc/shell/dd-conv.c
@@ -0,0 +1,272 @@
+/*-
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/dd/conv.c,v 1.19 2004/04/06 20:06:45 markm Exp $");
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include "dd.h"
+#include "extern-dd.h"
+
+/*
+ * def --
+ * Copy input to output. Input is buffered until reaches obs, and then
+ * output until less than obs remains. Only a single buffer is used.
+ * Worst case buffer calculation is (ibs + obs - 1).
+ */
+void
+def(rtems_shell_dd_globals* globals)
+{
+ u_char *inp;
+ const u_char *t;
+ size_t cnt;
+
+ if ((t = ctab) != NULL)
+ for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
+ *inp = t[*inp];
+
+ /* Make the output buffer look right. */
+ out.dbp = in.dbp;
+ out.dbcnt = in.dbcnt;
+
+ if (in.dbcnt >= out.dbsz) {
+ /* If the output buffer is full, write it. */
+ dd_out(globals, 0);
+
+ /*
+ * Ddout copies the leftover output to the beginning of
+ * the buffer and resets the output buffer. Reset the
+ * input buffer to match it.
+ */
+ in.dbp = out.dbp;
+ in.dbcnt = out.dbcnt;
+ }
+}
+
+void
+def_close(rtems_shell_dd_globals* globals)
+{
+ /* Just update the count, everything is already in the buffer. */
+ if (in.dbcnt)
+ out.dbcnt = in.dbcnt;
+}
+
+/*
+ * Copy variable length newline terminated records with a max size cbsz
+ * bytes to output. Records less than cbs are padded with spaces.
+ *
+ * max in buffer: MAX(ibs, cbsz)
+ * max out buffer: obs + cbsz
+ */
+void
+block(rtems_shell_dd_globals* globals)
+{
+ u_char *inp, *outp;
+ const u_char *t;
+ size_t cnt, maxlen;
+ static int intrunc;
+ int ch;
+
+ /*
+ * Record truncation can cross block boundaries. If currently in a
+ * truncation state, keep tossing characters until reach a newline.
+ * Start at the beginning of the buffer, as the input buffer is always
+ * left empty.
+ */
+ if (intrunc) {
+ for (inp = in.db, cnt = in.dbrcnt; cnt && *inp++ != '\n'; --cnt)
+ ;
+ if (!cnt) {
+ in.dbcnt = 0;
+ in.dbp = in.db;
+ return;
+ }
+ intrunc = 0;
+ /* Adjust the input buffer numbers. */
+ in.dbcnt = cnt - 1;
+ in.dbp = inp + cnt - 1;
+ }
+
+ /*
+ * Copy records (max cbsz size chunks) into the output buffer. The
+ * translation is done as we copy into the output buffer.
+ */
+ ch = 0;
+ for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) {
+ maxlen = MIN(cbsz, in.dbcnt);
+ if ((t = ctab) != NULL)
+ for (cnt = 0; cnt < maxlen && (ch = *inp++) != '\n';
+ ++cnt)
+ *outp++ = t[ch];
+ else
+ for (cnt = 0; cnt < maxlen && (ch = *inp++) != '\n';
+ ++cnt)
+ *outp++ = ch;
+ /*
+ * Check for short record without a newline. Reassemble the
+ * input block.
+ */
+ if (ch != '\n' && in.dbcnt < cbsz) {
+ (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
+ break;
+ }
+
+ /* Adjust the input buffer numbers. */
+ in.dbcnt -= cnt;
+ if (ch == '\n')
+ --in.dbcnt;
+
+ /* Pad short records with spaces. */
+ if (cnt < cbsz)
+ (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt);
+ else {
+ /*
+ * If the next character wouldn't have ended the
+ * block, it's a truncation.
+ */
+ if (!in.dbcnt || *inp != '\n')
+ ++st.trunc;
+
+ /* Toss characters to a newline. */
+ for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt)
+ ;
+ if (!in.dbcnt)
+ intrunc = 1;
+ else
+ --in.dbcnt;
+ }
+
+ /* Adjust output buffer numbers. */
+ out.dbp += cbsz;
+ if ((out.dbcnt += cbsz) >= out.dbsz)
+ dd_out(globals, 0);
+ outp = out.dbp;
+ }
+ in.dbp = in.db + in.dbcnt;
+}
+
+void
+block_close(rtems_shell_dd_globals* globals)
+{
+ /*
+ * Copy any remaining data into the output buffer and pad to a record.
+ * Don't worry about truncation or translation, the input buffer is
+ * always empty when truncating, and no characters have been added for
+ * translation. The bottom line is that anything left in the input
+ * buffer is a truncated record. Anything left in the output buffer
+ * just wasn't big enough.
+ */
+ if (in.dbcnt) {
+ ++st.trunc;
+ (void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt);
+ (void)memset(out.dbp + in.dbcnt, ctab ? ctab[' '] : ' ',
+ cbsz - in.dbcnt);
+ out.dbcnt += cbsz;
+ }
+}
+
+/*
+ * Convert fixed length (cbsz) records to variable length. Deletes any
+ * trailing blanks and appends a newline.
+ *
+ * max in buffer: MAX(ibs, cbsz) + cbsz
+ * max out buffer: obs + cbsz
+ */
+void
+unblock(rtems_shell_dd_globals* globals)
+{
+ u_char *inp;
+ const u_char *t;
+ size_t cnt;
+
+ /* Translation and case conversion. */
+ if ((t = ctab) != NULL)
+ for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
+ *inp = t[*inp];
+ /*
+ * Copy records (max cbsz size chunks) into the output buffer. The
+ * translation has to already be done or we might not recognize the
+ * spaces.
+ */
+ for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) {
+ for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t)
+ ;
+ if (t >= inp) {
+ cnt = t - inp + 1;
+ (void)memmove(out.dbp, inp, cnt);
+ out.dbp += cnt;
+ out.dbcnt += cnt;
+ }
+ *out.dbp++ = '\n';
+ if (++out.dbcnt >= out.dbsz)
+ dd_out(globals, 0);
+ }
+ if (in.dbcnt)
+ (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
+ in.dbp = in.db + in.dbcnt;
+}
+
+void
+unblock_close(rtems_shell_dd_globals* globals)
+{
+ u_char *t;
+ size_t cnt;
+
+ if (in.dbcnt) {
+ warnx("%s: short input record", in.name);
+ for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t)
+ ;
+ if (t >= in.db) {
+ cnt = t - in.db + 1;
+ (void)memmove(out.dbp, in.db, cnt);
+ out.dbp += cnt;
+ out.dbcnt += cnt;
+ }
+ ++out.dbcnt;
+ *out.dbp++ = '\n';
+ }
+}
diff --git a/cpukit/libmisc/shell/dd-conv_tab.c b/cpukit/libmisc/shell/dd-conv_tab.c
new file mode 100644
index 0000000000..782ed97be1
--- /dev/null
+++ b/cpukit/libmisc/shell/dd-conv_tab.c
@@ -0,0 +1,288 @@
+/*-
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)conv_tab.c 8.1 (Berkeley) 5/31/93";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/dd/conv_tab.c,v 1.12 2004/04/06 20:06:45 markm Exp $");
+
+#include <sys/types.h>
+
+/*
+ * There are currently six tables:
+ *
+ * ebcdic -> ascii 32V conv=oldascii
+ * ascii -> ebcdic 32V conv=oldebcdic
+ * ascii -> ibm ebcdic 32V conv=oldibm
+ *
+ * ebcdic -> ascii POSIX/S5 conv=ascii
+ * ascii -> ebcdic POSIX/S5 conv=ebcdic
+ * ascii -> ibm ebcdic POSIX/S5 conv=ibm
+ *
+ * Other tables are built from these if multiple conversions are being
+ * done.
+ *
+ * Tables used for conversions to/from IBM and EBCDIC to support an extension
+ * to POSIX P1003.2/D11. The tables referencing POSIX contain data extracted
+ * from tables 4-3 and 4-4 in P1003.2/Draft 11. The historic tables were
+ * constructed by running against a file with all possible byte values.
+ *
+ * More information can be obtained in "Correspondences of 8-Bit and Hollerith
+ * Codes for Computer Environments-A USASI Tutorial", Communications of the
+ * ACM, Volume 11, Number 11, November 1968, pp. 783-789.
+ */
+
+u_char casetab[256];
+
+/* EBCDIC to ASCII -- 32V compatible. */
+const u_char e2a_32V[] = {
+ 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */
+ 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */
+ 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */
+ 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */
+ 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */
+ 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */
+ 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */
+ 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */
+ 0247, 0250, 0133, 0056, 0074, 0050, 0053, 0041, /* 0110 */
+ 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */
+ 0260, 0261, 0135, 0044, 0052, 0051, 0073, 0136, /* 0130 */
+ 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */
+ 0270, 0271, 0174, 0054, 0045, 0137, 0076, 0077, /* 0150 */
+ 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */
+ 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */
+ 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */
+ 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */
+ 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */
+ 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320, /* 0230 */
+ 0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */
+ 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327, /* 0250 */
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, /* 0270 */
+ 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */
+ 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */
+ 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */
+ 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */
+ 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */
+ 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */
+ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */
+ 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
+
+/* ASCII to EBCDIC -- 32V compatible. */
+const u_char a2e_32V[] = {
+ 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
+ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
+ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
+ 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
+ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
+ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
+ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
+ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
+ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
+ 0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155, /* 0130 */
+ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
+ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
+ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
+ 0247, 0250, 0251, 0300, 0152, 0320, 0241, 0007, /* 0170 */
+ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
+ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
+ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
+ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
+ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
+ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
+ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
+ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
+ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
+ 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */
+ 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */
+ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
+ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
+ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
+
+/* ASCII to IBM EBCDIC -- 32V compatible. */
+const u_char a2ibm_32V[] = {
+ 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
+ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
+ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
+ 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
+ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
+ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
+ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
+ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
+ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
+ 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */
+ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
+ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
+ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
+ 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */
+ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
+ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
+ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
+ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
+ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
+ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
+ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
+ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
+ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
+ 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */
+ 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */
+ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
+ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
+ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
+
+/* EBCDIC to ASCII -- POSIX and System V compatible. */
+const u_char e2a_POSIX[] = {
+ 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */
+ 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */
+ 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */
+ 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */
+ 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */
+ 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */
+ 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */
+ 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */
+ 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174, /* 0110 */
+ 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */
+ 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176, /* 0130 */
+ 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */
+ 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077, /* 0150 */
+ 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */
+ 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */
+ 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */
+ 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */
+ 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */
+ 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320, /* 0230 */
+ 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */
+ 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327, /* 0250 */
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */
+ 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347, /* 0270 */
+ 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */
+ 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */
+ 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */
+ 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */
+ 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */
+ 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */
+ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */
+ 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
+
+/* ASCII to EBCDIC -- POSIX and System V compatible. */
+const u_char a2e_POSIX[] = {
+ 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
+ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
+ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
+ 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
+ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
+ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
+ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
+ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
+ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
+ 0347, 0350, 0351, 0255, 0340, 0275, 0232, 0155, /* 0130 */
+ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
+ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
+ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
+ 0247, 0250, 0251, 0300, 0117, 0320, 0137, 0007, /* 0170 */
+ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
+ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
+ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
+ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
+ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
+ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
+ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
+ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
+ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
+ 0216, 0217, 0220, 0152, 0233, 0234, 0235, 0236, /* 0310 */
+ 0237, 0240, 0252, 0253, 0254, 0112, 0256, 0257, /* 0320 */
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
+ 0270, 0271, 0272, 0273, 0274, 0241, 0276, 0277, /* 0340 */
+ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
+ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
+ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
+
+/* ASCII to IBM EBCDIC -- POSIX and System V compatible. */
+const u_char a2ibm_POSIX[] = {
+ 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
+ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
+ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
+ 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
+ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
+ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
+ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
+ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
+ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
+ 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */
+ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
+ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
+ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
+ 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */
+ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
+ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
+ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
+ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
+ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
+ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
+ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
+ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
+ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
+ 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */
+ 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */
+ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
+ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
+ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
diff --git a/cpukit/libmisc/shell/dd-misc.c b/cpukit/libmisc/shell/dd-misc.c
new file mode 100644
index 0000000000..dc5cc0eb09
--- /dev/null
+++ b/cpukit/libmisc/shell/dd-misc.c
@@ -0,0 +1,112 @@
+/*-
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94";
+#endif
+#endif /* not lint */
+#if 0
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/dd/misc.c,v 1.27 2004/04/06 20:06:46 markm Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dd.h"
+#include "extern-dd.h"
+
+void
+summary(rtems_shell_dd_globals* globals)
+{
+ struct timeval tv;
+ double secs;
+ char buf[100];
+
+ (void)gettimeofday(&tv, (struct timezone *)NULL);
+ secs = tv.tv_sec + tv.tv_usec * 1e-6 - st.start;
+ if (secs < 1e-6)
+ secs = 1e-6;
+ /* Use snprintf(3) so that we don't reenter stdio(3). */
+ (void)snprintf(buf, sizeof(buf),
+ "%ju+%ju records in\n%ju+%ju records out\n",
+ st.in_full, st.in_part, st.out_full, st.out_part);
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ if (st.swab) {
+ (void)snprintf(buf, sizeof(buf), "%ju odd length swab %s\n",
+ st.swab, (st.swab == 1) ? "block" : "blocks");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ }
+ if (st.trunc) {
+ (void)snprintf(buf, sizeof(buf), "%ju truncated %s\n",
+ st.trunc, (st.trunc == 1) ? "block" : "blocks");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ }
+ (void)snprintf(buf, sizeof(buf),
+ "%ju bytes transferred in %.6f secs (%.0f bytes/sec)\n",
+ st.bytes, secs, st.bytes / secs);
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+}
+
+/* ARGSUSED */
+void
+summaryx(rtems_shell_dd_globals* globals, int __unused)
+{
+ int save_errno = errno;
+
+ summary(globals);
+ errno = save_errno;
+}
+
+#if RTEMS_REMOVED
+/* ARGSUSED */
+void
+terminate(int sig)
+{
+
+ summary();
+ _exit(sig == 0 ? 0 : 1);
+}
+#endif
diff --git a/cpukit/libmisc/shell/dd-position.c b/cpukit/libmisc/shell/dd-position.c
new file mode 100644
index 0000000000..7586faddf8
--- /dev/null
+++ b/cpukit/libmisc/shell/dd-position.c
@@ -0,0 +1,193 @@
+/*-
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94";
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/dd/position.c,v 1.23 2004/04/06 20:06:46 markm Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#if RTEMS_REMOVED
+#include <sys/mtio.h>
+#endif
+
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+#include "dd.h"
+#include "extern-dd.h"
+
+/*
+ * Position input/output data streams before starting the copy. Device type
+ * dependent. Seekable devices use lseek, and the rest position by reading.
+ * Seeking past the end of file can cause null blocks to be written to the
+ * output.
+ */
+void
+pos_in(rtems_shell_dd_globals* globals)
+{
+ off_t cnt;
+ int warned;
+ ssize_t nr;
+ size_t bcnt;
+
+ /* If known to be seekable, try to seek on it. */
+ if (in.flags & ISSEEK) {
+ errno = 0;
+ if (lseek(in.fd, in.offset * in.dbsz, SEEK_CUR) == -1 &&
+ errno != 0)
+ err(exit_jump, 1, "%s", in.name);
+ return;
+ }
+
+ /* Don't try to read a really weird amount (like negative). */
+ if (in.offset < 0)
+ errx(exit_jump, 1, "%s: illegal offset", "iseek/skip");
+
+ /*
+ * Read the data. If a pipe, read until satisfy the number of bytes
+ * being skipped. No differentiation for reading complete and partial
+ * blocks for other devices.
+ */
+ for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) {
+ if ((nr = read(in.fd, in.db, bcnt)) > 0) {
+ if (in.flags & ISPIPE) {
+ if (!(bcnt -= nr)) {
+ bcnt = in.dbsz;
+ --cnt;
+ }
+ } else
+ --cnt;
+ continue;
+ }
+
+ if (nr == 0) {
+ if (files_cnt > 1) {
+ --files_cnt;
+ continue;
+ }
+ errx(exit_jump, 1, "skip reached end of input");
+ }
+
+ /*
+ * Input error -- either EOF with no more files, or I/O error.
+ * If noerror not set die. POSIX requires that the warning
+ * message be followed by an I/O display.
+ */
+ if (ddflags & C_NOERROR) {
+ if (!warned) {
+ warn("%s", in.name);
+ warned = 1;
+ summary(globals);
+ }
+ continue;
+ }
+ err(exit_jump, 1, "%s", in.name);
+ }
+}
+
+void
+pos_out(rtems_shell_dd_globals* globals)
+{
+#if RTEMS_REMOVED
+ struct mtop t_op;
+ off_t cnt;
+ ssize_t n;
+#endif
+
+ /*
+ * If not a tape, try seeking on the file. Seeking on a pipe is
+ * going to fail, but don't protect the user -- they shouldn't
+ * have specified the seek operand.
+ */
+ if (out.flags & (ISSEEK | ISPIPE)) {
+ errno = 0;
+ if (lseek(out.fd, out.offset * out.dbsz, SEEK_CUR) == -1 &&
+ errno != 0)
+ err(exit_jump, 1, "%s", out.name);
+ return;
+ }
+
+ /* Don't try to read a really weird amount (like negative). */
+ if (out.offset < 0)
+ errx(exit_jump, 1, "%s: illegal offset", "oseek/seek");
+
+#if RTEMS_REMOVED
+ /* If no read access, try using mtio. */
+ if (out.flags & NOREAD) {
+ t_op.mt_op = MTFSR;
+ t_op.mt_count = out.offset;
+
+ if (ioctl(out.fd, MTIOCTOP, &t_op) == -1)
+ err(1, "%s", out.name);
+ return;
+ }
+
+ /* Read it. */
+ for (cnt = 0; cnt < out.offset; ++cnt) {
+ if ((n = read(out.fd, out.db, out.dbsz)) > 0)
+ continue;
+
+ if (n == -1)
+ err(1, "%s", out.name);
+
+ /*
+ * If reach EOF, fill with NUL characters; first, back up over
+ * the EOF mark. Note, cnt has not yet been incremented, so
+ * the EOF read does not count as a seek'd block.
+ */
+ t_op.mt_op = MTBSR;
+ t_op.mt_count = 1;
+ if (ioctl(out.fd, MTIOCTOP, &t_op) == -1)
+ err(1, "%s", out.name);
+
+ while (cnt++ < out.offset) {
+ n = write(out.fd, out.db, out.dbsz);
+ if (n == -1)
+ err(1, "%s", out.name);
+ if ((size_t)n != out.dbsz)
+ errx(1, "%s: write failure", out.name);
+ }
+ break;
+ }
+#endif
+}
diff --git a/cpukit/libmisc/shell/dd.h b/cpukit/libmisc/shell/dd.h
new file mode 100644
index 0000000000..dc80765d48
--- /dev/null
+++ b/cpukit/libmisc/shell/dd.h
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)dd.h 8.3 (Berkeley) 4/2/94
+ * $FreeBSD: src/bin/dd/dd.h,v 1.22 2004/08/15 19:10:05 rwatson Exp $
+ */
+
+#ifndef _DD_H_
+#define _DD_H_
+
+#include <stddef.h>
+
+#define OFF_MAX LONG_MAX
+
+/* Input/output stream state. */
+typedef struct {
+ u_char *db; /* buffer address */
+ u_char *dbp; /* current buffer I/O address */
+ /* XXX ssize_t? */
+ size_t dbcnt; /* current buffer byte count */
+ size_t dbrcnt; /* last read byte count */
+ size_t dbsz; /* buffer size */
+
+#define ISCHR 0x01 /* character device (warn on short) */
+#define ISPIPE 0x02 /* pipe-like (see position.c) */
+#define ISTAPE 0x04 /* tape */
+#define ISSEEK 0x08 /* valid to seek on */
+#define NOREAD 0x10 /* not readable */
+#define ISTRUNC 0x20 /* valid to ftruncate() */
+ u_int flags;
+
+ const char *name; /* name */
+ int fd; /* file descriptor */
+ off_t offset; /* # of blocks to skip */
+} IO;
+
+typedef struct {
+ uintmax_t in_full; /* # of full input blocks */
+ uintmax_t in_part; /* # of partial input blocks */
+ uintmax_t out_full; /* # of full output blocks */
+ uintmax_t out_part; /* # of partial output blocks */
+ uintmax_t trunc; /* # of truncated records */
+ uintmax_t swab; /* # of odd-length swab blocks */
+ uintmax_t bytes; /* # of bytes written */
+ double start; /* start time of dd */
+} STAT;
+
+/* Flags (in ddflags). */
+#define C_ASCII 0x00001
+#define C_BLOCK 0x00002
+#define C_BS 0x00004
+#define C_CBS 0x00008
+#define C_COUNT 0x00010
+#define C_EBCDIC 0x00020
+#define C_FILES 0x00040
+#define C_IBS 0x00080
+#define C_IF 0x00100
+#define C_LCASE 0x00200
+#define C_NOERROR 0x00400
+#define C_NOTRUNC 0x00800
+#define C_OBS 0x01000
+#define C_OF 0x02000
+#define C_OSYNC 0x04000
+#define C_PAREVEN 0x08000
+#define C_PARNONE 0x100000
+#define C_PARODD 0x200000
+#define C_PARSET 0x400000
+#define C_SEEK 0x800000
+#define C_SKIP 0x1000000
+#define C_SPARSE 0x2000000
+#define C_SWAB 0x4000000
+#define C_SYNC 0x8000000
+#define C_UCASE 0x10000000
+#define C_UNBLOCK 0x20000000
+#define C_FILL 0x40000000
+
+#define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET)
+
+#endif
diff --git a/cpukit/libmisc/shell/err.c b/cpukit/libmisc/shell/err.c
new file mode 100644
index 0000000000..610ea598a2
--- /dev/null
+++ b/cpukit/libmisc/shell/err.c
@@ -0,0 +1,64 @@
+/* $NetBSD: err.c,v 1.25 2005/09/13 13:51:50 christos Exp $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: err.c,v 1.25 2005/09/13 13:51:50 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <stdarg.h>
+
+#ifdef __weak_alias
+__weak_alias(err, _err)
+#endif
+
+__dead void
+err(jmp_buf* exit_jmp, int eval, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ verr(exit_jmp, eval, fmt, ap);
+ va_end(ap);
+}
diff --git a/cpukit/libmisc/shell/err.h b/cpukit/libmisc/shell/err.h
new file mode 100644
index 0000000000..f028d3b151
--- /dev/null
+++ b/cpukit/libmisc/shell/err.h
@@ -0,0 +1,84 @@
+/* $NetBSD: err.h,v 1.14 2005/02/03 04:39:32 perry Exp $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ *
+ * @(#)err.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _ERR_H_
+#define _ERR_H_
+
+/*
+ * Don't use va_list in the err/warn prototypes. Va_list is typedef'd in two
+ * places (<machine/varargs.h> and <machine/stdarg.h>), so if we include one
+ * of them here we may collide with the utility's includes. It's unreasonable
+ * for utilities to have to include one of them to include err.h, so we get
+ * _BSD_VA_LIST_ from <machine/ansi.h> and use it.
+ */
+#include <machine/ansi.h>
+#include <sys/cdefs.h>
+
+#include <stdarg.h>
+#define _BSD_VA_LIST_ va_list
+
+#define __dead
+
+#define err rtems_shell_err
+#define verr rtems_shell_verr
+#define errx rtems_shell_errx
+#define verrx rtems_shell_verrx
+#define warn rtems_shell_warn
+#define vwarn rtems_shell_vwarn
+#define warnx rtems_shell_warnx
+#define vwarnx rtems_shell_vwarnx
+
+#include <setjmp.h>
+
+extern jmp_buf rtems_shell_bsd_exit_recover;
+
+__BEGIN_DECLS
+__dead void err(jmp_buf*, int, const char *, ...)
+ __attribute__((__noreturn__, __format__(__printf__, 3, 4)));
+__dead void verr(jmp_buf*, int, const char *, _BSD_VA_LIST_)
+ __attribute__((__noreturn__, __format__(__printf__, 3, 0)));
+__dead void errx(jmp_buf*, int, const char *, ...)
+ __attribute__((__noreturn__, __format__(__printf__, 3, 4)));
+__dead void verrx(jmp_buf*, int, const char *, _BSD_VA_LIST_)
+ __attribute__((__noreturn__, __format__(__printf__, 3, 0)));
+void warn(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+void vwarn(const char *, _BSD_VA_LIST_)
+ __attribute__((__format__(__printf__, 1, 0)));
+void warnx(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+void vwarnx(const char *, _BSD_VA_LIST_)
+ __attribute__((__format__(__printf__, 1, 0)));
+__END_DECLS
+
+#endif /* !_ERR_H_ */
diff --git a/cpukit/libmisc/shell/errx.c b/cpukit/libmisc/shell/errx.c
new file mode 100644
index 0000000000..04e15e128b
--- /dev/null
+++ b/cpukit/libmisc/shell/errx.c
@@ -0,0 +1,64 @@
+/* $NetBSD: errx.c,v 1.13 2005/09/13 13:51:50 christos Exp $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: errx.c,v 1.13 2005/09/13 13:51:50 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <stdarg.h>
+
+#ifdef __weak_alias
+__weak_alias(errx, _errx)
+#endif
+
+__dead void
+errx(jmp_buf* exit_jmp, int eval, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ verrx(exit_jmp, eval, fmt, ap);
+ va_end(ap);
+}
diff --git a/cpukit/libmisc/shell/extern-cp.h b/cpukit/libmisc/shell/extern-cp.h
new file mode 100644
index 0000000000..093b30ff10
--- /dev/null
+++ b/cpukit/libmisc/shell/extern-cp.h
@@ -0,0 +1,91 @@
+/* $NetBSD: extern.h,v 1.12 2005/10/15 18:22:18 christos Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * 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. 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.2 (Berkeley) 4/1/94
+ */
+
+#ifndef _EXTERN_CP_H_
+#define _EXTERN_CP_H_
+
+#define PATH_T RTEMS_SHELL_CP_PATH_T
+
+typedef struct {
+ char *p_end; /* pointer to NULL at end of path */
+ char *target_end; /* pointer to end of target base */
+ char p_path[MAXPATHLEN + 1]; /* pointer to the start of a path */
+} PATH_T;
+
+#include <setjmp.h>
+
+typedef struct {
+ PATH_T to;
+ int info;
+ uid_t myuid;
+ int fflag, iflag, lflag, nflag, pflag, vflag;
+ mode_t myumask;
+ jmp_buf exit_jmp;
+} rtems_shell_cp_globals;
+
+#define to cp_globals->to
+#define info cp_globals->info
+#define myuid cp_globals->myuid
+#define fflag cp_globals->fflag
+#define iflag cp_globals->iflag
+#define lflag cp_globals->lflag
+#define nflag cp_globals->nflag
+#define pflag cp_globals->pflag
+#define vflag cp_globals->vflag
+#define myumask cp_globals->myumask
+#define exit_jump &(cp_globals->exit_jmp)
+
+#define copy_fifo rtems_shell_cp_copy_fifo
+#define copy_file rtems_shell_cp_copy_file
+#define copy_link rtems_shell_cp_copy_link
+#define copy_special rtems_shell_cp_copy_special
+#define set_utimes rtems_shell_cp_set_utimes
+#define setfile rtems_shell_cp_setfile
+#define usage rtems_shell_cp_usage
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int copy_fifo(rtems_shell_cp_globals* cp_globals, struct stat *, int);
+int copy_file(rtems_shell_cp_globals* cp_globals, FTSENT *, int);
+int copy_link(rtems_shell_cp_globals* cp_globals, FTSENT *, int);
+int copy_special(rtems_shell_cp_globals* cp_globals, struct stat *, int);
+int set_utimes(const char *, struct stat *);
+int setfile(rtems_shell_cp_globals* cp_globals, struct stat *, int);
+int preserve_dir_acls(struct stat *, char *, char *);
+int preserve_fd_acls(int, int);
+void usage(rtems_shell_cp_globals* cp_globals);
+
+__END_DECLS
+
+#endif /* !_EXTERN_H_ */
diff --git a/cpukit/libmisc/shell/extern-dd.h b/cpukit/libmisc/shell/extern-dd.h
new file mode 100644
index 0000000000..405d460ef3
--- /dev/null
+++ b/cpukit/libmisc/shell/extern-dd.h
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.3 (Berkeley) 4/2/94
+ * $FreeBSD: src/bin/dd/extern.h,v 1.15 2004/08/15 19:10:05 rwatson Exp $
+ */
+
+#ifndef _EXTERN_DD_H_
+#define _EXTERN_DD_H_
+
+#include <setjmp.h>
+
+typedef struct rtems_shell_dd_globals_t {
+ IO in, out; /* input/output state */
+ STAT st; /* statistics */
+ void (*cfunc)(struct rtems_shell_dd_globals_t* globals); /* conversion function */
+ uintmax_t cpy_cnt; /* # of blocks to copy */
+ u_int ddflags; /* conversion options */
+ size_t cbsz; /* conversion block size */
+ uintmax_t files_cnt; /* # of files to copy */
+ const u_char *ctab; /* conversion table */
+ char fill_char; /* Character to fill with if defined */
+ u_char casetab[256];
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_dd_globals;
+
+#define in globals->in
+#define out globals->out
+#define st globals->st
+#define cfunc globals->cfunc
+#define cpy_cnt globals->cpy_cnt
+#define ddflags globals->ddflags
+#define cbsz globals->cbsz
+#define files_cnt globals->files_cnt
+#define casetab globals->casetab
+#define ctab globals->ctab
+#define fill_char globals->fill_char
+#define exit_jump &(globals->exit_jmp)
+
+#define block rtems_shell_dd_block
+#define block_close rtems_shell_dd_block_close
+#define dd_out rtems_shell_dd_dd_out
+#define def rtems_shell_dd_def
+#define def_close rtems_shell_dd_def_close
+#define jcl rtems_shell_dd_jcl
+#define pos_in rtems_shell_dd_pos_in
+#define pos_out rtems_shell_dd_pos_out
+#define summary rtems_shell_dd_summary
+#define summaryx rtems_shell_dd_summaryx
+#define terminate rtems_shell_dd_terminate
+#define unblock rtems_shell_dd_unblock
+#define unblock_close rtems_shell_dd_unblock_close
+
+void block(rtems_shell_dd_globals* );
+void block_close(rtems_shell_dd_globals* );
+void dd_out(rtems_shell_dd_globals* , int);
+void def(rtems_shell_dd_globals* globals);
+void def_close(rtems_shell_dd_globals* );
+void jcl(rtems_shell_dd_globals* , char **);
+void pos_in(rtems_shell_dd_globals* );
+void pos_out(rtems_shell_dd_globals* );
+void summary(rtems_shell_dd_globals* );
+void summaryx(rtems_shell_dd_globals* , int);
+void terminate(int);
+void unblock(rtems_shell_dd_globals* globals);
+void unblock_close(rtems_shell_dd_globals* globals);
+
+extern const u_char a2e_32V[256], a2e_POSIX[256];
+extern const u_char e2a_32V[256], e2a_POSIX[256];
+extern const u_char a2ibm_32V[256], a2ibm_POSIX[256];
+
+void rtems_shell_dd_exit(rtems_shell_dd_globals* globals, int code);
+
+#define exit(ec) rtems_shell_dd_exit(globals, ec)
+
+#endif /* !_EXTERN_H_ */
diff --git a/cpukit/libmisc/shell/extern-ls.h b/cpukit/libmisc/shell/extern-ls.h
new file mode 100644
index 0000000000..33f713b66e
--- /dev/null
+++ b/cpukit/libmisc/shell/extern-ls.h
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Fischbein.
+ *
+ * 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.
+ *
+ * from: @(#)ls.h 8.1 (Berkeley) 5/31/93
+ * $FreeBSD: src/bin/ls/ls.h,v 1.23 2008/04/04 03:57:46 grog Exp $
+ */
+
+#ifndef _EXTERN_LS_H_
+#define _EXTERN_LS_H_
+
+#define NO_PRINT 1
+//#define COLORLS 1
+
+#include <sys/cdefs.h>
+#include <setjmp.h>
+
+#define major(d) rtems_filesystem_dev_major_t(d)
+#define minor(d) rtems_filesystem_dev_minor_t(d)
+
+const char *user_from_uid(uid_t uid, int nouser);
+
+typedef struct {
+ int blocksize;
+ int termwidth;
+ int sortkey;
+ int rval;
+ int output;
+ time_t now;
+
+ int f_accesstime;
+ int f_column;
+ int f_columnacross;
+ int f_flags;
+ int f_grouponly;
+ int f_humanize;
+ int f_inode;
+ int f_listdir;
+ int f_listdot;
+ int f_longform;
+ int f_nonprint;
+ int f_nosort;
+ int f_numericonly;
+ int f_octal;
+ int f_octal_escape;
+ int f_recursive;
+ int f_reversesort;
+ int f_sectime;
+ int f_singlecol;
+ int f_size;
+ int f_statustime;
+ int f_stream;
+ int f_type;
+ int f_typedir;
+ int f_whiteout;
+
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_ls_globals;
+
+#define blocksize globals->blocksize
+#define termwidth globals->termwidth
+#define sortkey globals->sortkey
+#define rval globals->rval
+#define output globals->output
+#define now globals->now
+
+#define f_accesstime globals->f_accesstime
+#define f_column globals->f_column
+#define f_columnacross globals->f_columnacross
+#define f_flags globals->f_flags
+#define f_grouponly globals->f_grouponly
+#define f_humanize globals->f_humanize
+#define f_inode globals->f_inode
+#define f_listdir globals->f_listdir
+#define f_listdot globals->f_listdot
+#define f_longform globals->f_longform
+#define f_nonprint globals->f_nonprint
+#define f_nosort globals->f_nosort
+#define f_numericonly globals->f_numericonly
+#define f_octal globals->f_octal
+#define f_octal_escape globals->f_octal_escape
+#define f_recursive globals->f_recursive
+#define f_reversesort globals->f_reversesort
+#define f_sectime globals->f_sectime
+#define f_singlecol globals->f_singlecol
+#define f_size globals->f_size
+#define f_statustime globals->f_statustime
+#define f_stream globals->f_stream
+#define f_type globals->f_type
+#define f_typedir globals->f_typedir
+#define f_whiteout globals->f_whiteout
+
+#define exit_jump &(globals->exit_jmp)
+
+void rtems_shell_ls_exit(rtems_shell_ls_globals* globals, int code);
+
+#define exit(ec) rtems_shell_ls_exit(globals, ec)
+
+
+typedef struct {
+ FTSENT *list;
+ u_int64_t btotal;
+ u_int64_t stotal;
+ int entries;
+ int maxlen;
+ int s_block;
+ int s_flags;
+ int s_group;
+ int s_inode;
+ int s_nlink;
+ int s_size;
+ int s_user;
+ int s_major;
+ int s_minor;
+} DISPLAY;
+
+typedef struct {
+ char *user;
+ char *group;
+ char *flags;
+ char data[1];
+} NAMES;
+
+#define acccmp rtems_shell_ls_acccmp
+#define revacccmp rtems_shell_ls_revacccmp
+#define modcmp rtems_shell_ls_modcmp
+#define revmodcmp rtems_shell_ls_revmodcmp
+#define namecmp rtems_shell_ls_namecmp
+#define revnamecmp rtems_shell_ls_revnamecmp
+#define statcmp rtems_shell_ls_statcmp
+#define revstatcmp rtems_shell_ls_revstatcmp
+#define sizecmp rtems_shell_ls_sizecmp
+#define revsizecmp rtems_shell_ls_revsizecmp
+#define printescaped rtems_shell_ls_printescaped
+#define printacol rtems_shell_ls_printacol
+#define printcol rtems_shell_ls_printcol
+#define printlong rtems_shell_ls_printlong
+#define printscol rtems_shell_ls_printscol
+#define printstream rtems_shell_ls_printstream
+#define usage rtems_shell_ls_usage
+
+int acccmp(const FTSENT *, const FTSENT *);
+int revacccmp(const FTSENT *, const FTSENT *);
+int modcmp(const FTSENT *, const FTSENT *);
+int revmodcmp(const FTSENT *, const FTSENT *);
+int namecmp(const FTSENT *, const FTSENT *);
+int revnamecmp(const FTSENT *, const FTSENT *);
+int statcmp(const FTSENT *, const FTSENT *);
+int revstatcmp(const FTSENT *, const FTSENT *);
+int sizecmp(const FTSENT *, const FTSENT *);
+int revsizecmp(const FTSENT *, const FTSENT *);
+
+int printescaped(rtems_shell_ls_globals* globals, const char *);
+void printacol(rtems_shell_ls_globals* globals, DISPLAY *);
+void printcol(rtems_shell_ls_globals* globals, DISPLAY *);
+void printlong(rtems_shell_ls_globals* globals, DISPLAY *);
+void printscol(rtems_shell_ls_globals* globals, DISPLAY *);
+void printstream(rtems_shell_ls_globals* globals, DISPLAY *);
+int safe_print(rtems_shell_ls_globals* globals, const char *);
+void usage(rtems_shell_ls_globals* globals);
+
+void strmode(mode_t mode, char *p);
+
+#endif /* !_EXTERN_H_ */
diff --git a/cpukit/libmisc/shell/fdisk.c b/cpukit/libmisc/shell/fdisk.c
new file mode 100644
index 0000000000..37a2e217dc
--- /dev/null
+++ b/cpukit/libmisc/shell/fdisk.c
@@ -0,0 +1,280 @@
+/**
+ * @file
+ *
+ * Block device partition management.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rtems/bdpart.h>
+#include <rtems/error.h>
+#include <rtems/shell.h>
+
+#define RTEMS_BDPART_SHELL_ERROR( fmt, ...) \
+ do { \
+ printf( "error: " fmt "\n", ##__VA_ARGS__); \
+ return -1; \
+ } while (0)
+
+#define RTEMS_BDPART_SHELL_ERROR_SC( sc, fmt, ...) \
+ if ((sc) != RTEMS_SUCCESSFUL) { \
+ printf( "error: " fmt ": %s\n", ##__VA_ARGS__, rtems_status_text( sc)); \
+ return -1; \
+ }
+
+typedef enum {
+ RTEMS_BDPART_SHELL_FS,
+ RTEMS_BDPART_SHELL_N,
+ RTEMS_BDPART_SHELL_MBR,
+ RTEMS_BDPART_SHELL_GPT
+} rtems_bdpart_shell_state;
+
+static const char rtems_bdpart_shell_usage [] =
+ "disk format and utility functions\n"
+ "\n"
+ "fdisk DISK_NAME\n"
+ "\tprints the partition table\n"
+ "\n"
+ "fdisk DISK_NAME [FS N1 [N2 ... ]] ... [write] [FORMAT]\n"
+ "\tcreates a new partition table\n"
+ "\n"
+ "fdisk DISK_NAME register\n"
+ "\tcreates a logical disk for each partition of the disk\n"
+ "\n"
+ "fdisk DISK_NAME unregister\n"
+ "\tdeletes the logical disks associated with the partitions of the disk\n"
+ "\n"
+ "fdisk DISK_NAME mount\n"
+ "\tmounts the file system of each partition of the disk\n"
+ "\n"
+ "fdisk DISK_NAME unmount\n"
+ "\tunmounts the file system of each partition of the disk\n"
+ "\n"
+ "option values:\n"
+ "\tDISK_NAME: absolute path to disk device like '/dev/hda'\n"
+ "\tN*: weights of positive integers\n"
+ "\tFS: 0x00 ... 0xff, fat12, fat16, fat32, data\n"
+ "\twrite: write the new partition table to the disk\n"
+ "\tFORMAT: mbr [[no]dos], gpt";
+
+static int rtems_bdpart_shell_main( int argc, char **argv)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_bdpart_format format;
+ rtems_bdpart_partition pt [RTEMS_BDPART_PARTITION_NUMBER_HINT];
+ unsigned dist [RTEMS_BDPART_PARTITION_NUMBER_HINT];
+ size_t count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
+ const char *disk_name = NULL;
+ const char *mount_base = "/mnt";
+ bool do_create = false;
+ bool do_read = false;
+ bool do_write = false;
+ bool do_register = false;
+ bool do_unregister = false;
+ bool do_mount = false;
+ bool do_unmount = false;
+ bool do_dump = false;
+
+ if (argc < 2) {
+ puts( rtems_bdpart_shell_usage);
+ return -1;
+ }
+
+ disk_name = argv [1];
+
+ if (argc == 2) {
+ do_read = true;
+ do_dump = true;
+ } else if (argc == 3) {
+ /* Check option */
+ if (strcmp( argv [2], "register") == 0) {
+ do_read = true;
+ do_register = true;
+ } else if (strcmp( argv [2], "unregister") == 0) {
+ do_read = true;
+ do_unregister = true;
+ } else if (strcmp( argv [2], "mount") == 0) {
+ do_read = true;
+ do_mount = true;
+ } else if (strcmp( argv [2], "unmount") == 0) {
+ do_read = true;
+ do_unmount = true;
+ } else {
+ RTEMS_BDPART_SHELL_ERROR( "unexpected option: %s", argv [2]);
+ }
+ } else {
+ rtems_bdpart_shell_state state = RTEMS_BDPART_SHELL_FS;
+ uint8_t current_type = RTEMS_BDPART_MBR_FAT_32;
+ size_t i = 0;
+ int ai = 0;
+
+ /* Clear partition table */
+ memset( pt, 0, sizeof( pt));
+
+ /* Default format */
+ format.type = RTEMS_BDPART_FORMAT_MBR;
+ format.mbr.disk_id = 0;
+ format.mbr.dos_compatibility = true;
+
+ for (ai = 2; ai < argc; ++ai) {
+ char *s = argv [ai];
+ unsigned long v = 0;
+ char *end = NULL;
+
+ if (strlen( s) == 0) {
+ continue;
+ } else if (strcmp( s, "write") == 0) {
+ do_write = true;
+ continue;
+ } else if (strcmp( s, "mbr") == 0) {
+ state = RTEMS_BDPART_SHELL_MBR;
+ format.type = RTEMS_BDPART_FORMAT_MBR;
+ continue;
+ } else if (strcmp( s, "gpt") == 0) {
+ state = RTEMS_BDPART_SHELL_GPT;
+ format.type = RTEMS_BDPART_FORMAT_GPT;
+ continue;
+ }
+
+ switch (state) {
+ case RTEMS_BDPART_SHELL_FS:
+ v = strtoul( s, &end, 16);
+ if (*end == '\0') {
+ if (v <= 0xffU) {
+ current_type = (uint8_t) v;
+ } else {
+ RTEMS_BDPART_SHELL_ERROR( "type value out of range: %s", argv [ai]);
+ }
+ } else if (strcmp( s, "fat32") == 0) {
+ current_type = RTEMS_BDPART_MBR_FAT_32;
+ } else if (strcmp( s, "data") == 0) {
+ current_type = RTEMS_BDPART_MBR_DATA;
+ } else if (strcmp( s, "fat16") == 0) {
+ current_type = RTEMS_BDPART_MBR_FAT_16;
+ } else if (strcmp( s, "fat12") == 0) {
+ current_type = RTEMS_BDPART_MBR_FAT_12;
+ } else {
+ RTEMS_BDPART_SHELL_ERROR( "unexpected option: %s", argv [ai]);
+ }
+ state = RTEMS_BDPART_SHELL_N;
+ break;
+ case RTEMS_BDPART_SHELL_N:
+ v = strtoul( s, &end, 10);
+ if (*end == '\0') {
+ rtems_bdpart_to_partition_type( current_type, pt [i].type);
+ dist [i] = v;
+ if (i < count) {
+ ++i;
+ } else {
+ RTEMS_BDPART_SHELL_ERROR( "too many partitions");
+ }
+ } else {
+ --ai;
+ state = RTEMS_BDPART_SHELL_FS;
+ }
+ break;
+ case RTEMS_BDPART_SHELL_MBR:
+ if (strcmp( s, "dos") == 0) {
+ format.mbr.dos_compatibility = true;
+ } else if (strcmp( s, "nodos") == 0) {
+ format.mbr.dos_compatibility = false;
+ } else {
+ RTEMS_BDPART_SHELL_ERROR( "unexpected option: %s", argv [ai]);
+ }
+ break;
+ case RTEMS_BDPART_SHELL_GPT:
+ RTEMS_BDPART_SHELL_ERROR( "unexpected option: %s", argv [ai]);
+ default:
+ RTEMS_BDPART_SHELL_ERROR( "fdisk interal error");
+ }
+ }
+
+ /* Partition number */
+ count = i;
+
+ /* Actions */
+ do_create = true;
+ do_dump = true;
+ if (do_write) {
+ do_read = true;
+ }
+ }
+
+ if (do_create) {
+ /* Create partitions */
+ sc = rtems_bdpart_create( disk_name, &format, pt, dist, count);
+ RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot create partitions for '%s'", disk_name);
+ }
+
+ if (do_write) {
+ /* Write partitions */
+ sc = rtems_bdpart_write( disk_name, &format, pt, count);
+ RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot write partitions to '%s'", disk_name);
+ }
+
+ if (do_read) {
+ /* Read partitions */
+ count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
+ sc = rtems_bdpart_read( disk_name, &format, pt, &count);
+ RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot read partitions from '%s'", disk_name);
+ }
+
+ if (do_register) {
+ /* Register partitions */
+ sc = rtems_bdpart_register( disk_name, pt, count);
+ RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot register partitions of '%s'", disk_name);
+ }
+
+ if (do_unregister) {
+ /* Unregister partitions */
+ sc = rtems_bdpart_unregister( disk_name, pt, count);
+ RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot unregister partitions of '%s'", disk_name);
+ }
+
+ if (do_mount) {
+ /* Mount partitions */
+ sc = rtems_bdpart_mount( disk_name, pt, count, mount_base);
+ RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot mount partitions of '%s' to '%s'", disk_name, mount_base);
+ }
+
+ if (do_unmount) {
+ /* Unmount partitions */
+ sc = rtems_bdpart_unmount( disk_name, pt, count, mount_base);
+ RTEMS_BDPART_SHELL_ERROR_SC( sc, "cannot unmount partitions of '%s'", disk_name);
+ }
+
+ if (do_dump) {
+ /* Dump partitions */
+ rtems_bdpart_dump( pt, count);
+ }
+
+ return 0;
+}
+
+struct rtems_shell_cmd_tt rtems_shell_FDISK_Command = {
+ .name = "fdisk",
+ .usage = rtems_bdpart_shell_usage,
+ .topic = "files",
+ .command = rtems_bdpart_shell_main,
+ .alias = NULL,
+ .next = NULL
+};
diff --git a/cpukit/libmisc/shell/filemode.c b/cpukit/libmisc/shell/filemode.c
new file mode 100644
index 0000000000..9a5d0440b4
--- /dev/null
+++ b/cpukit/libmisc/shell/filemode.c
@@ -0,0 +1,154 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strmode.c,v 1.5 2007/01/09 00:28:12 imp Exp $");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+void
+strmode(
+ mode_t mode,
+ char *p)
+{
+ /* print type */
+ switch (mode & S_IFMT) {
+ case S_IFDIR: /* directory */
+ *p++ = 'd';
+ break;
+ case S_IFCHR: /* character special */
+ *p++ = 'c';
+ break;
+ case S_IFBLK: /* block special */
+ *p++ = 'b';
+ break;
+ case S_IFREG: /* regular */
+ *p++ = '-';
+ break;
+ case S_IFLNK: /* symbolic link */
+ *p++ = 'l';
+ break;
+ case S_IFSOCK: /* socket */
+ *p++ = 's';
+ break;
+#ifdef S_IFIFO
+ case S_IFIFO: /* fifo */
+ *p++ = 'p';
+ break;
+#endif
+#ifdef S_IFWHT
+ case S_IFWHT: /* whiteout */
+ *p++ = 'w';
+ break;
+#endif
+ default: /* unknown */
+ *p++ = '?';
+ break;
+ }
+ /* usr */
+ if (mode & S_IRUSR)
+ *p++ = 'r';
+ else
+ *p++ = '-';
+ if (mode & S_IWUSR)
+ *p++ = 'w';
+ else
+ *p++ = '-';
+ switch (mode & (S_IXUSR | S_ISUID)) {
+ case 0:
+ *p++ = '-';
+ break;
+ case S_IXUSR:
+ *p++ = 'x';
+ break;
+ case S_ISUID:
+ *p++ = 'S';
+ break;
+ case S_IXUSR | S_ISUID:
+ *p++ = 's';
+ break;
+ }
+ /* group */
+ if (mode & S_IRGRP)
+ *p++ = 'r';
+ else
+ *p++ = '-';
+ if (mode & S_IWGRP)
+ *p++ = 'w';
+ else
+ *p++ = '-';
+ switch (mode & (S_IXGRP | S_ISGID)) {
+ case 0:
+ *p++ = '-';
+ break;
+ case S_IXGRP:
+ *p++ = 'x';
+ break;
+ case S_ISGID:
+ *p++ = 'S';
+ break;
+ case S_IXGRP | S_ISGID:
+ *p++ = 's';
+ break;
+ }
+ /* other */
+ if (mode & S_IROTH)
+ *p++ = 'r';
+ else
+ *p++ = '-';
+ if (mode & S_IWOTH)
+ *p++ = 'w';
+ else
+ *p++ = '-';
+ switch (mode & (S_IXOTH | S_ISVTX)) {
+ case 0:
+ *p++ = '-';
+ break;
+ case S_IXOTH:
+ *p++ = 'x';
+ break;
+ case S_ISVTX:
+ *p++ = 'T';
+ break;
+ case S_IXOTH | S_ISVTX:
+ *p++ = 't';
+ break;
+ }
+ *p++ = ' '; /* will be a '+' if ACL's implemented */
+ *p = '\0';
+}
diff --git a/cpukit/libmisc/shell/fts.c b/cpukit/libmisc/shell/fts.c
new file mode 100644
index 0000000000..2fd91b874c
--- /dev/null
+++ b/cpukit/libmisc/shell/fts.c
@@ -0,0 +1,1244 @@
+/* $NetBSD: fts.c,v 1.40 2009/11/02 17:17:34 stacktic Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
+#else
+__RCSID("$NetBSD: fts.c,v 1.40 2009/11/02 17:17:34 stacktic Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#ifndef __rtems__
+#include "namespace.h"
+#endif
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#define _DIAGASSERT(a)
+#undef FTS_WHITEOUT
+#define dirfd(dp) __dirfd(dp)
+
+#if ! HAVE_NBTOOL_CONFIG_H
+#define HAVE_STRUCT_DIRENT_D_NAMLEN
+#endif
+
+static FTSENT *fts_alloc(FTS *, const char *, size_t);
+static FTSENT *fts_build(FTS *, int);
+static void fts_free(FTSENT *);
+static void fts_lfree(FTSENT *);
+static void fts_load(FTS *, FTSENT *);
+static size_t fts_maxarglen(char * const *);
+static size_t fts_pow2(size_t);
+static int fts_palloc(FTS *, size_t);
+static void fts_padjust(FTS *, FTSENT *);
+static FTSENT *fts_sort(FTS *, FTSENT *, size_t);
+static unsigned short fts_stat(FTS *, FTSENT *, int);
+static int fts_safe_changedir(const FTS *, const FTSENT *, int,
+ const char *);
+
+#if defined(ALIGNBYTES) && defined(ALIGN)
+#define FTS_ALLOC_ALIGNED 1
+/* FIXME: Redefine because some versions of
+ * RTEMS newlib and the BSDs ship a broken ALIGN */
+#undef ALIGN
+#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
+#else
+#undef FTS_ALLOC_ALIGNED
+#endif
+
+#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+
+#define CLR(opt) (sp->fts_options &= ~(opt))
+#define ISSET(opt) (sp->fts_options & (opt))
+#define SET(opt) (sp->fts_options |= (opt))
+
+#define CHDIR(sp, path) (!ISSET(FTS_NOCHDIR) && chdir(path))
+#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd))
+
+/* fts_build flags */
+#define BCHILD 1 /* fts_children */
+#define BNAMES 2 /* fts_children, names only */
+#define BREAD 3 /* fts_read */
+
+#ifndef DTF_HIDEW
+#undef FTS_WHITEOUT
+#endif
+
+FTS *
+fts_open(char * const *argv, int options,
+ int (*compar)(const FTSENT **, const FTSENT **))
+{
+ FTS *sp;
+ FTSENT *p, *root;
+ size_t nitems;
+ FTSENT *parent, *tmp = NULL; /* pacify gcc */
+ size_t len;
+
+ _DIAGASSERT(argv != NULL);
+
+ /* Options check. */
+ if (options & ~FTS_OPTIONMASK) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Allocate/initialize the stream */
+ if ((sp = malloc((unsigned int)sizeof(FTS))) == NULL)
+ return (NULL);
+ memset(sp, 0, sizeof(FTS));
+ sp->fts_compar = compar;
+ sp->fts_options = options;
+
+ /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
+ if (ISSET(FTS_LOGICAL))
+ SET(FTS_NOCHDIR);
+
+ /*
+ * Start out with 1K of path space, and enough, in any case,
+ * to hold the user's paths.
+ */
+ if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
+ goto mem1;
+
+ /* Allocate/initialize root's parent. */
+ if ((parent = fts_alloc(sp, "", 0)) == NULL)
+ goto mem2;
+ parent->fts_level = FTS_ROOTPARENTLEVEL;
+
+ /* Allocate/initialize root(s). */
+ for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
+ /* Don't allow zero-length paths. */
+ if ((len = strlen(*argv)) == 0) {
+ errno = ENOENT;
+ goto mem3;
+ }
+
+ if ((p = fts_alloc(sp, *argv, len)) == NULL)
+ goto mem3;
+ p->fts_level = FTS_ROOTLEVEL;
+ p->fts_parent = parent;
+ p->fts_accpath = p->fts_name;
+ p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
+
+ /* Command-line "." and ".." are real directories. */
+ if (p->fts_info == FTS_DOT)
+ p->fts_info = FTS_D;
+
+ /*
+ * If comparison routine supplied, traverse in sorted
+ * order; otherwise traverse in the order specified.
+ */
+ if (compar) {
+ p->fts_link = root;
+ root = p;
+ } else {
+ p->fts_link = NULL;
+ if (root == NULL)
+ tmp = root = p;
+ else {
+ tmp->fts_link = p;
+ tmp = p;
+ }
+ }
+ }
+ if (compar && nitems > 1)
+ root = fts_sort(sp, root, nitems);
+
+ /*
+ * Allocate a dummy pointer and make fts_read think that we've just
+ * finished the node before the root(s); set p->fts_info to FTS_INIT
+ * so that everything about the "current" node is ignored.
+ */
+ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
+ goto mem3;
+ sp->fts_cur->fts_link = root;
+ sp->fts_cur->fts_info = FTS_INIT;
+
+ /*
+ * If using chdir(2), grab a file descriptor pointing to dot to insure
+ * that we can get back here; this could be avoided for some paths,
+ * but almost certainly not worth the effort. Slashes, symbolic links,
+ * and ".." are all fairly nasty problems. Note, if we can't get the
+ * descriptor we run anyway, just more slowly.
+ */
+ if (!ISSET(FTS_NOCHDIR)) {
+ if ((sp->fts_rfd = open(".", O_RDONLY, 0)) == -1)
+ SET(FTS_NOCHDIR);
+ else if (fcntl(sp->fts_rfd, F_SETFD, FD_CLOEXEC) == -1) {
+ close(sp->fts_rfd);
+ SET(FTS_NOCHDIR);
+ }
+ }
+
+ if (nitems == 0)
+ fts_free(parent);
+
+ return (sp);
+
+mem3: fts_lfree(root);
+ fts_free(parent);
+mem2: free(sp->fts_path);
+mem1: free(sp);
+ return (NULL);
+}
+
+static void
+fts_load(FTS *sp, FTSENT *p)
+{
+ size_t len;
+ char *cp;
+
+ _DIAGASSERT(sp != NULL);
+ _DIAGASSERT(p != NULL);
+
+ /*
+ * Load the stream structure for the next traversal. Since we don't
+ * actually enter the directory until after the preorder visit, set
+ * the fts_accpath field specially so the chdir gets done to the right
+ * place and the user can access the first node. From fts_open it's
+ * known that the path will fit.
+ */
+ len = p->fts_pathlen = p->fts_namelen;
+ memmove(sp->fts_path, p->fts_name, len + 1);
+ if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
+ len = strlen(++cp);
+ memmove(p->fts_name, cp, len + 1);
+ p->fts_namelen = len;
+ }
+ p->fts_accpath = p->fts_path = sp->fts_path;
+ sp->fts_dev = p->fts_dev;
+}
+
+int
+fts_close(FTS *sp)
+{
+ FTSENT *freep, *p;
+ int saved_errno = 0;
+
+ _DIAGASSERT(sp != NULL);
+
+ /*
+ * This still works if we haven't read anything -- the dummy structure
+ * points to the root list, so we step through to the end of the root
+ * list which has a valid parent pointer.
+ */
+ if (sp->fts_cur) {
+ if (sp->fts_cur->fts_flags & FTS_SYMFOLLOW)
+ (void)close(sp->fts_cur->fts_symfd);
+ for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
+ freep = p;
+ p = p->fts_link ? p->fts_link : p->fts_parent;
+ fts_free(freep);
+ }
+ fts_free(p);
+ }
+
+ /* Free up child linked list, sort array, path buffer. */
+ if (sp->fts_child)
+ fts_lfree(sp->fts_child);
+ if (sp->fts_array)
+ free(sp->fts_array);
+ free(sp->fts_path);
+
+ /* Return to original directory, save errno if necessary. */
+ if (!ISSET(FTS_NOCHDIR)) {
+ if (fchdir(sp->fts_rfd) == -1)
+ saved_errno = errno;
+ (void)close(sp->fts_rfd);
+ }
+
+ /* Free up the stream pointer. */
+ free(sp);
+ if (saved_errno) {
+ errno = saved_errno;
+ return -1;
+ }
+
+ return 0;
+}
+
+#if !defined(__FTS_COMPAT_TAILINGSLASH)
+
+/*
+ * Special case of "/" at the end of the path so that slashes aren't
+ * appended which would cause paths to be written as "....//foo".
+ */
+#define NAPPEND(p) \
+ (p->fts_path[p->fts_pathlen - 1] == '/' \
+ ? p->fts_pathlen - 1 : p->fts_pathlen)
+
+#else /* !defined(__FTS_COMPAT_TAILINGSLASH) */
+
+/*
+ * compatibility with the old behaviour.
+ *
+ * Special case a root of "/" so that slashes aren't appended which would
+ * cause paths to be written as "//foo".
+ */
+
+#define NAPPEND(p) \
+ (p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \
+ p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
+
+#endif /* !defined(__FTS_COMPAT_TAILINGSLASH) */
+
+FTSENT *
+fts_read(FTS *sp)
+{
+ FTSENT *p, *tmp;
+ int instr;
+ char *t;
+ int saved_errno;
+
+ _DIAGASSERT(sp != NULL);
+
+ /* If finished or unrecoverable error, return NULL. */
+ if (sp->fts_cur == NULL || ISSET(FTS_STOP))
+ return (NULL);
+
+ /* Set current node pointer. */
+ p = sp->fts_cur;
+
+ /* Save and zero out user instructions. */
+ instr = p->fts_instr;
+ p->fts_instr = FTS_NOINSTR;
+
+ /* Any type of file may be re-visited; re-stat and re-turn. */
+ if (instr == FTS_AGAIN) {
+ p->fts_info = fts_stat(sp, p, 0);
+ return (p);
+ }
+
+ /*
+ * Following a symlink -- SLNONE test allows application to see
+ * SLNONE and recover. If indirecting through a symlink, have
+ * keep a pointer to current location. If unable to get that
+ * pointer, follow fails.
+ */
+ if (instr == FTS_FOLLOW &&
+ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
+ p->fts_info = fts_stat(sp, p, 1);
+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+ if ((p->fts_symfd = open(".", O_RDONLY, 0)) == -1) {
+ p->fts_errno = errno;
+ p->fts_info = FTS_ERR;
+ } else if (fcntl(p->fts_symfd, F_SETFD, FD_CLOEXEC) == -1) {
+ p->fts_errno = errno;
+ p->fts_info = FTS_ERR;
+ close(p->fts_symfd);
+ } else
+ p->fts_flags |= FTS_SYMFOLLOW;
+ }
+ return (p);
+ }
+
+ /* Directory in pre-order. */
+ if (p->fts_info == FTS_D) {
+ /* If skipped or crossed mount point, do post-order visit. */
+ if (instr == FTS_SKIP ||
+ (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
+ if (p->fts_flags & FTS_SYMFOLLOW)
+ (void)close(p->fts_symfd);
+ if (sp->fts_child) {
+ fts_lfree(sp->fts_child);
+ sp->fts_child = NULL;
+ }
+ p->fts_info = FTS_DP;
+ return (p);
+ }
+
+ /* Rebuild if only read the names and now traversing. */
+ if (sp->fts_child && ISSET(FTS_NAMEONLY)) {
+ CLR(FTS_NAMEONLY);
+ fts_lfree(sp->fts_child);
+ sp->fts_child = NULL;
+ }
+
+ /*
+ * Cd to the subdirectory.
+ *
+ * If have already read and now fail to chdir, whack the list
+ * to make the names come out right, and set the parent errno
+ * so the application will eventually get an error condition.
+ * Set the FTS_DONTCHDIR flag so that when we logically change
+ * directories back to the parent we don't do a chdir.
+ *
+ * If haven't read do so. If the read fails, fts_build sets
+ * FTS_STOP or the fts_info field of the node.
+ */
+ if (sp->fts_child) {
+ if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
+ p->fts_errno = errno;
+ p->fts_flags |= FTS_DONTCHDIR;
+ for (p = sp->fts_child; p; p = p->fts_link)
+ p->fts_accpath =
+ p->fts_parent->fts_accpath;
+ }
+ } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
+ if (ISSET(FTS_STOP))
+ return (NULL);
+ return (p);
+ }
+ p = sp->fts_child;
+ sp->fts_child = NULL;
+ goto name;
+ }
+
+ /* Move to the next node on this level. */
+next: tmp = p;
+ if ((p = p->fts_link) != NULL) {
+ fts_free(tmp);
+
+ /*
+ * If reached the top, return to the original directory, and
+ * load the paths for the next root.
+ */
+ if (p->fts_level == FTS_ROOTLEVEL) {
+ if (FCHDIR(sp, sp->fts_rfd)) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ fts_load(sp, p);
+ return (sp->fts_cur = p);
+ }
+
+ /*
+ * User may have called fts_set on the node. If skipped,
+ * ignore. If followed, get a file descriptor so we can
+ * get back if necessary.
+ */
+ if (p->fts_instr == FTS_SKIP)
+ goto next;
+ if (p->fts_instr == FTS_FOLLOW) {
+ p->fts_info = fts_stat(sp, p, 1);
+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+ if ((p->fts_symfd =
+ open(".", O_RDONLY, 0)) == -1) {
+ p->fts_errno = errno;
+ p->fts_info = FTS_ERR;
+ } else if (fcntl(p->fts_symfd, F_SETFD, FD_CLOEXEC) == -1) {
+ p->fts_errno = errno;
+ p->fts_info = FTS_ERR;
+ close(p->fts_symfd);
+ } else
+ p->fts_flags |= FTS_SYMFOLLOW;
+ }
+ p->fts_instr = FTS_NOINSTR;
+ }
+
+name: t = sp->fts_path + NAPPEND(p->fts_parent);
+ *t++ = '/';
+ memmove(t, p->fts_name, (size_t)(p->fts_namelen + 1));
+ return (sp->fts_cur = p);
+ }
+
+ /* Move up to the parent node. */
+ p = tmp->fts_parent;
+ fts_free(tmp);
+
+ if (p->fts_level == FTS_ROOTPARENTLEVEL) {
+ /*
+ * Done; free everything up and set errno to 0 so the user
+ * can distinguish between error and EOF.
+ */
+ fts_free(p);
+ errno = 0;
+ return (sp->fts_cur = NULL);
+ }
+
+ /* Nul terminate the pathname. */
+ sp->fts_path[p->fts_pathlen] = '\0';
+
+ /*
+ * Return to the parent directory. If at a root node or came through
+ * a symlink, go back through the file descriptor. Otherwise, cd up
+ * one directory.
+ */
+ if (p->fts_level == FTS_ROOTLEVEL) {
+ if (FCHDIR(sp, sp->fts_rfd)) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ } else if (p->fts_flags & FTS_SYMFOLLOW) {
+ if (FCHDIR(sp, p->fts_symfd)) {
+ saved_errno = errno;
+ (void)close(p->fts_symfd);
+ errno = saved_errno;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ (void)close(p->fts_symfd);
+ } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+ fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+ return (sp->fts_cur = p);
+}
+
+/*
+ * Fts_set takes the stream as an argument although it's not used in this
+ * implementation; it would be necessary if anyone wanted to add global
+ * semantics to fts using fts_set. An error return is allowed for similar
+ * reasons.
+ */
+/* ARGSUSED */
+int
+fts_set(FTS *sp, FTSENT *p, int instr)
+{
+
+ _DIAGASSERT(sp != NULL);
+ _DIAGASSERT(p != NULL);
+
+ if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
+ instr != FTS_NOINSTR && instr != FTS_SKIP) {
+ errno = EINVAL;
+ return (1);
+ }
+ p->fts_instr = instr;
+ return (0);
+}
+
+FTSENT *
+fts_children(FTS *sp, int instr)
+{
+ FTSENT *p;
+ int fd;
+
+ _DIAGASSERT(sp != NULL);
+
+ if (instr && instr != FTS_NAMEONLY) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Set current node pointer. */
+ p = sp->fts_cur;
+
+ /*
+ * Errno set to 0 so user can distinguish empty directory from
+ * an error.
+ */
+ errno = 0;
+
+ /* Fatal errors stop here. */
+ if (ISSET(FTS_STOP))
+ return (NULL);
+
+ /* Return logical hierarchy of user's arguments. */
+ if (p->fts_info == FTS_INIT)
+ return (p->fts_link);
+
+ /*
+ * If not a directory being visited in pre-order, stop here. Could
+ * allow FTS_DNR, assuming the user has fixed the problem, but the
+ * same effect is available with FTS_AGAIN.
+ */
+ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
+ return (NULL);
+
+ /* Free up any previous child list. */
+ if (sp->fts_child)
+ fts_lfree(sp->fts_child);
+
+ if (instr == FTS_NAMEONLY) {
+ SET(FTS_NAMEONLY);
+ instr = BNAMES;
+ } else
+ instr = BCHILD;
+
+ /*
+ * If using chdir on a relative path and called BEFORE fts_read does
+ * its chdir to the root of a traversal, we can lose -- we need to
+ * chdir into the subdirectory, and we don't know where the current
+ * directory is, so we can't get back so that the upcoming chdir by
+ * fts_read will work.
+ */
+ if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
+ ISSET(FTS_NOCHDIR))
+ return (sp->fts_child = fts_build(sp, instr));
+
+ if ((fd = open(".", O_RDONLY, 0)) == -1)
+ return (sp->fts_child = NULL);
+ sp->fts_child = fts_build(sp, instr);
+ if (fchdir(fd)) {
+ (void)close(fd);
+ return (NULL);
+ }
+ (void)close(fd);
+ return (sp->fts_child);
+}
+
+/*
+ * This is the tricky part -- do not casually change *anything* in here. The
+ * idea is to build the linked list of entries that are used by fts_children
+ * and fts_read. There are lots of special cases.
+ *
+ * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
+ * set and it's a physical walk (so that symbolic links can't be directories),
+ * we can do things quickly. First, if it's a 4.4BSD file system, the type
+ * of the file is in the directory entry. Otherwise, we assume that the number
+ * of subdirectories in a node is equal to the number of links to the parent.
+ * The former skips all stat calls. The latter skips stat calls in any leaf
+ * directories and for any files after the subdirectories in the directory have
+ * been found, cutting the stat calls by about 2/3.
+ */
+static FTSENT *
+fts_build(FTS *sp, int type)
+{
+ struct dirent *dp;
+ FTSENT *p, *head;
+ size_t nitems;
+ FTSENT *cur, *tail;
+ DIR *dirp;
+ void *oldaddr;
+ size_t dnamlen;
+ int cderrno, descend, level, nlinks, saved_errno, nostat, doadjust;
+ size_t len, maxlen;
+#ifdef FTS_WHITEOUT
+ int oflag;
+#endif
+ char *cp = NULL; /* pacify gcc */
+
+ _DIAGASSERT(sp != NULL);
+
+ /* Set current node pointer. */
+ cur = sp->fts_cur;
+
+ /*
+ * Open the directory for reading. If this fails, we're done.
+ * If being called from fts_read, set the fts_info field.
+ */
+#ifdef FTS_WHITEOUT
+ if (ISSET(FTS_WHITEOUT))
+ oflag = DTF_NODUP|DTF_REWIND;
+ else
+ oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
+#else
+#define __opendir2(path, flag) opendir(path)
+#endif
+ if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
+ if (type == BREAD) {
+ cur->fts_info = FTS_DNR;
+ cur->fts_errno = errno;
+ }
+ return (NULL);
+ }
+
+ /*
+ * Nlinks is the number of possible entries of type directory in the
+ * directory if we're cheating on stat calls, 0 if we're not doing
+ * any stat calls at all, -1 if we're doing stats on everything.
+ */
+ if (type == BNAMES) {
+ nlinks = 0;
+ nostat = 1;
+ } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
+ nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+ nostat = 1;
+ } else {
+ nlinks = -1;
+ nostat = 0;
+ }
+
+#ifdef notdef
+ (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
+ (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
+ ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
+#endif
+ /*
+ * If we're going to need to stat anything or we want to descend
+ * and stay in the directory, chdir. If this fails we keep going,
+ * but set a flag so we don't chdir after the post-order visit.
+ * We won't be able to stat anything, but we can still return the
+ * names themselves. Note, that since fts_read won't be able to
+ * chdir into the directory, it will have to return different path
+ * names than before, i.e. "a/b" instead of "b". Since the node
+ * has already been visited in pre-order, have to wait until the
+ * post-order visit to return the error. There is a special case
+ * here, if there was nothing to stat then it's not an error to
+ * not be able to stat. This is all fairly nasty. If a program
+ * needed sorted entries or stat information, they had better be
+ * checking FTS_NS on the returned nodes.
+ */
+ cderrno = 0;
+ if (nlinks || type == BREAD) {
+ if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
+ if (nlinks && type == BREAD)
+ cur->fts_errno = errno;
+ cur->fts_flags |= FTS_DONTCHDIR;
+ descend = 0;
+ cderrno = errno;
+ } else
+ descend = 1;
+ } else
+ descend = 0;
+
+ /*
+ * Figure out the max file name length that can be stored in the
+ * current path -- the inner loop allocates more path as necessary.
+ * We really wouldn't have to do the maxlen calculations here, we
+ * could do them in fts_read before returning the path, but it's a
+ * lot easier here since the length is part of the dirent structure.
+ *
+ * If not changing directories set a pointer so that can just append
+ * each new name into the path.
+ */
+ len = NAPPEND(cur);
+ if (ISSET(FTS_NOCHDIR)) {
+ cp = sp->fts_path + len;
+ *cp++ = '/';
+ }
+ len++;
+ maxlen = sp->fts_pathlen - len;
+
+#if defined(__FTS_COMPAT_LEVEL)
+ if (cur->fts_level == SHRT_MAX) {
+ (void)closedir(dirp);
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+#endif
+
+ level = cur->fts_level + 1;
+
+ /* Read the directory, attaching each entry to the `link' pointer. */
+ doadjust = 0;
+ for (head = tail = NULL, nitems = 0; (dp = readdir(dirp)) != NULL;) {
+
+ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+ continue;
+
+#if defined(HAVE_STRUCT_DIRENT_D_NAMLEN)
+ dnamlen = dp->d_namlen;
+#else
+ dnamlen = strlen(dp->d_name);
+#endif
+ if ((p = fts_alloc(sp, dp->d_name, dnamlen)) == NULL)
+ goto mem1;
+ if (dnamlen >= maxlen) { /* include space for NUL */
+ oldaddr = sp->fts_path;
+ if (fts_palloc(sp, dnamlen + len + 1)) {
+ /*
+ * No more memory for path or structures. Save
+ * errno, free up the current structure and the
+ * structures already allocated.
+ */
+mem1: saved_errno = errno;
+ if (p)
+ fts_free(p);
+ fts_lfree(head);
+ (void)closedir(dirp);
+ errno = saved_errno;
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ /* Did realloc() change the pointer? */
+ if (oldaddr != sp->fts_path) {
+ doadjust = 1;
+ if (ISSET(FTS_NOCHDIR))
+ cp = sp->fts_path + len;
+ }
+ maxlen = sp->fts_pathlen - len;
+ }
+
+#if defined(__FTS_COMPAT_LENGTH)
+ if (len + dnamlen >= USHRT_MAX) {
+ /*
+ * In an FTSENT, fts_pathlen is an unsigned short
+ * so it is possible to wraparound here.
+ * If we do, free up the current structure and the
+ * structures already allocated, then error out
+ * with ENAMETOOLONG.
+ */
+ fts_free(p);
+ fts_lfree(head);
+ (void)closedir(dirp);
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+#endif
+ p->fts_level = level;
+ p->fts_pathlen = len + dnamlen;
+ p->fts_parent = sp->fts_cur;
+
+#ifdef FTS_WHITEOUT
+ if (dp->d_type == DT_WHT)
+ p->fts_flags |= FTS_ISW;
+#endif
+
+ if (cderrno) {
+ if (nlinks) {
+ p->fts_info = FTS_NS;
+ p->fts_errno = cderrno;
+ } /* else
+ p->fts_info = FTS_NSOK;
+ */
+ /* Coverity Scan Id 1 says above is dead code */
+ p->fts_accpath = cur->fts_accpath;
+ } else if (nlinks == 0
+#ifdef DT_DIR
+ || (nostat &&
+ dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
+#endif
+ ) {
+ p->fts_accpath =
+ ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
+ p->fts_info = FTS_NSOK;
+ } else {
+ /* Build a file name for fts_stat to stat. */
+ if (ISSET(FTS_NOCHDIR)) {
+ p->fts_accpath = p->fts_path;
+ memmove(cp, p->fts_name,
+ (size_t)(p->fts_namelen + 1));
+ } else
+ p->fts_accpath = p->fts_name;
+ /* Stat it. */
+ p->fts_info = fts_stat(sp, p, 0);
+
+ /* Decrement link count if applicable. */
+ if (nlinks > 0 && (p->fts_info == FTS_D ||
+ p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
+ --nlinks;
+ }
+
+ /* We walk in directory order so "ls -f" doesn't get upset. */
+ p->fts_link = NULL;
+ if (head == NULL)
+ head = tail = p;
+ else {
+ tail->fts_link = p;
+ tail = p;
+ }
+ ++nitems;
+ }
+ (void)closedir(dirp);
+
+ /*
+ * If had to realloc the path, adjust the addresses for the rest
+ * of the tree.
+ */
+ if (doadjust)
+ fts_padjust(sp, head);
+
+ /*
+ * If not changing directories, reset the path back to original
+ * state.
+ */
+ if (ISSET(FTS_NOCHDIR)) {
+ if (len == sp->fts_pathlen || nitems == 0)
+ --cp;
+ *cp = '\0';
+ }
+
+ /*
+ * If descended after called from fts_children or after called from
+ * fts_read and nothing found, get back. At the root level we use
+ * the saved fd; if one of fts_open()'s arguments is a relative path
+ * to an empty directory, we wind up here with no other way back. If
+ * can't get back, we're done.
+ */
+ if (descend && (type == BCHILD || !nitems) &&
+ (cur->fts_level == FTS_ROOTLEVEL ?
+ FCHDIR(sp, sp->fts_rfd) :
+ fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+
+ /* If didn't find anything, return NULL. */
+ if (!nitems) {
+ if (type == BREAD)
+ cur->fts_info = FTS_DP;
+ return (NULL);
+ }
+
+ /* Sort the entries. */
+ if (sp->fts_compar && nitems > 1)
+ head = fts_sort(sp, head, nitems);
+ return (head);
+}
+
+static unsigned short
+fts_stat(FTS *sp, FTSENT *p, int follow)
+{
+ FTSENT *t;
+ dev_t dev;
+ __fts_ino_t ino;
+ __fts_stat_t *sbp, sb;
+ int saved_errno;
+
+ _DIAGASSERT(sp != NULL);
+ _DIAGASSERT(p != NULL);
+
+ /* If user needs stat info, stat buffer already allocated. */
+ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
+
+#ifdef FTS_WHITEOUT
+ /* check for whiteout */
+ if (p->fts_flags & FTS_ISW) {
+ if (sbp != &sb) {
+ memset(sbp, '\0', sizeof (*sbp));
+ sbp->st_mode = S_IFWHT;
+ }
+ return (FTS_W);
+ }
+#endif
+
+ /*
+ * If doing a logical walk, or application requested FTS_FOLLOW, do
+ * a stat(2). If that fails, check for a non-existent symlink. If
+ * fail, set the errno from the stat call.
+ */
+ if (ISSET(FTS_LOGICAL) || follow) {
+ if (stat(p->fts_accpath, sbp)) {
+ saved_errno = errno;
+ if (!lstat(p->fts_accpath, sbp)) {
+ errno = 0;
+ return (FTS_SLNONE);
+ }
+ p->fts_errno = saved_errno;
+ goto err;
+ }
+ } else if (lstat(p->fts_accpath, sbp)) {
+ p->fts_errno = errno;
+err: memset(sbp, 0, sizeof(*sbp));
+ return (FTS_NS);
+ }
+
+ if (S_ISDIR(sbp->st_mode)) {
+ /*
+ * Set the device/inode. Used to find cycles and check for
+ * crossing mount points. Also remember the link count, used
+ * in fts_build to limit the number of stat calls. It is
+ * understood that these fields are only referenced if fts_info
+ * is set to FTS_D.
+ */
+ dev = p->fts_dev = sbp->st_dev;
+ ino = p->fts_ino = sbp->st_ino;
+ p->fts_nlink = sbp->st_nlink;
+
+ if (ISDOT(p->fts_name))
+ return (FTS_DOT);
+
+ /*
+ * Cycle detection is done by brute force when the directory
+ * is first encountered. If the tree gets deep enough or the
+ * number of symbolic links to directories is high enough,
+ * something faster might be worthwhile.
+ */
+ for (t = p->fts_parent;
+ t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
+ if (ino == t->fts_ino && dev == t->fts_dev) {
+ p->fts_cycle = t;
+ return (FTS_DC);
+ }
+ return (FTS_D);
+ }
+ if (S_ISLNK(sbp->st_mode))
+ return (FTS_SL);
+ if (S_ISREG(sbp->st_mode))
+ return (FTS_F);
+ return (FTS_DEFAULT);
+}
+
+static FTSENT *
+fts_sort(FTS *sp, FTSENT *head, size_t nitems)
+{
+ FTSENT **ap, *p;
+
+ _DIAGASSERT(sp != NULL);
+ _DIAGASSERT(head != NULL);
+
+ /*
+ * Construct an array of pointers to the structures and call qsort(3).
+ * Reassemble the array in the order returned by qsort. If unable to
+ * sort for memory reasons, return the directory entries in their
+ * current order. Allocate enough space for the current needs plus
+ * 40 so don't realloc one entry at a time.
+ */
+ if (nitems > sp->fts_nitems) {
+ FTSENT **new;
+
+ new = realloc(sp->fts_array, sizeof(FTSENT *) * (nitems + 40));
+ if (new == 0)
+ return (head);
+ sp->fts_array = new;
+ sp->fts_nitems = nitems + 40;
+ }
+ for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+ *ap++ = p;
+ qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *),
+ (int (*)(const void *, const void *))sp->fts_compar);
+ for (head = *(ap = sp->fts_array); --nitems; ++ap)
+ ap[0]->fts_link = ap[1];
+ ap[0]->fts_link = NULL;
+ return (head);
+}
+
+static FTSENT *
+fts_alloc(FTS *sp, const char *name, size_t namelen)
+{
+ FTSENT *p;
+#if defined(FTS_ALLOC_ALIGNED)
+ size_t len;
+#endif
+
+ _DIAGASSERT(sp != NULL);
+ _DIAGASSERT(name != NULL);
+
+#if defined(FTS_ALLOC_ALIGNED)
+ /*
+ * The file name is a variable length array and no stat structure is
+ * necessary if the user has set the nostat bit. Allocate the FTSENT
+ * structure, the file name and the stat structure in one chunk, but
+ * be careful that the stat structure is reasonably aligned. Since the
+ * fts_name field is declared to be of size 1, the fts_name pointer is
+ * namelen + 2 before the first possible address of the stat structure.
+ */
+ len = sizeof(FTSENT) + namelen;
+ if (!ISSET(FTS_NOSTAT))
+ len += sizeof(*(p->fts_statp)) + ALIGNBYTES;
+ if ((p = malloc(len)) == NULL)
+ return (NULL);
+
+ if (!ISSET(FTS_NOSTAT))
+ p->fts_statp = (__fts_stat_t *)ALIGN(p->fts_name + namelen + 2);
+#else
+ if ((p = malloc(sizeof(FTSENT) + namelen)) == NULL)
+ return (NULL);
+
+ if (!ISSET(FTS_NOSTAT))
+ if ((p->fts_statp = malloc(sizeof(*(p->fts_statp)))) == NULL) {
+ free(p);
+ return (NULL);
+ }
+#endif
+
+ if (ISSET(FTS_NOSTAT))
+ p->fts_statp = NULL;
+
+ /* Copy the name plus the trailing NULL. */
+ memmove(p->fts_name, name, namelen + 1);
+
+ p->fts_namelen = namelen;
+ p->fts_path = sp->fts_path;
+ p->fts_errno = 0;
+ p->fts_flags = 0;
+ p->fts_instr = FTS_NOINSTR;
+ p->fts_number = 0;
+ p->fts_pointer = NULL;
+ return (p);
+}
+
+static void
+fts_free(FTSENT *p)
+{
+#if !defined(FTS_ALLOC_ALIGNED)
+ if (p->fts_statp)
+ free(p->fts_statp);
+#endif
+ free(p);
+}
+
+static void
+fts_lfree(FTSENT *head)
+{
+ FTSENT *p;
+
+ /* XXX: head may be NULL ? */
+
+ /* Free a linked list of structures. */
+ while ((p = head) != NULL) {
+ head = head->fts_link;
+ fts_free(p);
+ }
+}
+
+static size_t
+fts_pow2(size_t x)
+{
+
+ x--;
+ x |= x>>1;
+ x |= x>>2;
+ x |= x>>4;
+ x |= x>>8;
+#if (SIZEOF_SIZE_T * CHAR_BIT) > 16
+ x |= x>>16;
+#endif
+#if (SIZEOF_SIZE_T * CHAR_BIT) > 32
+ x |= x>>32;
+#endif
+#if (SIZEOF_SIZE_T * CHAR_BIT) > 64
+ x |= x>>64;
+#endif
+ x++;
+ return (x);
+}
+
+/*
+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
+ * though the kernel won't resolve them. Round up the new size to a power of 2,
+ * so we don't realloc the path 2 bytes at a time.
+ */
+static int
+fts_palloc(FTS *sp, size_t size)
+{
+ char *new;
+
+ _DIAGASSERT(sp != NULL);
+
+#ifdef __FTS_COMPAT_LENGTH
+ /* Protect against fts_pathlen overflow. */
+ if (size > USHRT_MAX + 1) {
+ errno = ENAMETOOLONG;
+ return (1);
+ }
+#endif
+ size = fts_pow2(size);
+ new = realloc(sp->fts_path, size);
+ if (new == 0)
+ return (1);
+ sp->fts_path = new;
+ sp->fts_pathlen = size;
+ return (0);
+}
+
+/*
+ * When the path is realloc'd, have to fix all of the pointers in structures
+ * already returned.
+ */
+static void
+fts_padjust(FTS *sp, FTSENT *head)
+{
+ FTSENT *p;
+ char *addr;
+
+ _DIAGASSERT(sp != NULL);
+
+#define ADJUST(p) do { \
+ if ((p)->fts_accpath != (p)->fts_name) \
+ (p)->fts_accpath = \
+ addr + ((p)->fts_accpath - (p)->fts_path); \
+ (p)->fts_path = addr; \
+} while (/*CONSTCOND*/0)
+
+ addr = sp->fts_path;
+
+ /* Adjust the current set of children. */
+ for (p = sp->fts_child; p; p = p->fts_link)
+ ADJUST(p);
+
+ /* Adjust the rest of the tree, including the current level. */
+ for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
+ ADJUST(p);
+ p = p->fts_link ? p->fts_link : p->fts_parent;
+ }
+}
+
+static size_t
+fts_maxarglen(char * const *argv)
+{
+ size_t len, max;
+
+ _DIAGASSERT(argv != NULL);
+
+ for (max = 0; *argv; ++argv)
+ if ((len = strlen(*argv)) > max)
+ max = len;
+ return (max + 1);
+}
+
+/*
+ * Change to dir specified by fd or p->fts_accpath without getting
+ * tricked by someone changing the world out from underneath us.
+ * Assumes p->fts_dev and p->fts_ino are filled in.
+ */
+static int
+fts_safe_changedir(const FTS *sp, const FTSENT *p, int fd, const char *path)
+{
+ int oldfd = fd, ret = -1;
+ __fts_stat_t sb;
+
+ if (ISSET(FTS_NOCHDIR))
+ return 0;
+
+ if (oldfd < 0 && (fd = open(path, O_RDONLY)) == -1)
+ return -1;
+
+ if (fstat(fd, &sb) == -1)
+ goto bail;
+
+ if (sb.st_ino != p->fts_ino || sb.st_dev != p->fts_dev) {
+ errno = ENOENT;
+ goto bail;
+ }
+
+ ret = fchdir(fd);
+
+bail:
+ if (oldfd < 0) {
+ int save_errno = errno;
+ (void)close(fd);
+ errno = save_errno;
+ }
+ return ret;
+}
diff --git a/cpukit/libmisc/shell/fts.h b/cpukit/libmisc/shell/fts.h
new file mode 100644
index 0000000000..68e9d46c3e
--- /dev/null
+++ b/cpukit/libmisc/shell/fts.h
@@ -0,0 +1,146 @@
+/* $NetBSD: fts.h,v 1.14 2005/09/13 01:44:32 christos Exp $ */
+
+/*
+ * 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. 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.
+ *
+ * @(#)fts.h 8.3 (Berkeley) 8/14/94
+ */
+
+#ifndef _FTS_H_
+#define _FTS_H_
+
+#ifndef __fts_stat_t
+#define __fts_stat_t struct stat
+#endif
+#ifndef __fts_nlink_t
+#define __fts_nlink_t nlink_t
+#endif
+#ifndef __fts_ino_t
+#define __fts_ino_t ino_t
+#endif
+
+typedef struct {
+ struct _ftsent *fts_cur; /* current node */
+ struct _ftsent *fts_child; /* linked list of children */
+ struct _ftsent **fts_array; /* sort array */
+ dev_t fts_dev; /* starting device # */
+ char *fts_path; /* path for this descent */
+ int fts_rfd; /* fd for root */
+ u_int fts_pathlen; /* sizeof(path) */
+ u_int fts_nitems; /* elements in the sort array */
+ int (*fts_compar) /* compare function */
+ (const struct _ftsent **, const struct _ftsent **);
+
+#define FTS_COMFOLLOW 0x001 /* follow command line symlinks */
+#define FTS_LOGICAL 0x002 /* logical walk */
+#define FTS_NOCHDIR 0x004 /* don't change directories */
+#define FTS_NOSTAT 0x008 /* don't get stat info */
+#define FTS_PHYSICAL 0x010 /* physical walk */
+#define FTS_SEEDOT 0x020 /* return dot and dot-dot */
+#define FTS_XDEV 0x040 /* don't cross devices */
+#define FTS_WHITEOUT 0x080 /* return whiteout information */
+#define FTS_OPTIONMASK 0x0ff /* valid user option mask */
+
+#define FTS_NAMEONLY 0x100 /* (private) child names only */
+#define FTS_STOP 0x200 /* (private) unrecoverable error */
+ int fts_options; /* fts_open options, global flags */
+} FTS;
+
+typedef struct _ftsent {
+ struct _ftsent *fts_cycle; /* cycle node */
+ struct _ftsent *fts_parent; /* parent directory */
+ struct _ftsent *fts_link; /* next file in directory */
+ long fts_number; /* local numeric value */
+ void *fts_pointer; /* local address value */
+ char *fts_accpath; /* access path */
+ char *fts_path; /* root path */
+ int fts_errno; /* errno for this node */
+ int fts_symfd; /* fd for symlink */
+ u_short fts_pathlen; /* strlen(fts_path) */
+ u_short fts_namelen; /* strlen(fts_name) */
+
+ __fts_ino_t fts_ino; /* inode */
+ dev_t fts_dev; /* device */
+ __fts_nlink_t fts_nlink; /* link count */
+
+#define FTS_ROOTPARENTLEVEL -1
+#define FTS_ROOTLEVEL 0
+ short fts_level; /* depth (-1 to N) */
+
+#define FTS_D 1 /* preorder directory */
+#define FTS_DC 2 /* directory that causes cycles */
+#define FTS_DEFAULT 3 /* none of the above */
+#define FTS_DNR 4 /* unreadable directory */
+#define FTS_DOT 5 /* dot or dot-dot */
+#define FTS_DP 6 /* postorder directory */
+#define FTS_ERR 7 /* error; errno is set */
+#define FTS_F 8 /* regular file */
+#define FTS_INIT 9 /* initialized only */
+#define FTS_NS 10 /* stat(2) failed */
+#define FTS_NSOK 11 /* no stat(2) requested */
+#define FTS_SL 12 /* symbolic link */
+#define FTS_SLNONE 13 /* symbolic link without target */
+#define FTS_W 14 /* whiteout object */
+ u_short fts_info; /* user flags for FTSENT structure */
+
+#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */
+#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */
+#define FTS_ISW 0x04 /* this is a whiteout object */
+ u_short fts_flags; /* private flags for FTSENT structure */
+
+#define FTS_AGAIN 1 /* read node again */
+#define FTS_FOLLOW 2 /* follow symbolic link */
+#define FTS_NOINSTR 3 /* no instructions */
+#define FTS_SKIP 4 /* discard node */
+ u_short fts_instr; /* fts_set() instructions */
+
+ __fts_stat_t *fts_statp; /* stat(2) information */
+ char fts_name[1]; /* file name */
+} FTSENT;
+
+#include <sys/cdefs.h>
+
+#define __RENAME(n)
+#define fts_children rtems_shell_fts_children
+#define fts_close rtems_shell_fts_close
+#define fts_open rtems_shell_fts_open
+#define fts_read rtems_shell_fts_read
+#define fts_set rtems_shell_fts_set
+
+__BEGIN_DECLS
+#ifndef __LIBC12_SOURCE__
+FTSENT *fts_children(FTS *, int) __RENAME(__fts_children30);
+int fts_close(FTS *) __RENAME(__fts_close30);
+FTS *fts_open(char * const *, int,
+ int (*)(const FTSENT **, const FTSENT **)) __RENAME(__fts_open30);
+FTSENT *fts_read(FTS *) __RENAME(__fts_read30);
+int fts_set(FTS *, FTSENT *, int) __RENAME(__fts_set30);
+#endif
+__END_DECLS
+
+#endif /* !_FTS_H_ */
diff --git a/cpukit/libmisc/shell/hexdump-conv.c b/cpukit/libmisc/shell/hexdump-conv.c
new file mode 100644
index 0000000000..44390baa32
--- /dev/null
+++ b/cpukit/libmisc/shell/hexdump-conv.c
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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];
+
+ 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%lc", pad, "", wc);
+ pr->mbleft = clen - 1;
+ }
+ } else {
+ (void)sprintf(buf, "%03o", (int)*p);
+ str = buf;
+strpr: *pr->cchar = 's';
+ (void)printf(pr->fmt, str);
+ }
+}
+
+void
+conv_u(rtems_shell_hexdump_globals* globals, PR *pr, u_char *p)
+{
+ static char const * list[] = {
+ "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
+ "bs", "ht", "lf", "vt", "ff", "cr", "so", "si",
+ "dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb",
+ "can", "em", "sub", "esc", "fs", "gs", "rs", "us",
+ };
+
+ /* od used nl, not lf */
+ if (*p <= 0x1f) {
+ *pr->cchar = 's';
+ if (odmode && *p == 0x0a)
+ (void)printf(pr->fmt, "nl");
+ else
+ (void)printf(pr->fmt, list[*p]);
+ } else if (*p == 0x7f) {
+ *pr->cchar = 's';
+ (void)printf(pr->fmt, "del");
+ } else if (odmode && *p == 0x20) { /* od replaced space with sp */
+ *pr->cchar = 's';
+ (void)printf(pr->fmt, " sp");
+ } else if (isprint(*p)) {
+ *pr->cchar = 'c';
+ (void)printf(pr->fmt, *p);
+ } else {
+ *pr->cchar = 'x';
+ (void)printf(pr->fmt, (int)*p);
+ }
+}
diff --git a/cpukit/libmisc/shell/hexdump-display.c b/cpukit/libmisc/shell/hexdump-display.c
new file mode 100644
index 0000000000..3e33fba143
--- /dev/null
+++ b/cpukit/libmisc/shell/hexdump-display.c
@@ -0,0 +1,431 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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"
+
+#define bcmp(s1,s2,sz) memcmp(s1,s2,sz)
+#define bcopy(s,d,sz) memcpy(d,s,sz)
+#define bzero(s,sz) memset(s,0,sz)
+#define index(s,c) strchr(s,c)
+
+#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");
+ }
+ memset (hdstdin, 0, sizeof(FILE));
+ }
+ if (!(hdstdin = freopen(*_argv, "r", hdstdin))) {
+ 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);
+ /* can seek block devices on RTEMS */
+ if (0 && S_ISREG(sb.st_mode) && skip >= sb.st_size) {
+ address += sb.st_size;
+ skip -= sb.st_size;
+ return;
+ }
+ if (1 || S_ISREG(sb.st_mode)) {
+ if (fseeko(hdstdin, skip, SEEK_SET))
+ err(exit_jump, 1, "%s", fname);
+ address += skip;
+ skip = 0;
+ } else {
+ for (cnt = 0; cnt < skip; ++cnt)
+ if (getchar() == EOF)
+ break;
+ address += cnt;
+ skip -= cnt;
+ }
+ }
+}
diff --git a/cpukit/libmisc/shell/hexdump-odsyntax.c b/cpukit/libmisc/shell/hexdump-odsyntax.c
new file mode 100644
index 0000000000..24e8d59e73
--- /dev/null
+++ b/cpukit/libmisc/shell/hexdump-odsyntax.c
@@ -0,0 +1,451 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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((unsigned char)p[0]) && (p[0] != 'x' || !isxdigit((unsigned char)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((unsigned char)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((unsigned char)*p); ++p);
+ else
+ for (num = p; isdigit((unsigned char)*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;
+ }
+ }
+ if (isize == sizeof(float) ) {
+ digits = FLT_DIG;
+ } else if (isize == sizeof(double)) {
+ digits = DBL_DIG;
+ } else if (isize == sizeof(long double)) {
+ digits = LDBL_DIG;
+ } else {
+ errx(exit_jump, 1, "unsupported floating point size %zu",
+ isize);
+ }
+
+ asprintf(&hdfmt, "%lu/%lu \" %%%d.%de \" \"\\n\"",
+ 16UL / (u_long)isize, (u_long)isize, digits + 8, digits);
+ if (hdfmt == NULL)
+ err(exit_jump, 1, NULL);
+ odadd(globals, hdfmt);
+ free(hdfmt);
+
+ return (fmt);
+}
+
+static const char *
+odformatint(rtems_shell_hexdump_globals* globals, char fchar, const char *fmt)
+{
+ unsigned long long n;
+ size_t isize;
+ int digits;
+ char *end, *hdfmt;
+
+ isize = sizeof(int);
+ switch (*fmt) {
+ case 'C':
+ isize = sizeof(char);
+ fmt++;
+ break;
+ case 'I':
+ isize = sizeof(int);
+ fmt++;
+ break;
+ case 'L':
+ isize = sizeof(long);
+ fmt++;
+ break;
+ case 'S':
+ isize = sizeof(short);
+ fmt++;
+ break;
+ default:
+ if (isdigit((unsigned char)*fmt)) {
+ errno = 0;
+ isize = (size_t)strtoul(fmt, &end, 10);
+ if (errno != 0 || isize == 0)
+ errx(exit_jump, 1, "%s: invalid size", fmt);
+ if (isize != sizeof(char) && isize != sizeof(short) &&
+ isize != sizeof(int) && isize != sizeof(long))
+ errx(exit_jump, 1, "unsupported int size %lu",
+ (u_long)isize);
+ fmt = (const char *)end;
+ }
+ }
+
+ /*
+ * Calculate the maximum number of digits we need to
+ * fit the number. Overestimate for decimal with log
+ * base 8. We need one extra space for signed numbers
+ * to store the sign.
+ */
+ n = (1ULL << (8 * isize)) - 1;
+ digits = 0;
+ while (n != 0) {
+ digits++;
+ n >>= (fchar == 'x') ? 4 : 3;
+ }
+ if (fchar == 'd')
+ digits++;
+ asprintf(&hdfmt, "%lu/%lu \"%*s%%%s%d%c\" \"\\n\"",
+ 16UL / (u_long)isize, (u_long)isize, (int)(4 * isize - digits),
+ "", (fchar == 'd' || fchar == 'u') ? "" : "0", digits, fchar);
+ if (hdfmt == NULL)
+ err(exit_jump, 1, NULL);
+ odadd(globals, hdfmt);
+ free(hdfmt);
+
+ return (fmt);
+}
+
+static void
+odadd(rtems_shell_hexdump_globals* globals, const char *fmt)
+{
+ static int needpad;
+
+ if (needpad)
+ add(globals, "\""PADDING"\"");
+ add(globals, fmt);
+ needpad = 1;
+}
diff --git a/cpukit/libmisc/shell/hexdump-parse.c b/cpukit/libmisc/shell/hexdump-parse.c
new file mode 100644
index 0000000000..1c35ba4649
--- /dev/null
+++ b/cpukit/libmisc/shell/hexdump-parse.c
@@ -0,0 +1,531 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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>
+
+#define index(s,c) strchr(s,c)
+
+#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;
+
+ pr = NULL;
+ 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 {
+ if (nextpr)
+ *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 (pr) {
+ free(pr);
+ pr = NULL;
+ }
+ /*
+ * If the format string interprets any data at all, and it's
+ * not the same as the blocksize, and its last format unit
+ * interprets any data at all, and has no iteration count,
+ * repeat it as necessary.
+ *
+ * If, rep count is greater than 1, no trailing whitespace
+ * gets output from the last iteration of the format unit.
+ */
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+ if (!fu->nextfu && fs->bcnt < blocksize &&
+ !(fu->flags&F_SETREP) && fu->bcnt)
+ fu->reps += (blocksize - fs->bcnt) / fu->bcnt;
+ if (fu->reps > 1) {
+ for (pr = fu->nextpr;; pr = pr->nextpr)
+ if (!pr->nextpr)
+ break;
+ for (p1 = (unsigned char*)pr->fmt, p2 = NULL; *p1; ++p1)
+ p2 = isspace(*p1) ? p1 : NULL;
+ if (p2)
+ pr->nospace = (char*)p2;
+ }
+ }
+#ifdef DEBUG
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+ (void)printf("fmt:");
+ for (pr = fu->nextpr; pr; pr = pr->nextpr)
+ (void)printf(" {%s}", pr->fmt);
+ (void)printf("\n");
+ }
+#endif
+}
+
+void
+escape(char *p1)
+{
+ char *p2;
+
+ /* alphabetic escape sequences have to be done in place */
+ for (p2 = p1;; ++p1, ++p2) {
+ if (!*p1) {
+ *p2 = *p1;
+ break;
+ }
+ if (*p1 == '\\')
+ switch(*++p1) {
+ case 'a':
+ /* *p2 = '\a'; */
+ *p2 = '\007';
+ break;
+ case 'b':
+ *p2 = '\b';
+ break;
+ case 'f':
+ *p2 = '\f';
+ break;
+ case 'n':
+ *p2 = '\n';
+ break;
+ case 'r':
+ *p2 = '\r';
+ break;
+ case 't':
+ *p2 = '\t';
+ break;
+ case 'v':
+ *p2 = '\v';
+ break;
+ default:
+ *p2 = *p1;
+ break;
+ }
+ }
+}
+
+void
+badcnt(rtems_shell_hexdump_globals* globals, char *s)
+{
+ errx(exit_jump, 1, "%s: bad byte count", s);
+}
+
+void
+badsfmt(rtems_shell_hexdump_globals* globals)
+{
+ errx(exit_jump, 1, "%%s: requires a precision or a byte count");
+}
+
+void
+badfmt(rtems_shell_hexdump_globals* globals, const char *fmt)
+{
+ errx(exit_jump, 1, "\"%s\": bad format", fmt);
+}
+
+void
+badconv(rtems_shell_hexdump_globals* globals, char *ch)
+{
+ errx(exit_jump, 1, "%%%s: bad conversion character", ch);
+}
diff --git a/cpukit/libmisc/shell/hexdump.h b/cpukit/libmisc/shell/hexdump.h
new file mode 100644
index 0000000000..5b0e61b966
--- /dev/null
+++ b/cpukit/libmisc/shell/hexdump.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)hexdump.h 8.1 (Berkeley) 6/6/93
+ * $FreeBSD: src/usr.bin/hexdump/hexdump.h,v 1.9 2004/07/11 01:11:12 tjr Exp $
+ */
+
+#include <wchar.h>
+
+typedef struct _pr {
+ struct _pr *nextpr; /* next print unit */
+#define F_ADDRESS 0x001 /* print offset */
+#define F_BPAD 0x002 /* blank pad */
+#define F_C 0x004 /* %_c */
+#define F_CHAR 0x008 /* %c */
+#define F_DBL 0x010 /* %[EefGf] */
+#define F_INT 0x020 /* %[di] */
+#define F_P 0x040 /* %_p */
+#define F_STR 0x080 /* %s */
+#define F_U 0x100 /* %_u */
+#define F_UINT 0x200 /* %[ouXx] */
+#define F_TEXT 0x400 /* no conversions */
+ u_int flags; /* flag values */
+ int bcnt; /* byte count */
+ char *cchar; /* conversion character */
+ char *fmt; /* printf format */
+ char *nospace; /* no whitespace version */
+ int mbleft; /* bytes left of multibyte char. */
+ mbstate_t mbstate; /* conversion state */
+} PR;
+
+typedef struct _fu {
+ struct _fu *nextfu; /* next format unit */
+ struct _pr *nextpr; /* next print unit */
+#define F_IGNORE 0x01 /* %_A */
+#define F_SETREP 0x02 /* rep count set, not default */
+ u_int flags; /* flag values */
+ int reps; /* repetition count */
+ int bcnt; /* byte count */
+ char *fmt; /* format string */
+} FU;
+
+typedef struct _fs { /* format strings */
+ struct _fs *nextfs; /* linked list of format strings */
+ struct _fu *nextfu; /* linked list of format units */
+ int bcnt;
+} FS;
+
+#if 0
+extern FS *fshead; /* head of format strings list */
+extern FU *endfu; /* format at end-of-data */
+extern int blocksize; /* data block size */
+extern int exitval; /* final exit value */
+extern int odmode; /* are we acting as od(1)? */
+extern int length; /* amount of data to read */
+extern off_t skip; /* amount of data to skip at start */
+enum _vflag { ALL, DUP, FIRST, WAIT }; /* -v values */
+extern enum _vflag vflag;
+#endif
+
+#include <setjmp.h>
+#include <stdio.h>
+
+enum _vflag { ALL, DUP, FIRST, WAIT }; /* -v values */
+typedef struct rtems_shell_hexdump_globals_t {
+ FS *fshead; /* head of format strings list */
+ FU *endfu; /* format at end-of-data */
+ int blocksize; /* data block size */
+ int exitval; /* final exit value */
+ int odmode; /* are we acting as od(1)? */
+ int length; /* amount of data to read */
+ off_t skip; /* amount of data to skip at start */
+ enum _vflag vflag;
+
+ off_t address;
+ off_t eaddress;
+ int ateof;
+ u_char *curp;
+ u_char *savp;
+ int done;
+
+ FILE* hdstdin;
+
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_hexdump_globals;
+
+#define fshead globals->fshead
+#define endfu globals->endfu
+#define blocksize globals->blocksize
+#define exitval globals->exitval
+#define odmode globals->odmode
+#define length globals->length
+#define skip globals->skip
+#define vflag globals->vflag
+
+#define address globals->address
+#define eaddress globals->eaddress
+#define ateof globals->ateof
+#define curp globals->curp
+#define savp globals->savp
+#define done globals->done
+
+#define hdstdin globals->hdstdin
+
+#define exit_jump &(globals->exit_jmp)
+
+#define add rtems_shell_hexdump_add
+#define addfile rtems_shell_hexdump_addfile
+#define badcnt rtems_shell_hexdump_badcnt
+#define badconv rtems_shell_hexdump_badconv
+#define badfmt rtems_shell_hexdump_badfmt
+#define badsfmt rtems_shell_hexdump_badsfmt
+#define bpad rtems_shell_hexdump_bpad
+#define conv_c rtems_shell_hexdump_conv_c
+#define conv_u rtems_shell_hexdump_conv_u
+#define display rtems_shell_hexdump_display
+#define doskip rtems_shell_hexdump_doskip
+#define escape rtems_shell_hexdump_escape
+#define get rtems_shell_hexdump_get
+#define newsyntax rtems_shell_hexdump_newsyntax
+#define next rtems_shell_hexdump_next
+#define nomem rtems_shell_hexdump_nomem
+#define oldsyntax rtems_shell_hexdump_oldsyntax
+#define peek rtems_shell_hexdump_peek
+#define rewrite rtems_shell_hexdump_rewrite
+#define size rtems_shell_hexdump_size
+#define usage rtems_shell_hexdump_usage
+
+void add(rtems_shell_hexdump_globals*, const char *);
+void addfile(rtems_shell_hexdump_globals*, char *);
+void badcnt(rtems_shell_hexdump_globals*, char *);
+void badconv(rtems_shell_hexdump_globals*, char *);
+void badfmt(rtems_shell_hexdump_globals*, const char *);
+void badsfmt(rtems_shell_hexdump_globals*);
+void bpad(PR *);
+void conv_c(rtems_shell_hexdump_globals*, PR *, u_char *, size_t);
+void conv_u(rtems_shell_hexdump_globals*, PR *, u_char *);
+void display(rtems_shell_hexdump_globals*);
+void doskip(rtems_shell_hexdump_globals*, const char *, int);
+void escape(char *);
+u_char *get(rtems_shell_hexdump_globals*);
+void newsyntax(rtems_shell_hexdump_globals*, int, char ***);
+int next(rtems_shell_hexdump_globals*, char **);
+void nomem(void);
+void oldsyntax(rtems_shell_hexdump_globals*, int, char ***);
+size_t peek(rtems_shell_hexdump_globals*, u_char *, size_t);
+void rewrite(rtems_shell_hexdump_globals*, FS *);
+int size(rtems_shell_hexdump_globals*, FS *);
+void usage(rtems_shell_hexdump_globals*);
+
+#define exit(ec) rtems_shell_hexdump_exit(globals, ec)
+
+void rtems_shell_hexdump_exit(rtems_shell_hexdump_globals* globals, int code);
diff --git a/cpukit/libmisc/shell/hexsyntax.c b/cpukit/libmisc/shell/hexsyntax.c
new file mode 100644
index 0000000000..0f80738172
--- /dev/null
+++ b/cpukit/libmisc/shell/hexsyntax.c
@@ -0,0 +1,158 @@
+/*-
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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>
+
+#define rindex(s,c) strrchr(s,c)
+
+#include "hexdump.h"
+
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#if RTEMS_REMOVED
+off_t skip; /* bytes to skip */
+#endif
+
+void
+newsyntax(rtems_shell_hexdump_globals* globals, int argc, char ***argvp)
+{
+ int ch;
+ char *p, **argv;
+
+ struct getopt_data getopt_reent;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+ argv = *argvp;
+ if ((p = rindex(argv[0], 'h')) != NULL &&
+ strcmp(p, "hd") == 0) {
+ /* "Canonical" format, implies -C. */
+ add(globals, "\"%08.8_Ax\n\"");
+ add(globals, "\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" ");
+ add(globals, "\" |\" 16/1 \"%_p\" \"|\\n\"");
+ }
+ while ((ch = getopt_r(argc, argv, "bcCde:f:n:os:vx", &getopt_reent)) != -1)
+ switch (ch) {
+ case 'b':
+ add(globals, "\"%07.7_Ax\n\"");
+ add(globals, "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"");
+ break;
+ case 'c':
+ add(globals, "\"%07.7_Ax\n\"");
+ add(globals, "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"");
+ break;
+ case 'C':
+ add(globals, "\"%08.8_Ax\n\"");
+ add(globals, "\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" ");
+ add(globals, "\" |\" 16/1 \"%_p\" \"|\\n\"");
+ break;
+ case 'd':
+ add(globals, "\"%07.7_Ax\n\"");
+ add(globals, "\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"");
+ break;
+ case 'e':
+ add(globals, getopt_reent.optarg);
+ break;
+ case 'f':
+ addfile(globals, getopt_reent.optarg);
+ break;
+ case 'n':
+ if ((length = atoi(getopt_reent.optarg)) < 0)
+ errx(exit_jump, 1, "%s: bad length value", getopt_reent.optarg);
+ break;
+ case 'o':
+ add(globals, "\"%07.7_Ax\n\"");
+ add(globals, "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"");
+ break;
+ case 's':
+ if ((skip = strtoll(getopt_reent.optarg, &p, 0)) < 0)
+ errx(exit_jump, 1, "%s: bad skip value", getopt_reent.optarg);
+ switch(*p) {
+ case 'b':
+ skip *= 512;
+ break;
+ case 'k':
+ skip *= 1024;
+ break;
+ case 'm':
+ skip *= 1048576;
+ break;
+ }
+ break;
+ case 'v':
+ vflag = ALL;
+ break;
+ case 'x':
+ add(globals, "\"%07.7_Ax\n\"");
+ add(globals, "\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"");
+ break;
+ case '?':
+ usage(globals);
+ }
+
+ if (!fshead) {
+ add(globals, "\"%07.7_Ax\n\"");
+ add(globals, "\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"");
+ }
+
+ *argvp += getopt_reent.optind;
+}
+
+void
+usage(rtems_shell_hexdump_globals* globals)
+{
+ (void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
+"usage: hexdump [-bcCdovx] [-e fmt] [-f fmt_file] [-n length]",
+" [-s skip] [file ...]",
+" hd [-bcdovx] [-e fmt] [-f fmt_file] [-n length]",
+" [-s skip] [file ...]");
+ exit(1);
+}
diff --git a/cpukit/libmisc/shell/internal.h b/cpukit/libmisc/shell/internal.h
new file mode 100644
index 0000000000..aadd346092
--- /dev/null
+++ b/cpukit/libmisc/shell/internal.h
@@ -0,0 +1,37 @@
+/*
+ * Shell Internal Information
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_SHELL_INTERNAL_H
+#define _RTEMS_SHELL_INTERNAL_H
+
+struct rtems_shell_topic_tt;
+typedef struct rtems_shell_topic_tt rtems_shell_topic_t;
+
+struct rtems_shell_topic_tt {
+ const char *topic;
+ rtems_shell_topic_t *next;
+};
+
+
+extern rtems_shell_cmd_t * rtems_shell_first_cmd;
+extern rtems_shell_topic_t * rtems_shell_first_topic;
+
+rtems_shell_topic_t * rtems_shell_lookup_topic(const char *topic);
+
+
+void rtems_shell_register_monitor_commands(void);
+void rtems_shell_initialize_command_set(void);
+
+void rtems_shell_print_heap_info(
+ const char *c,
+ Heap_Information *h
+);
+
+#endif
diff --git a/cpukit/libmisc/shell/login_check.c b/cpukit/libmisc/shell/login_check.c
new file mode 100644
index 0000000000..d744ee5954
--- /dev/null
+++ b/cpukit/libmisc/shell/login_check.c
@@ -0,0 +1,62 @@
+/**
+ * @file
+ *
+ * @brief Shell login check function.
+ */
+
+/*
+ * Copyright (c) 2009 embedded brains GmbH and others.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * Based on work from Chris Johns and Fernando Ruiz.
+ *
+ * Derived from file "cpukit/libmisc/shell/shell.c".
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include <rtems/shell.h>
+#include <rtems/userenv.h>
+
+bool rtems_shell_login_check(
+ const char *user,
+ const char *passphrase
+)
+{
+ struct passwd *pw = getpwnam( user);
+
+ /* Valid user? */
+ if (pw != NULL && strcmp( pw->pw_passwd, "!") != 0) {
+ setuid( pw->pw_uid);
+ setgid( pw->pw_gid);
+ rtems_current_user_env->euid = 0;
+ rtems_current_user_env->egid = 0;
+ chown( rtems_current_shell_env->devname, pw->pw_uid, 0);
+ rtems_current_user_env->euid = pw->pw_uid;
+ rtems_current_user_env->egid = pw->pw_gid;
+ if (strcmp( pw->pw_passwd, "*") == 0) {
+ /* TODO: /etc/shadow */
+ return true;
+ } else {
+ /* TODO: crypt() */
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/cpukit/libmisc/shell/login_prompt.c b/cpukit/libmisc/shell/login_prompt.c
new file mode 100644
index 0000000000..7e93078805
--- /dev/null
+++ b/cpukit/libmisc/shell/login_prompt.c
@@ -0,0 +1,209 @@
+/**
+ * @file
+ *
+ * @brief Shell login prompt functions.
+ */
+
+/*
+ * Authorship
+ * ----------
+ * Parts of this software was created by
+ * Till Straumann <strauman@slac.stanford.edu>, 2003-2007
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * Parts of this software was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ *
+ * Copyright (c) 2009 embedded brains GmbH and others.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * Based on work from Chris Johns, Fernando Ruiz and Till Straumann.
+ *
+ * Derived from files "cpukit/libmisc/shell/shell.c" and
+ * "cpukit/telnetd/check_passwd.c".
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <termios.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <rtems/shell.h>
+
+static int rtems_shell_discard( int c, FILE *stream)
+{
+ return c;
+}
+
+static bool rtems_shell_get_text(
+ FILE *in,
+ FILE *out,
+ char *line,
+ size_t size
+)
+{
+ int fd_in = fileno( in);
+ int (*put)( int, FILE *) =
+ out != NULL && isatty( fd_in)
+ ? fputc
+ : rtems_shell_discard;
+ size_t i = 0;
+
+ if (size < 1) {
+ return false;
+ }
+
+ tcdrain( fd_in);
+ if (out != NULL){
+ tcdrain( fileno(out) );
+ }
+
+ while (true) {
+ int c = fgetc(in);
+
+ switch (c) {
+ case EOF:
+ clearerr( in );
+ return false;
+ case '\n':
+ case '\r':
+ put('\n', out);
+ line [i] = '\0';
+ return true;
+ case 127:
+ case '\b':
+ if (i > 0) {
+ put('\b', out);
+ put(' ', out);
+ put('\b', out);
+ --i;
+ } else {
+ put('\a', out);
+ }
+ break;
+ default:
+ if (!iscntrl( c)) {
+ if (i < size - 1) {
+ line [i] = (char) c;
+ ++i;
+ put( c, out);
+ } else {
+ put('\a', out);
+ }
+ } else {
+ put('\a', out);
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+bool rtems_shell_login_prompt(
+ FILE *in,
+ FILE *out,
+ const char *device,
+ rtems_shell_login_check_t check
+)
+{
+ int fd_in = fileno(in);
+ struct termios termios_previous;
+ bool restore_termios = false;
+ int i = 0;
+ bool result = false;
+
+ if (tcgetattr( fd_in, &termios_previous) == 0) {
+ struct termios termios_new = termios_previous;
+
+ /*
+ * Stay in canonical mode so we can tell EOF and dropped connections.
+ * But read one character at a time and do not echo it.
+ */
+ termios_new.c_lflag &= (unsigned char) ~ECHO;
+ termios_new.c_cc [VTIME] = 0;
+ termios_new.c_cc [VMIN] = 1;
+
+ restore_termios = tcsetattr( fd_in, TCSANOW, &termios_new) == 0;
+ }
+
+ for (i = 0; i < 3; ++i) {
+ char user [32];
+ char passphrase [128];
+
+ fprintf( out, "%s login: ", device );
+ fflush( out );
+ result = rtems_shell_get_text( in, out, user, sizeof(user) );
+ if ( !result )
+ break;
+
+ fflush( in);
+ fprintf( out, "Password: ");
+ fflush( out);
+ result = rtems_shell_get_text( in, NULL, passphrase, sizeof(passphrase) );
+ if ( !result )
+ break;
+ fputc( '\n', out);
+
+ result = check( user, passphrase );
+ if (result)
+ break;
+
+ fprintf( out, "Login incorrect\n\n");
+ sleep( 2);
+ }
+
+ if (restore_termios) {
+ /* What to do if restoring the flags fails? */
+ tcsetattr( fd_in, TCSANOW, &termios_previous);
+ }
+
+ return result;
+}
diff --git a/cpukit/libmisc/shell/main_alias.c b/cpukit/libmisc/shell/main_alias.c
new file mode 100644
index 0000000000..9f1b094eaa
--- /dev/null
+++ b/cpukit/libmisc/shell/main_alias.c
@@ -0,0 +1,45 @@
+/*
+ * ALIAS Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_rtems_main_alias(int argc, char **argv)
+{
+ if (argc<3) {
+ fprintf(stderr,"too few arguments\n");
+ return 1;
+ }
+
+ if (!rtems_shell_alias_cmd(argv[1],argv[2])) {
+ fprintf(stderr,"unable to make an alias(%s,%s)\n",argv[1],argv[2]);
+ }
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_ALIAS_Command = {
+ "alias", /* name */
+ "alias old new", /* usage */
+ "misc", /* topic */
+ rtems_shell_rtems_main_alias, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_blksync.c b/cpukit/libmisc/shell/main_blksync.c
new file mode 100644
index 0000000000..bf8369570e
--- /dev/null
+++ b/cpukit/libmisc/shell/main_blksync.c
@@ -0,0 +1,77 @@
+/*
+ * RM Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/bdbuf.h>
+#include <rtems/blkdev.h>
+#include "internal.h"
+
+int rtems_shell_main_blksync(
+ int argc,
+ char *argv[]
+)
+{
+ const char* driver = NULL;
+ int arg;
+ int fd;
+
+ for (arg = 1; arg < argc; arg++) {
+ if (argv[arg][0] == '-') {
+ fprintf( stderr, "%s: invalid option: %s\n", argv[0], argv[arg]);
+ return 1;
+ } else {
+ if (!driver)
+ driver = argv[arg];
+ else {
+ fprintf( stderr, "%s: only one driver name allowed: %s\n",
+ argv[0], argv[arg]);
+ return 1;
+ }
+ }
+ }
+
+ fd = open (driver, O_WRONLY, 0);
+ if (fd < 0) {
+ fprintf( stderr, "%s: driver open failed: %s\n", argv[0], strerror (errno));
+ return 1;
+ }
+
+ if (ioctl (fd, RTEMS_BLKIO_SYNCDEV) < 0) {
+ fprintf( stderr, "%s: driver sync failed: %s\n", argv[0], strerror (errno));
+ return 1;
+ }
+
+ close (fd);
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_BLKSYNC_Command = {
+ "blksync", /* name */
+ "blksync driver # sync the block driver", /* usage */
+ "files", /* topic */
+ rtems_shell_main_blksync, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_cat.c b/cpukit/libmisc/shell/main_cat.c
new file mode 100644
index 0000000000..6efd7a09c8
--- /dev/null
+++ b/cpukit/libmisc/shell/main_cat.c
@@ -0,0 +1,60 @@
+/*
+ * CAT Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <termios.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <stddef.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_cat(int argc, char *argv[])
+{
+ int n;
+ int sc;
+
+ for ( n=1; n < argc ; n++) {
+ sc = rtems_shell_cat_file(stdout, argv[n]);
+ if ( sc == -1 ) {
+ fprintf(stderr, "%s: %s: %s\n", argv[0], argv[n], strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_CAT_Command = {
+ "cat", /* name */
+ "cat n1 [n2 [n3...]] # show the ascii contents", /* usage */
+ "files", /* topic */
+ rtems_shell_main_cat , /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_cd.c b/cpukit/libmisc/shell/main_cd.c
new file mode 100644
index 0000000000..e3ed35fa63
--- /dev/null
+++ b/cpukit/libmisc/shell/main_cd.c
@@ -0,0 +1,26 @@
+/*
+ * CD Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+rtems_shell_alias_t rtems_shell_CD_Alias = {
+ "chdir", /* command */
+ "cd" /* alias */
+};
diff --git a/cpukit/libmisc/shell/main_chdir.c b/cpukit/libmisc/shell/main_chdir.c
new file mode 100644
index 0000000000..2273f5c956
--- /dev/null
+++ b/cpukit/libmisc/shell/main_chdir.c
@@ -0,0 +1,54 @@
+/*
+ * CHDIR Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_chdir(
+ int argc,
+ char *argv[]
+)
+{
+ char *dir;
+
+ dir = "/";
+
+ if (argc > 1)
+ dir = argv[1];
+
+ if (chdir(dir)) {
+ fprintf(stderr, "chdir to '%s' failed:%s\n", dir,strerror(errno));
+ return errno;
+ }
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_CHDIR_Command = {
+ "chdir", /* name */
+ "chdir [dir] # change the current directory", /* usage */
+ "files", /* topic */
+ rtems_shell_main_chdir, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_chmod.c b/cpukit/libmisc/shell/main_chmod.c
new file mode 100644
index 0000000000..3c6ae68310
--- /dev/null
+++ b/cpukit/libmisc/shell/main_chmod.c
@@ -0,0 +1,70 @@
+/*
+ * CHMOD Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include "internal.h"
+
+int rtems_shell_main_chmod(
+ int argc,
+ char *argv[]
+)
+{
+ int n;
+ mode_t mode;
+ unsigned long tmp;
+
+ if (argc < 2) {
+ fprintf(stderr,"%s: too few arguments\n", argv[0]);
+ return -1;
+ }
+
+ /*
+ * Convert arguments into numbers
+ */
+ if ( rtems_string_to_unsigned_long(argv[1], &tmp, NULL, 0) ) {
+ printf( "Mode argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+ mode = (mode_t) (tmp & 0777);
+
+ /*
+ * Now change the files modes
+ */
+ for (n=2 ; n < argc ; n++)
+ chmod(argv[n++], mode);
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_CHMOD_Command = {
+ "chmod", /* name */
+ "chmod 0777 n1 n2... # change filemode", /* usage */
+ "files", /* topic */
+ rtems_shell_main_chmod, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_chroot.c b/cpukit/libmisc/shell/main_chroot.c
new file mode 100644
index 0000000000..ffdfb9ca3b
--- /dev/null
+++ b/cpukit/libmisc/shell/main_chroot.c
@@ -0,0 +1,53 @@
+/*
+ * CHROOT Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_chroot(
+ int argc,
+ char * argv[]
+)
+{
+ char *new_root = "/";
+
+ if (argc == 2)
+ new_root = argv[1];
+
+ if ( chroot(new_root) < 0 ) {
+ fprintf(stderr,"chroot %s (%s)\n", new_root, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_CHROOT_Command = {
+ "chroot", /* name */
+ "chroot [dir] # change the root directory", /* usage */
+ "files", /* topic */
+ rtems_shell_main_chroot, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_cp.c b/cpukit/libmisc/shell/main_cp.c
new file mode 100644
index 0000000000..5b56235abd
--- /dev/null
+++ b/cpukit/libmisc/shell/main_cp.c
@@ -0,0 +1,555 @@
+/* $NetBSD: cp.c,v 1.39 2005/10/24 12:59:07 kleink Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * David Hitz of Auspex Systems Inc.
+ *
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if 0
+#ifndef lint
+__COPYRIGHT(
+"@(#) Copyright (c) 1988, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cp.c 8.5 (Berkeley) 4/29/95";
+#else
+__RCSID("$NetBSD: cp.c,v 1.39 2005/10/24 12:59:07 kleink Exp $");
+#endif
+#endif /* not lint */
+#endif
+/*
+ * Cp copies source files to target files.
+ *
+ * The global PATH_T structure "to" always contains the path to the
+ * current target file. Since fts(3) does not change directories,
+ * this path can be either absolute or dot-relative.
+ *
+ * The basic algorithm is to initialize "to" and use fts(3) to traverse
+ * the file hierarchy rooted in the argument list. A trivial case is the
+ * case of 'cp file1 file2'. The more interesting case is the case of
+ * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
+ * path (relative to the root of the traversal) is appended to dir (stored
+ * in "to") to form the final target path.
+ */
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern-cp.h"
+
+#define S_ISTXT 0
+
+#define STRIP_TRAILING_SLASH(p) { \
+ while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/') \
+ *--(p).p_end = 0; \
+}
+
+enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
+
+static int Rflag, rflag;
+
+static int main_cp(rtems_shell_cp_globals* cp_globals, int, char *[]);
+static int copy(rtems_shell_cp_globals* cp_globals, char *[], enum op, int);
+static int mastercmp(const FTSENT **, const FTSENT **);
+
+void
+rtems_shell_cp_exit (rtems_shell_cp_globals* cp_global, int code __attribute__((unused)))
+{
+ longjmp (cp_global->exit_jmp, 1);
+}
+
+int
+rtems_shell_main_cp(int argc, char *argv[])
+{
+ rtems_shell_cp_globals cp_globals;
+ memset (&cp_globals, 0, sizeof (cp_globals));
+ Rflag = rflag = 0;
+ if (setjmp (cp_globals.exit_jmp) == 0)
+ return main_cp (&cp_globals, argc, argv);
+ return 1;
+}
+
+int
+main_cp(rtems_shell_cp_globals* cp_globals, int argc, char *argv[])
+{
+ struct stat to_stat, tmp_stat;
+ enum op type;
+ int Hflag, Lflag, Pflag, ch, fts_options, r, have_trailing_slash;
+ char *target;
+ struct getopt_data getopt_reent;
+
+ Hflag = Lflag = Pflag = 0;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+ while ((ch = getopt_r(argc, argv, "HLPRafilnprv", &getopt_reent)) != -1)
+ switch (ch) {
+ case 'H':
+ Hflag = 1;
+ Lflag = Pflag = 0;
+ break;
+ case 'L':
+ Lflag = 1;
+ Hflag = Pflag = 0;
+ break;
+ case 'P':
+ Pflag = 1;
+ Hflag = Lflag = 0;
+ break;
+ case 'R':
+ Rflag = 1;
+ break;
+ case 'a':
+ Pflag = 1;
+ pflag = 1;
+ Rflag = 1;
+ Hflag = Lflag = 0;
+ break;
+ case 'f':
+ fflag = 1;
+ iflag = nflag = 0;
+ break;
+ case 'i':
+ iflag = 1;
+ fflag = nflag = 0;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ fflag = iflag = 0;
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case 'r':
+ rflag = Lflag = 1;
+ Hflag = Pflag = 0;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ default:
+ usage(cp_globals);
+ break;
+ }
+ argc -= getopt_reent.optind;
+ argv += getopt_reent.optind;
+
+ if (argc < 2)
+ usage(cp_globals);
+
+ fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
+ if (Rflag && rflag)
+ errx(exit_jump, 1, "the -R and -r options may not be specified together");
+ if (rflag)
+ Rflag = 1;
+ if (Rflag) {
+ if (Hflag)
+ fts_options |= FTS_COMFOLLOW;
+ if (Lflag) {
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ }
+ } else {
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
+ }
+#if 0
+ (void)signal(SIGINFO, siginfo);
+#endif
+
+ /* Save the target base in "to". */
+ target = argv[--argc];
+ if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path))
+ errx(exit_jump, 1, "%s: name too long", target);
+ to.p_end = to.p_path + strlen(to.p_path);
+ if (to.p_path == to.p_end) {
+ *to.p_end++ = '.';
+ *to.p_end = 0;
+ }
+ have_trailing_slash = (to.p_end[-1] == '/');
+ if (have_trailing_slash)
+ STRIP_TRAILING_SLASH(to);
+ to.target_end = to.p_end;
+
+ /* Set end of argument list for fts(3). */
+ argv[argc] = NULL;
+
+ /*
+ * Cp has two distinct cases:
+ *
+ * cp [-R] source target
+ * cp [-R] source1 ... sourceN directory
+ *
+ * In both cases, source can be either a file or a directory.
+ *
+ * In (1), the target becomes a copy of the source. That is, if the
+ * source is a file, the target will be a file, and likewise for
+ * directories.
+ *
+ * In (2), the real target is not directory, but "directory/source".
+ */
+ r = stat(to.p_path, &to_stat);
+ if (r == -1 && errno != ENOENT)
+ err(exit_jump, 1, "%s", to.p_path);
+ if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
+ /*
+ * Case (1). Target is not a directory.
+ */
+ if (argc > 1)
+ errx(exit_jump, 1, "%s is not a directory", to.p_path);
+
+ /*
+ * Need to detect the case:
+ * cp -R dir foo
+ * Where dir is a directory and foo does not exist, where
+ * we want pathname concatenations turned on but not for
+ * the initial mkdir().
+ */
+ if (r == -1) {
+ if (Rflag && (Lflag || Hflag))
+ stat(*argv, &tmp_stat);
+ else
+ lstat(*argv, &tmp_stat);
+
+ if (S_ISDIR(tmp_stat.st_mode) && Rflag)
+ type = DIR_TO_DNE;
+ else
+ type = FILE_TO_FILE;
+ } else
+ type = FILE_TO_FILE;
+
+ if (have_trailing_slash && type == FILE_TO_FILE) {
+ if (r == -1)
+ errx(exit_jump, 1, "directory %s does not exist",
+ to.p_path);
+ else
+ errx(exit_jump, 1, "%s is not a directory", to.p_path);
+ }
+ } else
+ /*
+ * Case (2). Target is a directory.
+ */
+ type = FILE_TO_DIR;
+
+ return copy(cp_globals, argv, type, fts_options);
+}
+
+int
+copy(rtems_shell_cp_globals* cp_globals,
+ char *argv[], enum op type, int fts_options)
+{
+ struct stat to_stat;
+ FTS *ftsp;
+ FTSENT *curr;
+ int base = 0, dne, badcp, rval;
+ size_t nlen;
+ char *p, *target_mid;
+ mode_t mask, mode;
+
+ /*
+ * Keep an inverted copy of the umask, for use in correcting
+ * permissions on created directories when not using -p.
+ */
+ mask = ~umask(0777);
+ umask(~mask);
+
+ if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
+ err(exit_jump, 1, "fts_open");
+ for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) {
+ switch (curr->fts_info) {
+ case FTS_NS:
+ case FTS_DNR:
+ case FTS_ERR:
+ warnx("%s: %s",
+ curr->fts_path, strerror(curr->fts_errno));
+ badcp = rval = 1;
+ continue;
+ case FTS_DC: /* Warn, continue. */
+ warnx("%s: directory causes a cycle", curr->fts_path);
+ badcp = rval = 1;
+ continue;
+ default:
+ ;
+ }
+
+ /*
+ * If we are in case (2) or (3) above, we need to append the
+ * source name to the target name.
+ */
+ if (type != FILE_TO_FILE) {
+ /*
+ * Need to remember the roots of traversals to create
+ * correct pathnames. If there's a directory being
+ * copied to a non-existent directory, e.g.
+ * cp -R a/dir noexist
+ * the resulting path name should be noexist/foo, not
+ * noexist/dir/foo (where foo is a file in dir), which
+ * is the case where the target exists.
+ *
+ * Also, check for "..". This is for correct path
+ * concatenation for paths ending in "..", e.g.
+ * cp -R .. /tmp
+ * Paths ending in ".." are changed to ".". This is
+ * tricky, but seems the easiest way to fix the problem.
+ *
+ * XXX
+ * Since the first level MUST be FTS_ROOTLEVEL, base
+ * is always initialized.
+ */
+ if (curr->fts_level == FTS_ROOTLEVEL) {
+ if (type != DIR_TO_DNE) {
+ p = strrchr(curr->fts_path, '/');
+ base = (p == NULL) ? 0 :
+ (int)(p - curr->fts_path + 1);
+
+ if (!strcmp(&curr->fts_path[base],
+ ".."))
+ base += 1;
+ } else
+ base = curr->fts_pathlen;
+ }
+
+ p = &curr->fts_path[base];
+ nlen = curr->fts_pathlen - base;
+ target_mid = to.target_end;
+ if (*p != '/' && target_mid[-1] != '/')
+ *target_mid++ = '/';
+ *target_mid = 0;
+ if (target_mid - to.p_path + nlen >= PATH_MAX) {
+ warnx("%s%s: name too long (not copied)",
+ to.p_path, p);
+ badcp = rval = 1;
+ continue;
+ }
+ (void)strncat(target_mid, p, nlen);
+ to.p_end = target_mid + nlen;
+ *to.p_end = 0;
+ STRIP_TRAILING_SLASH(to);
+ }
+
+ if (curr->fts_info == FTS_DP) {
+ /*
+ * We are nearly finished with this directory. If we
+ * didn't actually copy it, or otherwise don't need to
+ * change its attributes, then we are done.
+ */
+ if (!curr->fts_number)
+ continue;
+ /*
+ * If -p is in effect, set all the attributes.
+ * Otherwise, set the correct permissions, limited
+ * by the umask. Optimise by avoiding a chmod()
+ * if possible (which is usually the case if we
+ * made the directory). Note that mkdir() does not
+ * honour setuid, setgid and sticky bits, but we
+ * normally want to preserve them on directories.
+ */
+ if (pflag) {
+ if (setfile(cp_globals, curr->fts_statp, -1))
+ rval = 1;
+ if (preserve_dir_acls(curr->fts_statp,
+ curr->fts_accpath, to.p_path) != 0)
+ rval = 1;
+ } else {
+ mode = curr->fts_statp->st_mode;
+ if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) ||
+ ((mode | S_IRWXU) & mask) != (mode & mask))
+ if (chmod(to.p_path, mode & mask) != 0){
+ warn("chmod: %s", to.p_path);
+ rval = 1;
+ }
+ }
+ continue;
+ }
+
+ /* Not an error but need to remember it happened */
+ if (stat(to.p_path, &to_stat) == -1)
+ dne = 1;
+ else {
+ if (to_stat.st_dev == curr->fts_statp->st_dev &&
+ to_stat.st_ino == curr->fts_statp->st_ino) {
+ warnx("%s and %s are identical (not copied).",
+ to.p_path, curr->fts_path);
+ badcp = rval = 1;
+ if (S_ISDIR(curr->fts_statp->st_mode))
+ (void)fts_set(ftsp, curr, FTS_SKIP);
+ continue;
+ }
+ if (!S_ISDIR(curr->fts_statp->st_mode) &&
+ S_ISDIR(to_stat.st_mode)) {
+ warnx("cannot overwrite directory %s with "
+ "non-directory %s",
+ to.p_path, curr->fts_path);
+ badcp = rval = 1;
+ continue;
+ }
+ dne = 0;
+ }
+
+ switch (curr->fts_statp->st_mode & S_IFMT) {
+ case S_IFLNK:
+ /* Catch special case of a non-dangling symlink */
+ if ((fts_options & FTS_LOGICAL) ||
+ ((fts_options & FTS_COMFOLLOW) &&
+ curr->fts_level == 0)) {
+ if (copy_file(cp_globals, curr, dne))
+ badcp = rval = 1;
+ } else {
+ if (copy_link(cp_globals, curr, !dne))
+ badcp = rval = 1;
+ }
+ break;
+ case S_IFDIR:
+ if (!Rflag) {
+ warnx("%s is a directory (not copied).",
+ curr->fts_path);
+ (void)fts_set(ftsp, curr, FTS_SKIP);
+ badcp = rval = 1;
+ break;
+ }
+ /*
+ * If the directory doesn't exist, create the new
+ * one with the from file mode plus owner RWX bits,
+ * modified by the umask. Trade-off between being
+ * able to write the directory (if from directory is
+ * 555) and not causing a permissions race. If the
+ * umask blocks owner writes, we fail..
+ */
+ if (dne) {
+ if (mkdir(to.p_path,
+ curr->fts_statp->st_mode | S_IRWXU) < 0)
+ err(exit_jump, 1, "%s", to.p_path);
+ } else if (!S_ISDIR(to_stat.st_mode)) {
+ errno = ENOTDIR;
+ err(exit_jump, 1, "%s", to.p_path);
+ }
+ /*
+ * Arrange to correct directory attributes later
+ * (in the post-order phase) if this is a new
+ * directory, or if the -p flag is in effect.
+ */
+ curr->fts_number = pflag || dne;
+ break;
+ case S_IFBLK:
+ case S_IFCHR:
+ if (Rflag) {
+ if (copy_special(cp_globals, curr->fts_statp, !dne))
+ badcp = rval = 1;
+ } else {
+ if (copy_file(cp_globals, curr, dne))
+ badcp = rval = 1;
+ }
+ break;
+ case S_IFSOCK:
+ warnx("%s is a socket (not copied).",
+ curr->fts_path);
+ case S_IFIFO:
+ if (Rflag) {
+ if (copy_fifo(cp_globals, curr->fts_statp, !dne))
+ badcp = rval = 1;
+ } else {
+ if (copy_file(cp_globals, curr, dne))
+ badcp = rval = 1;
+ }
+ break;
+ default:
+ if (copy_file(cp_globals, curr, dne))
+ badcp = rval = 1;
+ break;
+ }
+ if (vflag && !badcp)
+ (void)printf("%s -> %s\n", curr->fts_path, to.p_path);
+ }
+ if (errno)
+ err(exit_jump, 1, "fts_read");
+ fts_close(ftsp);
+ return (rval);
+}
+
+/*
+ * mastercmp --
+ * The comparison function for the copy order. The order is to copy
+ * non-directory files before directory files. The reason for this
+ * is because files tend to be in the same cylinder group as their
+ * parent directory, whereas directories tend not to be. Copying the
+ * files first reduces seeking.
+ */
+int
+mastercmp(const FTSENT **a, const FTSENT **b)
+{
+ int a_info, b_info;
+
+ a_info = (*a)->fts_info;
+ if (a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR)
+ return (0);
+ b_info = (*b)->fts_info;
+ if (b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR)
+ return (0);
+ if (a_info == FTS_D)
+ return (-1);
+ if (b_info == FTS_D)
+ return (1);
+ return (0);
+}
+
+rtems_shell_cmd_t rtems_shell_CP_Command = {
+ "cp", /* name */
+ "cp [-R [-H | -L | -P]] [-f | -i] [-pv] src target", /* usage */
+ "files", /* topic */
+ rtems_shell_main_cp, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
+
diff --git a/cpukit/libmisc/shell/main_cpuuse.c b/cpukit/libmisc/shell/main_cpuuse.c
new file mode 100644
index 0000000000..b2329934bd
--- /dev/null
+++ b/cpukit/libmisc/shell/main_cpuuse.c
@@ -0,0 +1,61 @@
+/*
+ * CPUUSE Command Implementation
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <rtems.h>
+#include <rtems/cpuuse.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_cpuuse(
+ int argc,
+ char *argv[]
+)
+{
+ /*
+ * When invoked with no arguments, print the report.
+ */
+ if ( argc == 1 ) {
+ rtems_cpu_usage_report_with_plugin(stdout, (rtems_printk_plugin_t)fprintf);
+ return 0;
+ }
+
+ /*
+ * When invoked with the single argument -r, reset the statistics.
+ */
+ if ( argc == 2 && !strcmp( argv[1], "-r" ) ) {
+ printf( "Resetting CPU Usage information\n" );
+ rtems_cpu_usage_reset();
+ return 0;
+ }
+
+ /*
+ * OK. The user did something wrong.
+ */
+ fprintf( stderr, "%s: [-r]\n", argv[0] );
+ return -1;
+}
+
+rtems_shell_cmd_t rtems_shell_CPUUSE_Command = {
+ "cpuuse", /* name */
+ "[-r] print or reset per thread cpu usage", /* usage */
+ "rtems", /* topic */
+ rtems_shell_main_cpuuse, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_date.c b/cpukit/libmisc/shell/main_date.c
new file mode 100644
index 0000000000..da6faa0e53
--- /dev/null
+++ b/cpukit/libmisc/shell/main_date.c
@@ -0,0 +1,80 @@
+/*
+ * DATE Shell Command Implmentation
+ *
+ * OAuthor: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * Significantly rewritten by Joel Sherrill <joel.sherrill@oarcorp.com>.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_date(
+ int argc,
+ char *argv[]
+)
+{
+ /*
+ * Print the current date and time in default format.
+ */
+ if ( argc == 1 ) {
+ time_t t;
+
+ time(&t);
+ printf("%s", ctime(&t));
+ return 0;
+ }
+
+ /*
+ * Set the current date and time
+ */
+ if ( argc == 3 ) {
+ char buf[128];
+ struct tm TOD;
+ struct timespec timesp;
+ char *result;
+
+ snprintf( buf, sizeof(buf), "%s %s", argv[1], argv[2] );
+ result = strptime(
+ buf,
+ "%Y-%m-%d %T",
+ &TOD
+ );
+ if ( result && !*result ) {
+ timesp.tv_sec = mktime( &TOD );
+ timesp.tv_nsec = 0;
+ clock_settime( CLOCK_REALTIME, &timesp );
+ return 0;
+ }
+ }
+
+ fprintf( stderr, "%s: Usage: [YYYY-MM-DD HH:MM:SS]\n", argv[0] );
+ return -1;
+}
+
+rtems_shell_cmd_t rtems_shell_DATE_Command = {
+ "date", /* name */
+ "date [YYYY-MM-DD HH:MM:SS]", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_date, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_dd.c b/cpukit/libmisc/shell/main_dd.c
new file mode 100644
index 0000000000..930d382a97
--- /dev/null
+++ b/cpukit/libmisc/shell/main_dd.c
@@ -0,0 +1,565 @@
+/*-
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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>
+#if RTEMS_REMOVED
+#include <sys/conf.h>
+#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 DD_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, DD_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, DD_DEFFILEMODE);
+ out.flags |= NOREAD;
+ }
+ if (out.fd == -1)
+ err(exit_jump, 1, "%s", out.name);
+ }
+
+ getfdtype(globals, &out);
+
+ /*
+ * Allocate space for the input and output buffers. If not doing
+ * record oriented I/O, only need a single buffer.
+ */
+ if (!(ddflags & (C_BLOCK | C_UNBLOCK))) {
+ if ((in.db = malloc(out.dbsz + in.dbsz - 1)) == NULL)
+ err(exit_jump, 1, "input buffer");
+ out.db = in.db;
+ } else if ((in.db = malloc(MAX(in.dbsz, cbsz) + cbsz)) == NULL ||
+ (out.db = malloc(out.dbsz + cbsz)) == NULL)
+ err(exit_jump, 1, "output buffer");
+ in.dbp = in.db;
+ out.dbp = out.db;
+
+ /* Position the input/output streams. */
+ if (in.offset)
+ pos_in(globals);
+ if (out.offset)
+ pos_out(globals);
+
+ /*
+ * Truncate the output file. If it fails on a type of output file
+ * that it should _not_ fail on, error out.
+ */
+ if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK) &&
+ out.flags & ISTRUNC)
+ if (ftruncate(out.fd, out.offset * out.dbsz) == -1)
+ err(exit_jump, 1, "truncating %s", out.name);
+
+ if (ddflags & (C_LCASE | C_UCASE | C_ASCII | C_EBCDIC | C_PARITY)) {
+ if (ctab != NULL) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = ctab[cnt];
+ } else {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = cnt;
+ }
+ if ((ddflags & C_PARITY) && !(ddflags & C_ASCII)) {
+ /*
+ * If the input is not EBCDIC, and we do parity
+ * processing, strip input parity.
+ */
+ for (cnt = 200; cnt <= 0377; ++cnt)
+ casetab[cnt] = casetab[cnt & 0x7f];
+ }
+ if (ddflags & C_LCASE) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = tolower(casetab[cnt]);
+ } else if (ddflags & C_UCASE) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = toupper(casetab[cnt]);
+ }
+ if ((ddflags & C_PARITY)) {
+ /*
+ * This should strictly speaking be a no-op, but I
+ * wonder what funny LANG settings could get us.
+ */
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = casetab[cnt] & 0x7f;
+ }
+ if ((ddflags & C_PARSET)) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = casetab[cnt] | 0x80;
+ }
+ if ((ddflags & C_PAREVEN)) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ if (parity(casetab[cnt]))
+ casetab[cnt] = casetab[cnt] | 0x80;
+ }
+ if ((ddflags & C_PARODD)) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ if (!parity(casetab[cnt]))
+ casetab[cnt] = casetab[cnt] | 0x80;
+ }
+
+ ctab = casetab;
+ }
+
+ (void)gettimeofday(&tv, (struct timezone *)NULL);
+ st.start = tv.tv_sec + tv.tv_usec * 1e-6;
+}
+
+static void
+getfdtype(rtems_shell_dd_globals* globals, IO *io)
+{
+ struct stat sb;
+#if RTEMS_REMOVED
+ int type;
+#endif
+
+ if (fstat(io->fd, &sb) == -1)
+ err(exit_jump, 1, "%s", io->name);
+ if (S_ISREG(sb.st_mode))
+ io->flags |= ISTRUNC;
+#if RTEMS_REMOVED
+ if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
+ if (ioctl(io->fd, FIODTYPE, &type) == -1) {
+ err(exit_jump, 1, "%s", io->name);
+ } else {
+ if (type & D_TAPE)
+ io->flags |= ISTAPE;
+ else if (type & (D_DISK | D_MEM))
+ io->flags |= ISSEEK;
+ if (S_ISCHR(sb.st_mode) && (type & D_TAPE) == 0)
+ io->flags |= ISCHR;
+ }
+ return;
+ }
+#else
+ io->flags |= ISSEEK;
+#endif
+ errno = 0;
+ if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
+ io->flags |= ISPIPE;
+ else
+ io->flags |= ISSEEK;
+}
+
+static void
+dd_in(rtems_shell_dd_globals* globals)
+{
+ ssize_t n;
+
+ for (;;) {
+ switch (cpy_cnt) {
+ case -1: /* count=0 was specified */
+ return;
+ case 0:
+ break;
+ default:
+ if (st.in_full + st.in_part >= (uintmax_t)cpy_cnt)
+ return;
+ break;
+ }
+
+ /*
+ * Zero the buffer first if sync; if doing block operations,
+ * use spaces.
+ */
+ if (ddflags & C_SYNC) {
+ if (ddflags & C_FILL)
+ memset(in.dbp, fill_char, in.dbsz);
+ else if (ddflags & (C_BLOCK | C_UNBLOCK))
+ memset(in.dbp, ' ', in.dbsz);
+ else
+ memset(in.dbp, 0, in.dbsz);
+ }
+
+ n = read(in.fd, in.dbp, in.dbsz);
+ if (n == 0) {
+ in.dbrcnt = 0;
+ return;
+ }
+
+ /* Read error. */
+ if (n == -1) {
+ /*
+ * If noerror not specified, die. POSIX requires that
+ * the warning message be followed by an I/O display.
+ */
+ if (!(ddflags & C_NOERROR))
+ err(exit_jump, 1, "%s", in.name);
+ warn("%s", in.name);
+ summary(globals);
+
+ /*
+ * If it's a seekable file descriptor, seek past the
+ * error. If your OS doesn't do the right thing for
+ * raw disks this section should be modified to re-read
+ * in sector size chunks.
+ */
+ if (in.flags & ISSEEK &&
+ lseek(in.fd, (off_t)in.dbsz, SEEK_CUR))
+ warn("%s", in.name);
+
+ /* If sync not specified, omit block and continue. */
+ if (!(ddflags & C_SYNC))
+ continue;
+
+ /* Read errors count as full blocks. */
+ in.dbcnt += in.dbrcnt = in.dbsz;
+ ++st.in_full;
+
+ /* Handle full input blocks. */
+ } else if ((size_t)n == in.dbsz) {
+ in.dbcnt += in.dbrcnt = n;
+ ++st.in_full;
+
+ /* Handle partial input blocks. */
+ } else {
+ /* If sync, use the entire block. */
+ if (ddflags & C_SYNC)
+ in.dbcnt += in.dbrcnt = in.dbsz;
+ else
+ in.dbcnt += in.dbrcnt = n;
+ ++st.in_part;
+ }
+
+ /*
+ * POSIX states that if bs is set and no other conversions
+ * than noerror, notrunc or sync are specified, the block
+ * is output without buffering as it is read.
+ */
+ if (ddflags & C_BS) {
+ out.dbcnt = in.dbcnt;
+ dd_out(globals, 1);
+ in.dbcnt = 0;
+ continue;
+ }
+
+ if (ddflags & C_SWAB) {
+ if ((n = in.dbrcnt) & 1) {
+ ++st.swab;
+ --n;
+ }
+ swab(in.dbp, in.dbp, (size_t)n);
+ }
+
+ in.dbp += in.dbrcnt;
+ (*cfunc)(globals);
+ }
+}
+
+/*
+ * Clean up any remaining I/O and flush output. If necessary, the output file
+ * is truncated.
+ */
+static void
+dd_close(rtems_shell_dd_globals* globals)
+{
+ if (cfunc == def)
+ def_close(globals);
+ else if (cfunc == block)
+ block_close(globals);
+ else if (cfunc == unblock)
+ unblock_close(globals);
+ if (ddflags & C_OSYNC && out.dbcnt && out.dbcnt < out.dbsz) {
+ if (ddflags & C_FILL)
+ memset(out.dbp, fill_char, out.dbsz - out.dbcnt);
+ else if (ddflags & (C_BLOCK | C_UNBLOCK))
+ memset(out.dbp, ' ', out.dbsz - out.dbcnt);
+ else
+ memset(out.dbp, 0, out.dbsz - out.dbcnt);
+ out.dbcnt = out.dbsz;
+ }
+ if (out.dbcnt || pending)
+ dd_out(globals, 1);
+}
+
+void
+dd_out(rtems_shell_dd_globals* globals, int force)
+{
+ u_char *outp;
+ size_t cnt, i, n;
+ ssize_t nw;
+ static int warned;
+ int sparse;
+
+ /*
+ * Write one or more blocks out. The common case is writing a full
+ * output block in a single write; increment the full block stats.
+ * Otherwise, we're into partial block writes. If a partial write,
+ * and it's a character device, just warn. If a tape device, quit.
+ *
+ * The partial writes represent two cases. 1: Where the input block
+ * was less than expected so the output block was less than expected.
+ * 2: Where the input block was the right size but we were forced to
+ * write the block in multiple chunks. The original versions of dd(1)
+ * never wrote a block in more than a single write, so the latter case
+ * never happened.
+ *
+ * One special case is if we're forced to do the write -- in that case
+ * we play games with the buffer size, and it's usually a partial write.
+ */
+ outp = out.db;
+ for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
+ for (cnt = n;; cnt -= nw) {
+ sparse = 0;
+ if (ddflags & C_SPARSE) {
+ sparse = 1; /* Is buffer sparse? */
+ for (i = 0; i < cnt; i++)
+ if (outp[i] != 0) {
+ sparse = 0;
+ break;
+ }
+ }
+ if (sparse && !force) {
+ pending += cnt;
+ nw = cnt;
+ } else {
+ if (pending != 0) {
+ if (force)
+ pending--;
+ if (lseek(out.fd, pending, SEEK_CUR) ==
+ -1)
+ err(exit_jump, 2, "%s: seek error creating sparse file",
+ out.name);
+ if (force)
+ write(out.fd, outp, 1);
+ pending = 0;
+ }
+ if (cnt)
+ nw = write(out.fd, outp, cnt);
+ else
+ return;
+ }
+
+ if (nw <= 0) {
+ if (nw == 0)
+ errx(exit_jump, 1, "%s: end of device", out.name);
+ if (errno != EINTR)
+ err(exit_jump, 1, "%s", out.name);
+ nw = 0;
+ }
+ outp += nw;
+ st.bytes += nw;
+ if ((size_t)nw == n) {
+ if (n != out.dbsz)
+ ++st.out_part;
+ else
+ ++st.out_full;
+ break;
+ }
+ ++st.out_part;
+ if ((size_t)nw == cnt)
+ break;
+ if (out.flags & ISTAPE)
+ errx(exit_jump, 1, "%s: short write on tape device",
+ out.name);
+ if (out.flags & ISCHR && !warned) {
+ warned = 1;
+ warnx("%s: short write on character device",
+ out.name);
+ }
+ }
+ if ((out.dbcnt -= n) < out.dbsz)
+ break;
+ }
+
+ /* Reassemble the output block. */
+ if (out.dbcnt)
+ (void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
+ out.dbp = out.db + out.dbcnt;
+}
+
+rtems_shell_cmd_t rtems_shell_DD_Command = {
+ "dd", /* name */
+ "dd [OPERAND]...", /* usage */
+ "files", /* topic */
+ rtems_shell_main_dd, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_debugrfs.c b/cpukit/libmisc/shell/main_debugrfs.c
new file mode 100644
index 0000000000..5d4052d43a
--- /dev/null
+++ b/cpukit/libmisc/shell/main_debugrfs.c
@@ -0,0 +1,35 @@
+/*
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include <rtems/shellconfig.h>
+#include <rtems/rtems-rfs-shell.h>
+#include <rtems/fsmount.h>
+#include "internal.h"
+
+#define OPTIONS "[-h]"
+
+rtems_shell_cmd_t rtems_shell_DEBUGRFS_Command = {
+ "debugrfs", /* name */
+ "debugrfs " OPTIONS, /* usage */
+ "files", /* topic */
+ rtems_shell_debugrfs, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_dir.c b/cpukit/libmisc/shell/main_dir.c
new file mode 100644
index 0000000000..473ab13f80
--- /dev/null
+++ b/cpukit/libmisc/shell/main_dir.c
@@ -0,0 +1,26 @@
+/*
+ * DIR Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+rtems_shell_alias_t rtems_shell_DIR_Alias = {
+ "ls", /* command */
+ "dir" /* alias */
+};
diff --git a/cpukit/libmisc/shell/main_echo.c b/cpukit/libmisc/shell/main_echo.c
new file mode 100644
index 0000000000..8f868a2f29
--- /dev/null
+++ b/cpukit/libmisc/shell/main_echo.c
@@ -0,0 +1,142 @@
+/* $NetBSD: echo.c,v 1.12 2005/02/06 04:43:43 perry Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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. 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.
+ *
+ * @(#)echo.c 8.1 (Berkeley) 5/31/93
+ */
+
+/*
+ * Echo command.
+ *
+ * echo is steeped in tradition - several of them!
+ * netbsd has supported 'echo [-n | -e] args' in spite of -e not being
+ * documented anywhere.
+ * Posix requires that -n be supported, output from strings containing
+ * \ is implementation defined
+ * The Single Unix Spec requires that \ escapes be treated as if -e
+ * were set, but that -n not be treated as an option.
+ * (ksh supports 'echo [-eEn] args', but not -- so that it is actually
+ * impossible to actually output '-n')
+ *
+ * It is suggested that 'printf "%b" "string"' be used to get \ sequences
+ * expanded. printf is now a builtin of netbsd's sh and csh.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+
+
+int rtems_shell_main_echo(
+ int argc,
+ char *argv[]
+)
+{
+ char **ap;
+ char *p;
+ char c;
+ int count;
+ int nflag = 0;
+ int eflag = 0;
+
+ ap = argv;
+ if (argc)
+ ap++;
+
+ if ((p = *ap) != NULL) {
+ if (!strcmp(p, "-n")) {
+ nflag = 1;
+ ap++;
+ } else if (!strcmp(p, "-e")) {
+ eflag = 1;
+ ap++;
+ }
+ }
+
+ while ((p = *ap++) != NULL) {
+ while ((c = *p++) != '\0') {
+ if (c == '\\' && eflag) {
+ switch (*p++) {
+ case 'a': c = '\a'; break; /* bell */
+ case 'b': c = '\b'; break;
+ case 'c': return 0; /* exit */
+ case 'e': c = 033; break; /* escape */
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+ case '\\': break; /* c = '\\' */
+ case '0':
+ c = 0;
+ count = 3;
+ while (--count >= 0 && (unsigned)(*p - '0') < 8)
+ c = (c << 3) + (*p++ - '0');
+ break;
+ default:
+ /* Output the '/' and char following */
+ p--;
+ break;
+ }
+ }
+ putchar(c);
+ }
+ if (*ap)
+ putchar(' ');
+ }
+ if (! nflag)
+ putchar('\n');
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_ECHO_Command = {
+ "echo", /* name */
+ "echo [args]", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_echo, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_exit.c b/cpukit/libmisc/shell/main_exit.c
new file mode 100644
index 0000000000..4d996cde10
--- /dev/null
+++ b/cpukit/libmisc/shell/main_exit.c
@@ -0,0 +1,26 @@
+/*
+ * exit Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+rtems_shell_alias_t rtems_shell_EXIT_Alias = {
+ "logoff", /* command */
+ "exit" /* alias */
+};
diff --git a/cpukit/libmisc/shell/main_getenv.c b/cpukit/libmisc/shell/main_getenv.c
new file mode 100644
index 0000000000..4e4789b632
--- /dev/null
+++ b/cpukit/libmisc/shell/main_getenv.c
@@ -0,0 +1,49 @@
+/*
+ * Get an environment vairable.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_getenv(int argc, char *argv[])
+{
+ char* string;
+
+ if (argc != 2)
+ {
+ printf ("error: only argument is the variable name\n");
+ return 1;
+ }
+
+ string = getenv (argv[1]);
+
+ if (!string)
+ {
+ printf ("error: %s not found\n", argv[1]);
+ return 1;
+ }
+
+ printf ("%s\n", string);
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_GETENV_Command = {
+ "getenv", /* name */
+ "getenv [var]", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_getenv, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_halt.c b/cpukit/libmisc/shell/main_halt.c
new file mode 100644
index 0000000000..f6f9f7e4fd
--- /dev/null
+++ b/cpukit/libmisc/shell/main_halt.c
@@ -0,0 +1,40 @@
+/*
+ * Halt Command Implementation
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_halt(
+ int argc __attribute__((unused)),
+ char *argv[] __attribute__((unused))
+)
+{
+ exit(0);
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_HALT_Command = {
+ "halt", /* name */
+ "halt", /* usage */
+ "rtems", /* topic */
+ rtems_shell_main_halt, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_help.c b/cpukit/libmisc/shell/main_help.c
new file mode 100644
index 0000000000..512eb60bbc
--- /dev/null
+++ b/cpukit/libmisc/shell/main_help.c
@@ -0,0 +1,152 @@
+/*
+ *
+ * Shell Help Command
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <time.h>
+
+#include <rtems.h>
+#include <rtems/error.h>
+#include <rtems/system.h>
+#include <rtems/shell.h>
+
+#include "internal.h"
+#include <string.h>
+
+/*
+ * show the help for one command.
+ */
+int rtems_shell_help_cmd(
+ rtems_shell_cmd_t *shell_cmd
+)
+{
+ const char * pc;
+ int col,line;
+
+ printf("%-12.12s - ",shell_cmd->name);
+ col = 14;
+ line = 1;
+ if (shell_cmd->alias) {
+ printf("is an <alias> for command '%s'",shell_cmd->alias->name);
+ } else if (shell_cmd->usage) {
+ pc = shell_cmd->usage;
+ while (*pc) {
+ switch(*pc) {
+ case '\r':
+ break;
+ case '\n':
+ putchar('\n');
+ col = 0;
+ break;
+ default:
+ putchar(*pc);
+ col++;
+ break;
+ }
+ pc++;
+ if (col>78) { /* What daring... 78?*/
+ if (*pc) {
+ putchar('\n');
+ col = 0;
+ }
+ }
+ if (!col && *pc) {
+ printf(" ");
+ col = 12;line++;
+ }
+ }
+ }
+ puts("");
+ return line;
+}
+
+/*
+ * show the help. The first command implemented.
+ * Can you see the header of routine? Known?
+ * The same with all the commands....
+ */
+int rtems_shell_help(
+ int argc,
+ char * argv[]
+)
+{
+ int col,line,arg;
+ rtems_shell_topic_t *topic;
+ rtems_shell_cmd_t * shell_cmd = rtems_shell_first_cmd;
+
+ if (argc<2) {
+ printf("help: ('r' repeat last cmd - 'e' edit last cmd)\n"
+ " TOPIC? The topics are\n");
+ topic = rtems_shell_first_topic;
+ col = 0;
+ while (topic) {
+ if (!col){
+ col = printf(" %s",topic->topic);
+ } else {
+ if ((col+strlen(topic->topic)+2)>78){
+ printf("\n");
+ col = printf(" %s",topic->topic);
+ } else {
+ col+= printf(", %s",topic->topic);
+ }
+ }
+ topic = topic->next;
+ }
+ printf("\n");
+ return 1;
+ }
+ line = 0;
+ for (arg = 1;arg<argc;arg++) {
+ if (line>16) {
+ printf("Press any key to continue...");getchar();
+ printf("\n");
+ line = 0;
+ }
+ topic = rtems_shell_lookup_topic(argv[arg]);
+ if (!topic){
+ if ((shell_cmd = rtems_shell_lookup_cmd(argv[arg])) == NULL) {
+ printf("help: topic or cmd '%s' not found. Try <help> alone for a list\n",
+ argv[arg]);
+ line++;
+ } else {
+ line+= rtems_shell_help_cmd(shell_cmd);
+ }
+ continue;
+ }
+ printf("help: list for the topic '%s'\n",argv[arg]);
+ line++;
+ while (shell_cmd) {
+ if (!strcmp(topic->topic,shell_cmd->topic))
+ line+= rtems_shell_help_cmd(shell_cmd);
+ if (line>16) {
+ printf("Press any key to continue...");
+ getchar();
+ printf("\n");
+ line = 0;
+ }
+ shell_cmd = shell_cmd->next;
+ }
+ }
+ puts("");
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_HELP_Command = {
+ "help", /* name */
+ "help [topic] # list of usage of commands", /* usage */
+ "help", /* topic */
+ rtems_shell_help, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_hexdump.c b/cpukit/libmisc/shell/main_hexdump.c
new file mode 100644
index 0000000000..8eb5a4e409
--- /dev/null
+++ b/cpukit/libmisc/shell/main_hexdump.c
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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>
+
+#define rindex(s,c) strrchr(s,c)
+
+#include "hexdump.h"
+
+#if RTEMS_REMOVED
+FS *fshead; /* head of format strings */
+int blocksize; /* data block size */
+int exitval; /* final exit value */
+int length = -1; /* max bytes to read */
+#endif
+
+void
+rtems_shell_hexdump_exit (rtems_shell_hexdump_globals* globals, int code)
+{
+ globals->exit_code = code;
+ longjmp (globals->exit_jmp, 1);
+}
+
+static int main_hexdump(rtems_shell_hexdump_globals* globals, int argc, char *argv[]);
+
+int
+rtems_shell_main_hexdump(int argc, char *argv[])
+{
+ rtems_shell_hexdump_globals hexdump_globals;
+ rtems_shell_hexdump_globals* globals = &hexdump_globals;
+ memset (globals, 0, sizeof (hexdump_globals));
+ vflag = FIRST;
+ ateof = 1;
+ hexdump_globals.exit_code = 1;
+ if (setjmp (hexdump_globals.exit_jmp) == 0)
+ hexdump_globals.exit_code = main_hexdump (globals, argc, argv);
+ if (curp)
+ free (curp);
+ if (savp)
+ free (savp);
+ while (fshead)
+ {
+ FS* nextfs = fshead->nextfs;
+ while (fshead->nextfu)
+ {
+ FU* nextfu = fshead->nextfu->nextfu;
+ if (fshead->nextfu->fmt)
+ free(fshead->nextfu->fmt);
+ while (fshead->nextfu->nextpr)
+ {
+ PR* nextpr = fshead->nextfu->nextpr->nextpr;
+ if (((fshead->nextfu->nextpr->flags & F_TEXT) == 0) &&
+ fshead->nextfu->nextpr->fmt)
+ free(fshead->nextfu->nextpr->fmt);
+ free(fshead->nextfu->nextpr);
+ fshead->nextfu->nextpr = nextpr;
+ }
+ free(fshead->nextfu);
+ fshead->nextfu = nextfu;
+ }
+ free(fshead);
+ fshead = nextfs;
+ }
+ if (hdstdin)
+ {
+ fclose (hdstdin);
+ free (hdstdin);
+ }
+ return hexdump_globals.exit_code;
+}
+
+int
+main_hexdump(rtems_shell_hexdump_globals* globals, int argc, char *argv[])
+{
+ FS *tfs;
+ char *p;
+
+#if RTEMS_REMOVED
+ (void)setlocale(LC_ALL, "");
+#endif
+
+ if (!(p = rindex(argv[0], 'o')) || strcmp(p, "od"))
+ newsyntax(globals, argc, &argv);
+ else
+ oldsyntax(globals, argc, &argv);
+
+ /* figure out the data block size */
+ for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) {
+ tfs->bcnt = size(globals, tfs);
+ if (blocksize < tfs->bcnt)
+ blocksize = tfs->bcnt;
+ }
+ /* rewrite the rules, do syntax checking */
+ for (tfs = fshead; tfs; tfs = tfs->nextfs)
+ rewrite(globals, tfs);
+
+ (void)next(globals, argv);
+ display(globals);
+ exit(exitval);
+ return exitval;
+}
+
+rtems_shell_cmd_t rtems_shell_HEXDUMP_Command = {
+ "hexdump", /* name */
+ "hexdump [-bcCdovx] [-e fmt] [-f fmt_file] [-n length]\n" /* usage */
+ " [-s skip] [file ...]",
+ "files", /* topic */
+ rtems_shell_main_hexdump, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
+
diff --git a/cpukit/libmisc/shell/main_id.c b/cpukit/libmisc/shell/main_id.c
new file mode 100644
index 0000000000..8fa0914597
--- /dev/null
+++ b/cpukit/libmisc/shell/main_id.c
@@ -0,0 +1,67 @@
+/*
+ * ID Command Implementation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_id(
+ int argc __attribute__((unused)),
+ char *argv[] __attribute__((unused))
+)
+{
+ struct passwd *pwd;
+ struct group *grp;
+
+ pwd = getpwuid(getuid());
+ grp = getgrgid(getgid());
+ printf(
+ "uid=%d(%s),gid=%d(%s),",
+ getuid(),
+ (pwd) ? pwd->pw_name : "",
+ getgid(),
+ (grp) ? grp->gr_name : ""
+ );
+ pwd = getpwuid(geteuid());
+ grp = getgrgid(getegid());
+ printf(
+ "euid=%d(%s),egid=%d(%s)\n",
+ geteuid(),
+ (pwd) ? pwd->pw_name : "",
+ getegid(),
+ (grp) ? grp->gr_name : ""
+ );
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_ID_Command = {
+ "id", /* name */
+ "show uid, gid, euid, and egid", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_id, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_ifconfig.c b/cpukit/libmisc/shell/main_ifconfig.c
new file mode 100644
index 0000000000..9f16207b10
--- /dev/null
+++ b/cpukit/libmisc/shell/main_ifconfig.c
@@ -0,0 +1,243 @@
+/*
+ * IFCONFIG Command Implmentation
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_ifconfig(
+ int argc,
+ char *argv[]
+)
+{
+ struct sockaddr_in ipaddr;
+ struct sockaddr_in dstaddr;
+ struct sockaddr_in netmask;
+ struct sockaddr_in broadcast;
+ char *iface;
+ int f_ip = 0;
+ int f_ptp = 0;
+ int f_netmask = 0;
+ int f_up = 0;
+ int f_down = 0;
+ int f_bcast = 0;
+ int cur_idx;
+ int rc;
+ int flags;
+
+ memset(&ipaddr, 0, sizeof(ipaddr));
+ memset(&dstaddr, 0, sizeof(dstaddr));
+ memset(&netmask, 0, sizeof(netmask));
+ memset(&broadcast, 0, sizeof(broadcast));
+
+ ipaddr.sin_len = sizeof(ipaddr);
+ ipaddr.sin_family = AF_INET;
+
+ dstaddr.sin_len = sizeof(dstaddr);
+ dstaddr.sin_family = AF_INET;
+
+ netmask.sin_len = sizeof(netmask);
+ netmask.sin_family = AF_INET;
+
+ broadcast.sin_len = sizeof(broadcast);
+ broadcast.sin_family = AF_INET;
+
+ cur_idx = 0;
+ if (argc <= 1) {
+ /* display all interfaces */
+ iface = NULL;
+ cur_idx += 1;
+ } else {
+ iface = argv[1];
+ if (isdigit((unsigned char)*argv[2])) {
+ if (inet_pton(AF_INET, argv[2], &ipaddr.sin_addr) < 0) {
+ printf("bad ip address: %s\n", argv[2]);
+ return 0;
+ }
+ f_ip = 1;
+ cur_idx += 3;
+ } else {
+ cur_idx += 2;
+ }
+ }
+
+ if ((f_down !=0) && (f_ip != 0)) {
+ f_up = 1;
+ }
+
+ while(argc > cur_idx) {
+ if (strcmp(argv[cur_idx], "up") == 0) {
+ f_up = 1;
+ if (f_down != 0) {
+ printf("Can't make interface up and down\n");
+ }
+ } else if(strcmp(argv[cur_idx], "down") == 0) {
+ f_down = 1;
+ if (f_up != 0) {
+ printf("Can't make interface up and down\n");
+ }
+ } else if(strcmp(argv[cur_idx], "netmask") == 0) {
+ if ((cur_idx + 1) >= argc) {
+ printf("No netmask address\n");
+ return -1;
+ }
+ if (inet_pton(AF_INET, argv[cur_idx+1], &netmask.sin_addr) < 0) {
+ printf("bad netmask: %s\n", argv[cur_idx]);
+ return -1;
+ }
+ f_netmask = 1;
+ cur_idx += 1;
+ } else if(strcmp(argv[cur_idx], "broadcast") == 0) {
+ if ((cur_idx + 1) >= argc) {
+ printf("No broadcast address\n");
+ return -1;
+ }
+ if (inet_pton(AF_INET, argv[cur_idx+1], &broadcast.sin_addr) < 0) {
+ printf("bad broadcast: %s\n", argv[cur_idx]);
+ return -1;
+ }
+ f_bcast = 1;
+ cur_idx += 1;
+ } else if(strcmp(argv[cur_idx], "pointopoint") == 0) {
+ if ((cur_idx + 1) >= argc) {
+ printf("No pointopoint address\n");
+ return -1;
+ }
+ if (inet_pton(AF_INET, argv[cur_idx+1], &dstaddr.sin_addr) < 0) {
+ printf("bad pointopoint: %s\n", argv[cur_idx]);
+ return -1;
+ }
+ f_ptp = 1;
+ cur_idx += 1;
+ } else {
+ printf("Bad parameter: %s\n", argv[cur_idx]);
+ return -1;
+ }
+ cur_idx += 1;
+ }
+
+ printf("ifconfig ");
+ if (iface != NULL) {
+ printf("%s ", iface);
+ if (f_ip != 0) {
+ char str[256];
+ inet_ntop(AF_INET, &ipaddr.sin_addr, str, 256);
+ printf("%s ", str);
+ }
+
+ if (f_netmask != 0) {
+ char str[256];
+ inet_ntop(AF_INET, &netmask.sin_addr, str, 256);
+ printf("netmask %s ", str);
+ }
+
+ if (f_bcast != 0) {
+ char str[256];
+ inet_ntop(AF_INET, &broadcast.sin_addr, str, 256);
+ printf("broadcast %s ", str);
+ }
+
+ if (f_ptp != 0) {
+ char str[256];
+ inet_ntop(AF_INET, &dstaddr.sin_addr, str, 256);
+ printf("pointopoint %s ", str);
+ }
+
+ if (f_up != 0) {
+ printf("up\n");
+ } else if (f_down != 0) {
+ printf("down\n");
+ } else {
+ printf("\n");
+ }
+ }
+
+ if ((iface == NULL) || ((f_ip == 0) && (f_down == 0) && (f_up == 0))) {
+ rtems_bsdnet_show_if_stats();
+ return 0;
+ }
+
+ flags = 0;
+ if (f_netmask) {
+ rc = rtems_bsdnet_ifconfig(iface, SIOCSIFNETMASK, &netmask);
+ if (rc < 0) {
+ printf("Could not set netmask: %s\n", strerror(errno));
+ return -1;
+ }
+ }
+
+ if (f_bcast) {
+ rc = rtems_bsdnet_ifconfig(iface, SIOCSIFBRDADDR, &broadcast);
+ if (rc < 0) {
+ printf("Could not set broadcast: %s\n", strerror(errno));
+ return -1;
+ }
+ }
+
+ if (f_ptp) {
+ rc = rtems_bsdnet_ifconfig(iface, SIOCSIFDSTADDR, &dstaddr);
+ if (rc < 0) {
+ printf("Could not set destination address: %s\n", strerror(errno));
+ return -1;
+ }
+ flags |= IFF_POINTOPOINT;
+ }
+
+ /* This must come _after_ setting the netmask, broadcast addresses */
+ if (f_ip) {
+ rc = rtems_bsdnet_ifconfig(iface, SIOCSIFADDR, &ipaddr);
+ if (rc < 0) {
+ printf("Could not set IP address: %s\n", strerror(errno));
+ return -1;
+ }
+ }
+
+ if (f_up != 0) {
+ flags |= IFF_UP;
+ }
+
+ if (f_down != 0) {
+ printf("Warning: taking interfaces down is not supported\n");
+ }
+
+ rc = rtems_bsdnet_ifconfig(iface, SIOCSIFFLAGS, &flags);
+ if (rc < 0) {
+ printf("Could not set interface flags: %s\n", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_IFCONFIG_Command = {
+ "ifconfig", /* name */
+ "TBD", /* usage */
+ "network", /* topic */
+ rtems_shell_main_ifconfig, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_ln.c b/cpukit/libmisc/shell/main_ln.c
new file mode 100644
index 0000000000..aff1ffbf91
--- /dev/null
+++ b/cpukit/libmisc/shell/main_ln.c
@@ -0,0 +1,309 @@
+/* $NetBSD: ln.c,v 1.34 2008/07/20 00:52:40 lukem Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if 0
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ln.c 8.2 (Berkeley) 3/31/94";
+#else
+__RCSID("$NetBSD: ln.c,v 1.34 2008/07/20 00:52:40 lukem Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <setjmp.h>
+
+typedef struct {
+ int fflag; /* Unlink existing files. */
+ int hflag; /* Check new name for symlink first. */
+ int iflag; /* Interactive mode. */
+ int sflag; /* Symbolic, not hard, link. */
+ int vflag; /* Verbose output */
+ char linkch;
+
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_ln_globals;
+
+#define fflag globals->fflag
+#define hflag globals->hflag
+#define iflag globals->iflag
+#define sflag globals->sflag
+#define vflag globals->vflag
+#define linkch globals->linkch
+
+#define exit_jump &(globals->exit_jmp)
+
+#define exit(ec) rtems_shell_ln_exit(globals, ec)
+
+static int main_ln(rtems_shell_ln_globals* , int, char *[]);
+
+static void
+rtems_shell_ln_exit (rtems_shell_ln_globals* globals, int code)
+{
+ globals->exit_code = code;
+ longjmp (globals->exit_jmp, 1);
+}
+
+static int main_ln(rtems_shell_ln_globals* globals, int argc, char *argv[]);
+
+int
+rtems_shell_main_ln(int argc, char *argv[])
+{
+ rtems_shell_ln_globals ln_globals;
+ rtems_shell_ln_globals* globals = &ln_globals;
+ memset (globals, 0, sizeof (ln_globals));
+ ln_globals.exit_code = 1;
+ if (setjmp (ln_globals.exit_jmp) == 0)
+ return main_ln (globals, argc, argv);
+ return ln_globals.exit_code;
+}
+
+#if RTEMS_REMOVED
+int fflag; /* Unlink existing files. */
+int hflag; /* Check new name for symlink first. */
+int iflag; /* Interactive mode. */
+int sflag; /* Symbolic, not hard, link. */
+int vflag; /* Verbose output */
+
+ /* System link call. */
+int (*linkf)(const char *, const char *);
+char linkch;
+#endif
+
+int (*linkf)(const char *, const char *);
+
+static int linkit(rtems_shell_ln_globals* , const char *, const char *, int);
+static void usage(rtems_shell_ln_globals* );
+
+static int
+main_ln(rtems_shell_ln_globals* globals, int argc, char *argv[])
+{
+ struct stat sb;
+ int ch, exitval;
+ char *sourcedir;
+
+ struct getopt_data getopt_reent;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+#if RTEMS_REMOVED
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+#endif
+
+ while ((ch = getopt_r(argc, argv, "fhinsv", &getopt_reent)) != -1)
+ switch (ch) {
+ case 'f':
+ fflag = 1;
+ iflag = 0;
+ break;
+ case 'h':
+ case 'n':
+ hflag = 1;
+ break;
+ case 'i':
+ iflag = 1;
+ fflag = 0;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ case '?':
+ default:
+ usage(globals);
+ /* NOTREACHED */
+ }
+
+ argv += getopt_reent.optind;
+ argc -= getopt_reent.optind;
+
+ if (sflag) {
+ linkf = symlink;
+ linkch = '-';
+ } else {
+ linkf = link;
+ linkch = '=';
+ }
+
+ switch(argc) {
+ case 0:
+ usage(globals);
+ /* NOTREACHED */
+ case 1: /* ln target */
+ exit(linkit(globals, argv[0], ".", 1));
+ /* NOTREACHED */
+ case 2: /* ln target source */
+ exit(linkit(globals, argv[0], argv[1], 0));
+ /* NOTREACHED */
+ }
+
+ /* ln target1 target2 directory */
+ sourcedir = argv[argc - 1];
+ if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
+ /* we were asked not to follow symlinks, but found one at
+ the target--simulate "not a directory" error */
+ errno = ENOTDIR;
+ err(exit_jump, EXIT_FAILURE, "%s", sourcedir);
+ /* NOTREACHED */
+ }
+ if (stat(sourcedir, &sb)) {
+ err(exit_jump, EXIT_FAILURE, "%s", sourcedir);
+ /* NOTREACHED */
+ }
+ if (!S_ISDIR(sb.st_mode)) {
+ usage(globals);
+ /* NOTREACHED */
+ }
+ for (exitval = 0; *argv != sourcedir; ++argv)
+ exitval |= linkit(globals, *argv, sourcedir, 1);
+ exit(exitval);
+ /* NOTREACHED */
+ return 0;
+}
+
+int
+linkit(rtems_shell_ln_globals* globals, const char *source, const char *target, int isdir)
+{
+ struct stat sb;
+ const char *p;
+ char path[MAXPATHLEN];
+ int ch, exists, first;
+
+ if (!sflag) {
+ /* If target doesn't exist, quit now. */
+ if (stat(target, &sb)) {
+ warn("%s", target);
+ return (1);
+ }
+ }
+
+ /* If the source is a directory (and not a symlink if hflag),
+ append the target's name. */
+ if (isdir ||
+ (!lstat(source, &sb) && S_ISDIR(sb.st_mode)) ||
+ (!hflag && !stat(source, &sb) && S_ISDIR(sb.st_mode))) {
+ if ((p = strrchr(target, '/')) == NULL)
+ p = target;
+ else
+ ++p;
+ (void)snprintf(path, sizeof(path), "%s/%s", source, p);
+ source = path;
+ }
+
+ exists = !lstat(source, &sb);
+
+ /*
+ * If the file exists, then unlink it forcibly if -f was specified
+ * and interactively if -i was specified.
+ */
+ if (fflag && exists) {
+ if (unlink(source)) {
+ warn("%s", source);
+ return (1);
+ }
+ } else if (iflag && exists) {
+ fflush(stdout);
+ (void)fprintf(stderr, "replace %s? ", source);
+
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (first != 'y' && first != 'Y') {
+ (void)fprintf(stderr, "not replaced\n");
+ return (1);
+ }
+
+ if (unlink(source)) {
+ warn("%s", source);
+ return (1);
+ }
+ }
+
+ /* Attempt the link. */
+ if ((*linkf)(target, source)) {
+ warn("%s", source);
+ return (1);
+ }
+ if (vflag)
+ (void)printf("%s %c> %s\n", source, linkch, target);
+
+ return (0);
+}
+
+void
+usage(rtems_shell_ln_globals* globals)
+{
+#define getprogname() "ln"
+ (void)fprintf(stderr,
+ "usage:\t%s [-fhinsv] file1 file2\n\t%s [-fhinsv] file ... directory\n",
+ getprogname(), getprogname());
+ exit(1);
+ /* NOTREACHED */
+}
+
+rtems_shell_cmd_t rtems_shell_LN_Command = {
+ "ln", /* name */
+ "ln ln [-fhinsv] source_file [target_file]", /* usage */
+ "files", /* topic */
+ rtems_shell_main_ln, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_logoff.c b/cpukit/libmisc/shell/main_logoff.c
new file mode 100644
index 0000000000..7258724f04
--- /dev/null
+++ b/cpukit/libmisc/shell/main_logoff.c
@@ -0,0 +1,44 @@
+/*
+ * LOGOFF Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_logoff(
+ int argc __attribute__((unused)),
+ char *argv[] __attribute__((unused))
+)
+{
+ printf("logoff from the system...");
+
+ rtems_current_shell_env->exit_shell = true;
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_LOGOFF_Command = {
+ "logoff", /* name */
+ "logoff from the system", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_logoff, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_ls.c b/cpukit/libmisc/shell/main_ls.c
new file mode 100644
index 0000000000..08072fb723
--- /dev/null
+++ b/cpukit/libmisc/shell/main_ls.c
@@ -0,0 +1,776 @@
+/* $NetBSD: ls.c,v 1.58 2005/10/26 02:24:22 jschauma Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Fischbein.
+ *
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if 0
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ls.c 8.7 (Berkeley) 8/5/94";
+#else
+__RCSID("$NetBSD: ls.c,v 1.58 2005/10/26 02:24:22 jschauma Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "extern-ls.h"
+
+static void display(rtems_shell_ls_globals* globals, FTSENT *, FTSENT *);
+static int mastercmp_listdir(const FTSENT **, const FTSENT **);
+static int mastercmp_no_listdir(const FTSENT **, const FTSENT **);
+static void traverse(rtems_shell_ls_globals* globals, int, char **, int);
+
+static void (*printfcn)(rtems_shell_ls_globals* globals, DISPLAY *);
+static int (*sortfcn)(const FTSENT *, const FTSENT *);
+
+#define BY_NAME 0
+#define BY_SIZE 1
+#define BY_TIME 2
+
+#if RTEMS_REMOVED
+long blocksize; /* block size units */
+int termwidth = 80; /* default terminal width */
+int sortkey = BY_NAME;
+int rval = EXIT_SUCCESS; /* exit value - set if error encountered */
+
+/* flags */
+int f_accesstime; /* use time of last access */
+int f_column; /* columnated format */
+int f_columnacross; /* columnated format, sorted across */
+int f_flags; /* show flags associated with a file */
+int f_grouponly; /* long listing without owner */
+int f_humanize; /* humanize the size field */
+int f_inode; /* print inode */
+int f_listdir; /* list actual directory, not contents */
+int f_listdot; /* list files beginning with . */
+int f_longform; /* long listing format */
+int f_nonprint; /* show unprintables as ? */
+int f_nosort; /* don't sort output */
+int f_numericonly; /* don't convert uid/gid to name */
+int f_octal; /* print octal escapes for nongraphic characters */
+int f_octal_escape; /* like f_octal but use C escapes if possible */
+int f_recursive; /* ls subdirectories also */
+int f_reversesort; /* reverse whatever sort is used */
+int f_sectime; /* print the real time for all files */
+int f_singlecol; /* use single column output */
+int f_size; /* list size in short listing */
+int f_statustime; /* use time of last mode change */
+int f_stream; /* stream format */
+int f_type; /* add type character for non-regular files */
+int f_typedir; /* add type character for directories */
+int f_whiteout; /* show whiteout entries */
+#endif
+
+void
+rtems_shell_ls_exit (rtems_shell_ls_globals* globals, int code)
+{
+ globals->exit_code = code;
+ longjmp (globals->exit_jmp, 1);
+}
+
+static int main_ls(rtems_shell_ls_globals* globals, int argc, char *argv[]);
+
+int
+rtems_shell_main_ls(int argc, char *argv[])
+{
+ rtems_shell_ls_globals ls_globals;
+ rtems_shell_ls_globals* globals = &ls_globals;
+ memset (globals, 0, sizeof (ls_globals));
+ termwidth = 80;
+ sortkey = BY_NAME;
+ rval = EXIT_SUCCESS;
+ ls_globals.exit_code = 1;
+ if (setjmp (ls_globals.exit_jmp) == 0)
+ return main_ls (globals, argc, argv);
+ return ls_globals.exit_code;
+}
+
+int
+main_ls(rtems_shell_ls_globals* globals, int argc, char *argv[])
+{
+ static char dot[] = ".", *dotav[] = { dot, NULL };
+ //struct winsize win;
+ int ch, fts_options;
+ int kflag = 0;
+ const char *p;
+
+ struct getopt_data getopt_reent;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+#if RTEMS_REMOVED
+ setprogname(argv[0]);
+#endif
+ setlocale(LC_ALL, "");
+
+ /* Terminal defaults to -Cq, non-terminal defaults to -1. */
+ if (isatty(STDOUT_FILENO)) {
+#if RTEMS_REMOVED
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 &&
+ win.ws_col > 0)
+ termwidth = win.ws_col;
+ f_column = f_nonprint = 1;
+#endif
+ } else
+ f_singlecol = 1;
+
+ /* Root is -A automatically. */
+ if (!getuid())
+ f_listdot = 1;
+
+ fts_options = FTS_PHYSICAL;
+ while ((ch = getopt_r(argc, argv,
+ "1ABCFLRSTWabcdfghiklmnopqrstuwx", &getopt_reent)) != -1) {
+ switch (ch) {
+ /*
+ * The -1, -C, -l, -m and -x options all override each other so
+ * shell aliasing works correctly.
+ */
+ case '1':
+ f_singlecol = 1;
+ f_column = f_columnacross = f_longform = f_stream = 0;
+ break;
+ case 'C':
+ f_column = 1;
+ f_columnacross = f_longform = f_singlecol = f_stream =
+ 0;
+ break;
+ case 'g':
+ if (f_grouponly != -1)
+ f_grouponly = 1;
+ f_longform = 1;
+ f_column = f_columnacross = f_singlecol = f_stream = 0;
+ break;
+ case 'l':
+ f_longform = 1;
+ f_column = f_columnacross = f_singlecol = f_stream = 0;
+ /* Never let -g take precedence over -l. */
+ f_grouponly = -1;
+ break;
+ case 'm':
+ f_stream = 1;
+ f_column = f_columnacross = f_longform = f_singlecol =
+ 0;
+ break;
+ case 'x':
+ f_columnacross = 1;
+ f_column = f_longform = f_singlecol = f_stream = 0;
+ break;
+ /* The -c and -u options override each other. */
+ case 'c':
+ f_statustime = 1;
+ f_accesstime = 0;
+ break;
+ case 'u':
+ f_accesstime = 1;
+ f_statustime = 0;
+ break;
+ case 'F':
+ f_type = 1;
+ break;
+ case 'L':
+ fts_options &= ~FTS_PHYSICAL;
+ fts_options |= FTS_LOGICAL;
+ break;
+ case 'R':
+ f_recursive = 1;
+ break;
+ case 'a':
+ fts_options |= FTS_SEEDOT;
+ /* FALLTHROUGH */
+ case 'A':
+ f_listdot = 1;
+ break;
+ /* The -B option turns off the -b, -q and -w options. */
+ case 'B':
+ f_nonprint = 0;
+ f_octal = 1;
+ f_octal_escape = 0;
+ break;
+ /* The -b option turns off the -B, -q and -w options. */
+ case 'b':
+ f_nonprint = 0;
+ f_octal = 0;
+ f_octal_escape = 1;
+ break;
+ /* The -d option turns off the -R option. */
+ case 'd':
+ f_listdir = 1;
+ f_recursive = 0;
+ break;
+ case 'f':
+ f_nosort = 1;
+ break;
+ case 'i':
+ f_inode = 1;
+ break;
+ case 'k':
+ blocksize = 1024;
+ kflag = 1;
+ break;
+ /* The -h option forces all sizes to be measured in bytes. */
+ case 'h':
+ f_humanize = 1;
+ break;
+ case 'n':
+ f_numericonly = 1;
+ break;
+ case 'o':
+ f_flags = 1;
+ break;
+ case 'p':
+ f_typedir = 1;
+ break;
+ /* The -q option turns off the -B, -b and -w options. */
+ case 'q':
+ f_nonprint = 1;
+ f_octal = 0;
+ f_octal_escape = 0;
+ break;
+ case 'r':
+ f_reversesort = 1;
+ break;
+ case 'S':
+ sortkey = BY_SIZE;
+ break;
+ case 's':
+ f_size = 1;
+ break;
+ case 'T':
+ f_sectime = 1;
+ break;
+ case 't':
+ sortkey = BY_TIME;
+ break;
+ case 'W':
+ f_whiteout = 1;
+ break;
+ /* The -w option turns off the -B, -b and -q options. */
+ case 'w':
+ f_nonprint = 0;
+ f_octal = 0;
+ f_octal_escape = 0;
+ break;
+ default:
+ case '?':
+ usage(globals);
+ }
+ }
+ argc -= getopt_reent.optind;
+ argv += getopt_reent.optind;
+
+ if (f_column || f_columnacross || f_stream) {
+ if ((p = getenv("COLUMNS")) != NULL)
+ termwidth = atoi(p);
+ }
+
+ /*
+ * If both -g and -l options, let -l take precedence.
+ */
+ if (f_grouponly == -1)
+ f_grouponly = 0;
+
+ /*
+ * If not -F, -i, -l, -p, -S, -s or -t options, don't require stat
+ * information.
+ */
+ if (!f_inode && !f_longform && !f_size && !f_type && !f_typedir &&
+ sortkey == BY_NAME)
+ fts_options |= FTS_NOSTAT;
+
+ /*
+ * If not -F, -d or -l options, follow any symbolic links listed on
+ * the command line.
+ */
+ if (!f_longform && !f_listdir && !f_type)
+ fts_options |= FTS_COMFOLLOW;
+
+ /*
+ * If -W, show whiteout entries
+ */
+#ifdef FTS_WHITEOUT
+ if (f_whiteout)
+ fts_options |= FTS_WHITEOUT;
+#endif
+
+ /* If -l or -s, figure out block size. */
+ if (f_inode || f_longform || f_size) {
+#if RTEMS_REMOVED
+ if (!kflag)
+ (void)getbsize(NULL, &blocksize);
+#else
+ /* Make equal to 1 so ls -l shows the actual blcok count */
+ blocksize = 512;
+#endif
+ blocksize /= 512;
+ }
+
+ /* Select a sort function. */
+ if (f_reversesort) {
+ switch (sortkey) {
+ case BY_NAME:
+ sortfcn = revnamecmp;
+ break;
+ case BY_SIZE:
+ sortfcn = revsizecmp;
+ break;
+ case BY_TIME:
+ if (f_accesstime)
+ sortfcn = revacccmp;
+ else if (f_statustime)
+ sortfcn = revstatcmp;
+ else /* Use modification time. */
+ sortfcn = revmodcmp;
+ break;
+ }
+ } else {
+ switch (sortkey) {
+ case BY_NAME:
+ sortfcn = namecmp;
+ break;
+ case BY_SIZE:
+ sortfcn = sizecmp;
+ break;
+ case BY_TIME:
+ if (f_accesstime)
+ sortfcn = acccmp;
+ else if (f_statustime)
+ sortfcn = statcmp;
+ else /* Use modification time. */
+ sortfcn = modcmp;
+ break;
+ }
+ }
+
+ /* Select a print function. */
+ if (f_singlecol)
+ printfcn = printscol;
+ else if (f_columnacross)
+ printfcn = printacol;
+ else if (f_longform)
+ printfcn = printlong;
+ else if (f_stream)
+ printfcn = printstream;
+ else
+ printfcn = printcol;
+
+ if (argc)
+ traverse(globals, argc, argv, fts_options);
+ else
+ traverse(globals, 1, dotav, fts_options);
+ exit(rval);
+ /* NOTREACHED */
+ return 0;
+}
+
+#if RTEMS_REMOVED
+static int output; /* If anything output. */
+#endif
+
+/*
+ * Traverse() walks the logical directory structure specified by the argv list
+ * in the order specified by the mastercmp() comparison function. During the
+ * traversal it passes linked lists of structures to display() which represent
+ * a superset (may be exact set) of the files to be displayed.
+ */
+static void
+traverse(rtems_shell_ls_globals* globals, int argc, char *argv[], int options)
+{
+ FTS *ftsp;
+ FTSENT *p, *chp;
+ int ch_options;
+
+ if ((ftsp =
+ fts_open(argv, options,
+ f_nosort ? NULL : f_listdir ?
+ mastercmp_listdir : mastercmp_no_listdir)) == NULL)
+ err(exit_jump, EXIT_FAILURE, NULL);
+
+ display(globals, NULL, fts_children(ftsp, 0));
+ if (f_listdir)
+ {
+ fts_close(ftsp);
+ return;
+ }
+
+ /*
+ * If not recursing down this tree and don't need stat info, just get
+ * the names.
+ */
+ ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0;
+
+ while ((p = fts_read(ftsp)) != NULL)
+ switch (p->fts_info) {
+ case FTS_DC:
+ warnx("%s: directory causes a cycle", p->fts_name);
+ break;
+ case FTS_DNR:
+ case FTS_ERR:
+ warnx("%s: %s", p->fts_name, strerror(p->fts_errno));
+ rval = EXIT_FAILURE;
+ break;
+ case FTS_D:
+ if (p->fts_level != FTS_ROOTLEVEL &&
+ p->fts_name[0] == '.' && !f_listdot)
+ break;
+
+ /*
+ * If already output something, put out a newline as
+ * a separator. If multiple arguments, precede each
+ * directory with its name.
+ */
+ if (output)
+ (void)printf("\n%s:\n", p->fts_path);
+ else if (argc > 1) {
+ (void)printf("%s:\n", p->fts_path);
+ output = 1;
+ }
+
+ chp = fts_children(ftsp, ch_options);
+ display(globals, p, chp);
+
+ if (!f_recursive && chp != NULL)
+ (void)fts_set(ftsp, p, FTS_SKIP);
+ break;
+ }
+ fts_close(ftsp);
+ if (errno)
+ err(exit_jump, EXIT_FAILURE, "fts_read");
+}
+
+/*
+ * Display() takes a linked list of FTSENT structures and passes the list
+ * along with any other necessary information to the print function. P
+ * points to the parent directory of the display list.
+ */
+static void
+display(rtems_shell_ls_globals* globals, FTSENT *p, FTSENT *list)
+{
+ struct stat *sp;
+ DISPLAY d;
+ FTSENT *cur;
+ NAMES *np;
+ u_int64_t btotal, stotal, maxblock, maxsize;
+ int maxinode, maxnlink, maxmajor, maxminor;
+ int bcfile, entries, flen, glen, ulen, maxflags, maxgroup, maxlen;
+ int maxuser, needstats;
+ const char *user, *group;
+ char buf[21]; /* 64 bits == 20 digits, +1 for NUL */
+ char nuser[12], ngroup[12];
+ char *flags = NULL;
+
+#ifdef __GNUC__
+ /* This outrageous construct just to shut up a GCC warning. */
+ (void) &maxsize;
+#endif
+
+ /*
+ * If list is NULL there are two possibilities: that the parent
+ * directory p has no children, or that fts_children() returned an
+ * error. We ignore the error case since it will be replicated
+ * on the next call to fts_read() on the post-order visit to the
+ * directory p, and will be signalled in traverse().
+ */
+ if (list == NULL)
+ return;
+
+ needstats = f_inode || f_longform || f_size;
+ flen = 0;
+ maxinode = maxnlink = 0;
+ bcfile = 0;
+ maxuser = maxgroup = maxflags = maxlen = 0;
+ btotal = stotal = maxblock = maxsize = 0;
+ maxmajor = maxminor = 0;
+ for (cur = list, entries = 0; cur; cur = cur->fts_link) {
+ uint64_t size;
+ if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
+ warnx("%s: %s",
+ cur->fts_name, strerror(cur->fts_errno));
+ cur->fts_number = NO_PRINT;
+ rval = EXIT_FAILURE;
+ continue;
+ }
+
+ /*
+ * P is NULL if list is the argv list, to which different rules
+ * apply.
+ */
+ if (p == NULL) {
+ /* Directories will be displayed later. */
+ if (cur->fts_info == FTS_D && !f_listdir) {
+ cur->fts_number = NO_PRINT;
+ continue;
+ }
+ } else {
+ /* Only display dot file if -a/-A set. */
+ if (cur->fts_name[0] == '.' && !f_listdot) {
+ cur->fts_number = NO_PRINT;
+ continue;
+ }
+ }
+ if (cur->fts_namelen > maxlen)
+ maxlen = cur->fts_namelen;
+ if (needstats) {
+ sp = cur->fts_statp;
+ if (sp->st_size < 0)
+ size = sp->st_size * -1;
+ else
+ size = sp->st_size;
+ if (sp->st_blocks > maxblock)
+ maxblock = sp->st_blocks;
+ if (sp->st_ino > maxinode)
+ maxinode = sp->st_ino;
+ if (sp->st_nlink > maxnlink)
+ maxnlink = sp->st_nlink;
+ if (size > maxsize)
+ maxsize = size;
+ if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) {
+ bcfile = 1;
+ if (major(sp->st_rdev) > maxmajor)
+ maxmajor = major(sp->st_rdev);
+ if (minor(sp->st_rdev) > maxminor)
+ maxminor = minor(sp->st_rdev);
+ }
+
+ btotal += sp->st_blocks;
+ stotal += size;
+ if (f_longform) {
+ if (f_numericonly ||
+ (user = user_from_uid(sp->st_uid, 0)) ==
+ NULL) {
+ (void)snprintf(nuser, sizeof(nuser),
+ "%u", sp->st_uid);
+ user = nuser;
+ }
+ if (f_numericonly ||
+ (group = group_from_gid(sp->st_gid, 0)) ==
+ NULL) {
+ (void)snprintf(ngroup, sizeof(ngroup),
+ "%u", sp->st_gid);
+ group = ngroup;
+ }
+ if ((ulen = strlen(user)) > maxuser)
+ maxuser = ulen;
+ if ((glen = strlen(group)) > maxgroup)
+ maxgroup = glen;
+#if RTEMS_REMOVED
+ if (f_flags) {
+ flags =
+ flags_to_string(sp->st_flags, "-");
+ if ((flen = strlen(flags)) > maxflags)
+ maxflags = flen;
+ } else
+#endif
+ flen = 0;
+
+ if ((np = malloc(sizeof(NAMES) +
+ ulen + glen + flen + 3)) == NULL)
+ err(exit_jump, EXIT_FAILURE, NULL);
+
+ np->user = &np->data[0];
+ (void)strcpy(np->user, user);
+ np->group = &np->data[ulen + 1];
+ (void)strcpy(np->group, group);
+
+ if (f_flags && flags) {
+ np->flags = &np->data[ulen + glen + 2];
+ (void)strcpy(np->flags, flags);
+ }
+ cur->fts_pointer = np;
+ }
+ }
+ ++entries;
+ }
+
+ if (!entries)
+ return;
+
+ d.list = list;
+ d.entries = entries;
+ d.maxlen = maxlen;
+ if (needstats) {
+ d.btotal = btotal;
+ d.stotal = stotal;
+ if (f_humanize) {
+ d.s_block = 4; /* min buf length for humanize_number */
+ } else {
+ (void)snprintf(buf, sizeof(buf), "%llu",
+ (long long)howmany(maxblock, blocksize));
+ d.s_block = strlen(buf);
+ }
+ d.s_flags = maxflags;
+ d.s_group = maxgroup;
+ (void)snprintf(buf, sizeof(buf), "%u", maxinode);
+ d.s_inode = strlen(buf);
+ (void)snprintf(buf, sizeof(buf), "%u", maxnlink);
+ d.s_nlink = strlen(buf);
+ if (f_humanize) {
+ d.s_size = 4; /* min buf length for humanize_number */
+ } else {
+ (void)snprintf(buf, sizeof(buf), "%llu",
+ (long long)maxsize);
+ d.s_size = strlen(buf);
+ }
+ d.s_user = maxuser;
+ if (bcfile) {
+ (void)snprintf(buf, sizeof(buf), "%u", maxmajor);
+ d.s_major = strlen(buf);
+ (void)snprintf(buf, sizeof(buf), "%u", maxminor);
+ d.s_minor = strlen(buf);
+ if (d.s_major + d.s_minor + 2 > d.s_size)
+ d.s_size = d.s_major + d.s_minor + 2;
+ else if (d.s_size - d.s_minor - 2 > d.s_major)
+ d.s_major = d.s_size - d.s_minor - 2;
+ } else {
+ d.s_major = 0;
+ d.s_minor = 0;
+ }
+ }
+
+ printfcn(globals, &d);
+ output = 1;
+
+ if (f_longform)
+ for (cur = list; cur; cur = cur->fts_link)
+ free(cur->fts_pointer);
+}
+
+/*
+ * Ordering for mastercmp:
+ * If ordering the argv (fts_level = FTS_ROOTLEVEL) return non-directories
+ * as larger than directories. Within either group, use the sort function.
+ * All other levels use the sort function. Error entries remain unsorted.
+ */
+static int
+mastercmp_no_listdir(const FTSENT **a, const FTSENT **b)
+{
+ int a_info, b_info;
+ int l_f_listdir = 0;
+
+ a_info = (*a)->fts_info;
+ if (a_info == FTS_ERR)
+ return (0);
+ b_info = (*b)->fts_info;
+ if (b_info == FTS_ERR)
+ return (0);
+
+ if (a_info == FTS_NS || b_info == FTS_NS) {
+ if (b_info != FTS_NS)
+ return (1);
+ else if (a_info != FTS_NS)
+ return (-1);
+ else
+ return (namecmp(*a, *b));
+ }
+
+ if (a_info != b_info && !l_f_listdir &&
+ (*a)->fts_level == FTS_ROOTLEVEL) {
+ if (a_info == FTS_D)
+ return (1);
+ else if (b_info == FTS_D)
+ return (-1);
+ }
+ return (sortfcn(*a, *b));
+}
+
+static int
+mastercmp_listdir(const FTSENT **a, const FTSENT **b)
+{
+ int a_info, b_info;
+ int l_f_listdir = 1;
+
+ a_info = (*a)->fts_info;
+ if (a_info == FTS_ERR)
+ return (0);
+ b_info = (*b)->fts_info;
+ if (b_info == FTS_ERR)
+ return (0);
+
+ if (a_info == FTS_NS || b_info == FTS_NS) {
+ if (b_info != FTS_NS)
+ return (1);
+ else if (a_info != FTS_NS)
+ return (-1);
+ else
+ return (namecmp(*a, *b));
+ }
+
+ if (a_info != b_info && !l_f_listdir &&
+ (*a)->fts_level == FTS_ROOTLEVEL) {
+ if (a_info == FTS_D)
+ return (1);
+ else if (b_info == FTS_D)
+ return (-1);
+ }
+ return (sortfcn(*a, *b));
+}
+
+rtems_shell_cmd_t rtems_shell_LS_Command = {
+ "ls", /* name */
+ "ls [dir] # list files in the directory", /* usage */
+ "files", /* topic */
+ rtems_shell_main_ls, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mallocinfo.c b/cpukit/libmisc/shell/main_mallocinfo.c
new file mode 100644
index 0000000000..12423c7a73
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mallocinfo.c
@@ -0,0 +1,63 @@
+/*
+ * MALLOC_INFO Shell Command Implmentation
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+
+#include <rtems.h>
+#include <rtems/malloc.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+extern int malloc_info( region_information_block * );
+extern void rtems_shell_print_unified_work_area_message(void);
+
+int rtems_shell_main_malloc_info(
+ int argc,
+ char *argv[]
+)
+{
+ if ( argc == 2 ) {
+ rtems_shell_print_unified_work_area_message();
+
+ if ( !strcmp( argv[1], "info" ) ) {
+ region_information_block info;
+
+ malloc_info( &info );
+ rtems_shell_print_heap_info( "free", &info.Free );
+ rtems_shell_print_heap_info( "used", &info.Used );
+ return 0;
+ } else if ( !strcmp( argv[1], "stats" ) ) {
+ malloc_report_statistics_with_plugin(
+ stdout,
+ (rtems_printk_plugin_t) fprintf
+ );
+ return 0;
+ }
+ }
+ fprintf( stderr, "%s: [info|stats]\n", argv[0] );
+ return -1;
+}
+
+rtems_shell_cmd_t rtems_shell_MALLOC_INFO_Command = {
+ "malloc", /* name */
+ "[info|stats]", /* usage */
+ "mem", /* topic */
+ rtems_shell_main_malloc_info, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
+
diff --git a/cpukit/libmisc/shell/main_mdump.c b/cpukit/libmisc/shell/main_mdump.c
new file mode 100644
index 0000000000..d196711363
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mdump.c
@@ -0,0 +1,96 @@
+/*
+ * MDUMP Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include "internal.h"
+
+int rtems_shell_main_mdump(
+ int argc,
+ char *argv[]
+)
+{
+ unsigned char n;
+ unsigned char m;
+ int max;
+ int res;
+ void *addr = NULL;
+ unsigned char *pb;
+
+ if (argc > 1) {
+ if ( rtems_string_to_pointer(argv[1], &addr, NULL) ) {
+ printf( "Address argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+
+ }
+
+ if (argc > 2) {
+ if ( rtems_string_to_int(argv[1], &max, NULL, 0) ) {
+ printf( "Length argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+ if (max <= 0) {
+ max = 1; /* print 1 item if 0 or neg. */
+ res = 0;
+ } else {
+ max--;
+ res = max & 0xf;/* num bytes in last row */
+ max >>= 4; /* div by 16 */
+ max++; /* num of rows to print */
+ if (max > 20) { /* limit to 20 */
+ max = 20;
+ res = 0xf; /* 16 bytes print in last row */
+ }
+ }
+ } else {
+ max = 20;
+ res = 0xf;
+ }
+
+ pb = addr;
+ for (m=0; m<max; m++) {
+ printf("%10p ", pb);
+ for (n=0;n<=(m==(max-1)?res:0xf);n++)
+ printf("%02X%c",pb[n],n==7?'-':' ');
+ for (;n<=0xf;n++)
+ printf(" %c",n==7?'-':' ');
+ for (n=0;n<=(m==(max-1)?res:0xf);n++) {
+ printf("%c", isprint(pb[n]) ? pb[n] : '.');
+ }
+ printf("\n");
+ pb += 16;
+ }
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_MDUMP_Command = {
+ "mdump", /* name */
+ "mdump [address [length]]", /* usage */
+ "mem", /* topic */
+ rtems_shell_main_mdump, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
+
diff --git a/cpukit/libmisc/shell/main_medit.c b/cpukit/libmisc/shell/main_medit.c
new file mode 100644
index 0000000000..7905fbe689
--- /dev/null
+++ b/cpukit/libmisc/shell/main_medit.c
@@ -0,0 +1,79 @@
+/*
+ * MEDIT Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include "internal.h"
+
+extern int rtems_shell_main_mdump(int, char *);
+
+int rtems_shell_main_medit(
+ int argc,
+ char *argv[]
+)
+{
+ unsigned char *pb;
+ void *tmpp;
+ int n;
+ int i;
+
+ if ( argc < 3 ) {
+ fprintf(stderr,"%s: too few arguments\n", argv[0]);
+ return -1;
+ }
+
+ /*
+ * Convert arguments into numbers
+ */
+ if ( rtems_string_to_pointer(argv[1], &tmpp, NULL) ) {
+ printf( "Address argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+ pb = tmpp;
+
+ /*
+ * Now edit the memory
+ */
+ n = 0;
+ for (i=2 ; i<=argc ; i++) {
+ unsigned char tmpc;
+
+ if ( rtems_string_to_unsigned_char(argv[i], &tmpc, NULL, 0) ) {
+ printf( "Value (%s) is not a number\n", argv[i] );
+ continue;
+ }
+
+ pb[n++] = tmpc;
+ }
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_MEDIT_Command = {
+ "medit", /* name */
+ "medit address value1 [value2 ...]", /* usage */
+ "mem", /* topic */
+ rtems_shell_main_medit, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mfill.c b/cpukit/libmisc/shell/main_mfill.c
new file mode 100644
index 0000000000..ecbaec4878
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mfill.c
@@ -0,0 +1,77 @@
+/*
+ * MFILL Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include "internal.h"
+
+int rtems_shell_main_mfill(
+ int argc,
+ char *argv[]
+)
+{
+ unsigned long tmp;
+ void *addr;
+ size_t size;
+ unsigned char value;
+
+ if ( argc != 4 ) {
+ fprintf(stderr,"%s: too few arguments\n", argv[0]);
+ return -1;
+ }
+
+ /*
+ * Convert arguments into numbers
+ */
+ if ( rtems_string_to_pointer(argv[1], &addr, NULL) ) {
+ printf( "Address argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+
+ if ( rtems_string_to_unsigned_long(argv[2], &tmp, NULL, 0) ) {
+ printf( "Size argument (%s) is not a number\n", argv[2] );
+ return -1;
+ }
+ size = (size_t) tmp;
+
+ if ( rtems_string_to_unsigned_char(argv[3], &value, NULL, 0) ) {
+ printf( "Value argument (%s) is not a number\n", argv[3] );
+ return -1;
+ }
+
+ /*
+ * Now fill the memory.
+ */
+ memset(addr, size, value);
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_MFILL_Command = {
+ "mfill", /* name */
+ "mfill address size value", /* usage */
+ "mem", /* topic */
+ rtems_shell_main_mfill, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mkdir.c b/cpukit/libmisc/shell/main_mkdir.c
new file mode 100644
index 0000000000..e191818923
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mkdir.c
@@ -0,0 +1,55 @@
+/*
+ * MKDIR Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_mkdir(
+ int argc,
+ char *argv[]
+)
+{
+ char *dir;
+ int n;
+
+ n = 1;
+ while (n<argc) {
+ dir = argv[n++];
+ if (mkdir(dir,S_IRWXU|S_IRWXG|S_IRWXO)) {
+ fprintf(stderr, "mkdir '%s' failed:%s\n", dir, strerror(errno));
+ }
+ }
+ return errno;
+}
+
+rtems_shell_cmd_t rtems_shell_MKDIR_Command = {
+ "mkdir", /* name */
+ "mkdir dir # make a directory", /* usage */
+ "files", /* topic */
+ rtems_shell_main_mkdir, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mknod.c b/cpukit/libmisc/shell/main_mknod.c
new file mode 100644
index 0000000000..e1ebb2a162
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mknod.c
@@ -0,0 +1,463 @@
+/* $NetBSD: mknod.c,v 1.39 2009/02/13 01:37:23 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#if 0
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1998\
+ The NetBSD Foundation, Inc. All rights reserved.");
+__RCSID("$NetBSD: mknod.c,v 1.39 2009/02/13 01:37:23 lukem Exp $");
+#endif /* not lint */
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#if !HAVE_NBTOOL_CONFIG_H && defined(KERN_DRIVERS)
+#include <sys/sysctl.h>
+#endif
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "mknod-pack_dev.h"
+
+#include <setjmp.h>
+
+typedef struct {
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_mknod_globals;
+
+#define exit_jump &(globals->exit_jmp)
+
+#define exit(ec) rtems_shell_mknod_exit(globals, ec)
+
+static int gid_name(const char *, gid_t *);
+static portdev_t callPack(rtems_shell_mknod_globals* globals,
+ pack_t *, int, u_long *);
+
+static int main_mknod(rtems_shell_mknod_globals*, int, char *[]);
+static void usage(rtems_shell_mknod_globals* );
+
+static void
+rtems_shell_mknod_exit (rtems_shell_mknod_globals* globals, int code)
+{
+ globals->exit_code = code;
+ longjmp (globals->exit_jmp, 1);
+}
+
+#include "mknod-pack_dev.c"
+
+int
+rtems_shell_main_mknod(int argc, char *argv[])
+{
+ rtems_shell_mknod_globals mknod_globals;
+ rtems_shell_mknod_globals* globals = &mknod_globals;
+ memset (globals, 0, sizeof (mknod_globals));
+ mknod_globals.exit_code = 1;
+ if (setjmp (mknod_globals.exit_jmp) == 0)
+ return main_mknod (globals, argc, argv);
+ return mknod_globals.exit_code;
+}
+
+#define getprogname() "mknod"
+
+#ifdef KERN_DRIVERS
+#error invalid for RTEMS
+static struct kinfo_drivers *kern_drivers;
+static int num_drivers;
+
+static void get_device_info(void);
+static void print_device_info(char **);
+static int major_from_name(const char *, mode_t);
+#endif
+
+#define MAXARGS 3 /* 3 for bsdos, 2 for rest */
+
+int
+main_mknod(rtems_shell_mknod_globals* globals, int argc, char **argv)
+{
+ char *name, *p;
+ mode_t mode;
+ portdev_t dev;
+ pack_t *pack;
+ u_long numbers[MAXARGS];
+ int n, ch, fifo, hasformat;
+ int r_flag = 0; /* force: delete existing entry */
+#ifdef KERN_DRIVERS
+ int l_flag = 0; /* list device names and numbers */
+ int major;
+#endif
+#if RTEMS_REMOVED
+ void *modes = 0;
+#endif
+ uid_t uid = -1;
+ gid_t gid = -1;
+ int rval;
+
+ struct getopt_data getopt_reent;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+ dev = 0;
+ fifo = hasformat = 0;
+ pack = pack_native;
+
+#ifdef KERN_DRIVERS
+ while ((ch = getopt(argc, argv, "lrRF:g:m:u:")) != -1) {
+#else
+ while ((ch = getopt_r(argc, argv, "rRF:g:m:u:", &getopt_reent)) != -1) {
+#endif
+ switch (ch) {
+
+#ifdef KERN_DRIVERS
+ case 'l':
+ l_flag = 1;
+ break;
+#endif
+
+ case 'r':
+ r_flag = 1;
+ break;
+
+ case 'R':
+ r_flag = 2;
+ break;
+
+ case 'F':
+ pack = pack_find(getopt_reent.optarg);
+ if (pack == NULL)
+ errx(exit_jump, 1, "invalid format: %s", getopt_reent.optarg);
+ hasformat++;
+ break;
+
+ case 'g':
+ if (getopt_reent.optarg[0] == '#') {
+ gid = strtol(getopt_reent.optarg + 1, &p, 10);
+ if (*p == 0)
+ break;
+ }
+ if (gid_name(getopt_reent.optarg, &gid) == 0)
+ break;
+ gid = strtol(getopt_reent.optarg, &p, 10);
+ if (*p == 0)
+ break;
+ errx(exit_jump, 1, "%s: invalid group name", getopt_reent.optarg);
+
+ case 'm':
+#if RTEMS_REMOVED
+ modes = setmode(getopt_reent.optarg);
+ if (modes == NULL)
+#endif
+ err(exit_jump, 1, "Cannot set file mode `%s'", getopt_reent.optarg);
+ break;
+
+ case 'u':
+ if (getopt_reent.optarg[0] == '#') {
+ uid = strtol(getopt_reent.optarg + 1, &p, 10);
+ if (*p == 0)
+ break;
+ }
+#if RTEMS_REMOVED
+ if (uid_from_user(getopt_reent.optarg, &uid) == 0)
+ break;
+#endif
+ uid = strtol(getopt_reent.optarg, &p, 10);
+ if (*p == 0)
+ break;
+ errx(exit_jump, 1, "%s: invalid user name", getopt_reent.optarg);
+
+ default:
+ case '?':
+ usage(globals);
+ }
+ }
+ argc -= getopt_reent.optind;
+ argv += getopt_reent.optind;
+
+#ifdef KERN_DRIVERS
+ if (l_flag) {
+ print_device_info(argv);
+ return 0;
+ }
+#endif
+
+ if (argc < 2 || argc > 10)
+ usage(globals);
+
+ name = *argv;
+ argc--;
+ argv++;
+
+ umask(mode = umask(0));
+ mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) & ~mode;
+
+ if (argv[0][1] != '\0')
+ goto badtype;
+ switch (*argv[0]) {
+ case 'c':
+ mode |= S_IFCHR;
+ break;
+
+ case 'b':
+ mode |= S_IFBLK;
+ break;
+
+ case 'p':
+ if (hasformat)
+ errx(exit_jump, 1, "format is meaningless for fifos");
+ mode |= S_IFIFO;
+ fifo = 1;
+ break;
+
+ default:
+ badtype:
+ errx(exit_jump, 1, "node type must be 'b', 'c' or 'p'.");
+ }
+ argc--;
+ argv++;
+
+ if (fifo) {
+ if (argc != 0)
+ usage(globals);
+ } else {
+ if (argc < 1 || argc > MAXARGS)
+ usage(globals);
+ }
+
+ for (n = 0; n < argc; n++) {
+ errno = 0;
+ numbers[n] = strtoul(argv[n], &p, 0);
+ if (*p == 0 && errno == 0)
+ continue;
+#ifdef KERN_DRIVERS
+ if (n == 0) {
+ major = major_from_name(argv[0], mode);
+ if (major != -1) {
+ numbers[0] = major;
+ continue;
+ }
+ if (!isdigit(*(unsigned char *)argv[0]))
+ errx(1, "unknown driver: %s", argv[0]);
+ }
+#endif
+ errx(exit_jump, 1, "invalid number: %s", argv[n]);
+ }
+
+ switch (argc) {
+ case 0:
+ dev = 0;
+ break;
+
+ case 1:
+ dev = numbers[0];
+ break;
+
+ default:
+ dev = callPack(globals, pack, argc, numbers);
+ break;
+ }
+
+#if RTEMS_REMOVED
+ if (modes != NULL)
+ mode = getmode(modes, mode);
+#endif
+ umask(0);
+ rval = fifo ? mkfifo(name, mode) : mknod(name, mode, dev);
+ if (rval < 0 && errno == EEXIST && r_flag) {
+ struct stat sb;
+ if (lstat(name, &sb) != 0 || (!fifo && sb.st_rdev != dev))
+ sb.st_mode = 0;
+
+ if ((sb.st_mode & S_IFMT) == (mode & S_IFMT)) {
+ if (r_flag == 1)
+ /* Ignore permissions and user/group */
+ return 0;
+ if (sb.st_mode != mode)
+ rval = chmod(name, mode);
+ else
+ rval = 0;
+ } else {
+ unlink(name);
+ rval = fifo ? mkfifo(name, mode)
+ : mknod(name, mode, dev);
+ }
+ }
+ if (rval < 0)
+ err(exit_jump, 1, "%s", name);
+ if ((uid != (uid_t)-1 || gid != (uid_t)-1) && chown(name, uid, gid) == -1)
+ /* XXX Should we unlink the files here? */
+ warn("%s: uid/gid not changed", name);
+
+ return 0;
+}
+
+static void
+usage(rtems_shell_mknod_globals* globals)
+{
+ const char *progname = getprogname();
+
+ (void)fprintf(stderr,
+ "usage: %s [-rR] [-F format] [-m mode] [-u user] [-g group]\n",
+ progname);
+ (void)fprintf(stderr,
+#ifdef KERN_DRIVERS
+ " [ name [b | c] [major | driver] minor\n"
+#else
+ " [ name [b | c] major minor\n"
+#endif
+ " | name [b | c] major unit subunit\n"
+ " | name [b | c] number\n"
+ " | name p ]\n");
+#ifdef KERN_DRIVERS
+ (void)fprintf(stderr, " %s -l [driver] ...\n", progname);
+#endif
+ exit(1);
+}
+
+static int
+gid_name(const char *name, gid_t *gid)
+{
+ struct group *g;
+
+ g = getgrnam(name);
+ if (!g)
+ return -1;
+ *gid = g->gr_gid;
+ return 0;
+}
+
+static portdev_t
+callPack(rtems_shell_mknod_globals* globals, pack_t *f, int n, u_long *numbers)
+{
+ portdev_t d;
+ const char *error = NULL;
+
+ d = (*f)(n, numbers, &error);
+ if (error != NULL)
+ errx(exit_jump, 1, "%s", error);
+ return d;
+}
+
+#ifdef KERN_DRIVERS
+static void
+get_device_info(void)
+{
+ static int mib[2] = {CTL_KERN, KERN_DRIVERS};
+ size_t len;
+
+ if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0)
+ err(1, "kern.drivers" );
+ kern_drivers = malloc(len);
+ if (kern_drivers == NULL)
+ err(1, "malloc");
+ if (sysctl(mib, 2, kern_drivers, &len, NULL, 0) != 0)
+ err(1, "kern.drivers" );
+
+ num_drivers = len / sizeof *kern_drivers;
+}
+
+static void
+print_device_info(char **names)
+{
+ int i;
+ struct kinfo_drivers *kd;
+
+ if (kern_drivers == NULL)
+ get_device_info();
+
+ do {
+ kd = kern_drivers;
+ for (i = 0; i < num_drivers; kd++, i++) {
+ if (*names && strcmp(*names, kd->d_name))
+ continue;
+ printf("%s", kd->d_name);
+ if (kd->d_cmajor != -1)
+ printf(" character major %d", kd->d_cmajor);
+ if (kd->d_bmajor != -1)
+ printf(" block major %d", kd->d_bmajor);
+ printf("\n");
+ }
+ } while (*names && *++names);
+}
+
+static int
+major_from_name(const char *name, mode_t mode)
+{
+ int i;
+ struct kinfo_drivers *kd;
+
+ if (kern_drivers == NULL)
+ get_device_info();
+
+ kd = kern_drivers;
+ for (i = 0; i < num_drivers; kd++, i++) {
+ if (strcmp(name, kd->d_name))
+ continue;
+ if (S_ISCHR(mode))
+ return kd->d_cmajor;
+ return kd->d_bmajor;
+ }
+ return -1;
+}
+#endif
+
+rtems_shell_cmd_t rtems_shell_MKNOD_Command = {
+ "mknod", /* name */
+ "mknod mknod [-rR] [-F fmt] [-m mode] name [c | b] minor", /* usage */
+ "files", /* topic */
+ rtems_shell_main_mknod, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mkrfs.c b/cpukit/libmisc/shell/main_mkrfs.c
new file mode 100644
index 0000000000..726b575b03
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mkrfs.c
@@ -0,0 +1,35 @@
+/*
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include <rtems/shellconfig.h>
+#include <rtems/rtems-rfs-shell.h>
+#include <rtems/fsmount.h>
+#include "internal.h"
+
+#define OPTIONS "[-v] [-s blksz] [-b grpblk] [-i grpinode] [-I] [-o %inode]"
+
+rtems_shell_cmd_t rtems_shell_MKRFS_Command = {
+ "mkrfs", /* name */
+ "mkrfs " OPTIONS " dev", /* usage */
+ "files", /* topic */
+ rtems_shell_rfs_format, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mmove.c b/cpukit/libmisc/shell/main_mmove.c
new file mode 100644
index 0000000000..30c6629547
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mmove.c
@@ -0,0 +1,79 @@
+/*
+ * MMOVE Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include "internal.h"
+
+extern int rtems_shell_main_mdump(int, char *);
+
+int rtems_shell_main_mmove(
+ int argc,
+ char *argv[]
+)
+{
+ unsigned long tmp;
+ void *src;
+ void *dst;
+ size_t length;
+
+ if ( argc < 4 ) {
+ fprintf(stderr,"%s: too few arguments\n", argv[0]);
+ return -1;
+ }
+
+ /*
+ * Convert arguments into numbers
+ */
+ if ( rtems_string_to_pointer(argv[1], &dst, NULL) ) {
+ printf( "Destination argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+
+ if ( rtems_string_to_pointer(argv[2], &src, NULL) ) {
+ printf( "Source argument (%s) is not a number\n", argv[2] );
+ return -1;
+ }
+
+ if ( rtems_string_to_unsigned_long(argv[3], &tmp, NULL, 0) ) {
+ printf( "Length argument (%s) is not a number\n", argv[3] );
+ return -1;
+ }
+ length = (size_t) tmp;
+
+ /*
+ * Now copy the memory.
+ */
+ memcpy(dst, src, length);
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_MMOVE_Command = {
+ "mmove", /* name */
+ "mmove dst src length", /* usage */
+ "mem", /* topic */
+ rtems_shell_main_mmove, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mount.c b/cpukit/libmisc/shell/main_mount.c
new file mode 100644
index 0000000000..b192a1668d
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mount.c
@@ -0,0 +1,133 @@
+/*
+ * Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#include <rtems/libio.h>
+#include "internal.h"
+
+static bool print_filesystem(const rtems_filesystem_table_t *entry, void *arg)
+{
+ printf("%s ", entry->type);
+
+ return false;
+}
+
+int rtems_shell_main_mount(
+ int argc,
+ char *argv[]
+)
+{
+ rtems_filesystem_options_t options = RTEMS_FILESYSTEM_READ_WRITE;
+ char* type = NULL;
+ char* source = NULL;
+ char* target = NULL;
+ char* fsoptions = NULL;
+ int arg;
+
+ for (arg = 1; arg < argc; arg++) {
+ if (argv[arg][0] == '-') {
+ if (argv[arg][1] == 't') {
+ arg++;
+ if (arg == argc) {
+ fprintf(
+ stderr,
+ "%s: -t needs a type of file-system;; see -L.\n",
+ argv[0]
+ );
+ return 1;
+ }
+ type = argv[arg];
+ } else if (argv[arg][1] == 'r') {
+ options = RTEMS_FILESYSTEM_READ_ONLY;
+ } else if (argv[arg][1] == 'L') {
+ printf ("File systems: ");
+ rtems_filesystem_iterate(print_filesystem, NULL);
+ printf ("\n");
+ return 0;
+ } else if (argv[arg][1] == 'o') {
+ arg++;
+ if (arg == argc) {
+ fprintf(
+ stderr,
+ "%s: -o needs a list if filesystem options.\n",
+ argv[0]
+ );
+ return 1;
+ }
+ fsoptions = argv[arg];
+ } else {
+ fprintf (stderr, "unknown option: %s\n", argv[arg]);
+ return 1;
+ }
+ } else {
+ if (!source)
+ source = argv[arg];
+ else if (!target)
+ target = argv[arg];
+ else {
+ fprintf (
+ stderr, "mount: source and mount only require: %s\n", argv[arg]);
+ return 1;
+ }
+ }
+ }
+
+ if (!type) {
+ fprintf (stderr, "mount: no file-system; see the -L option\n");
+ return 1;
+ }
+
+ if (!source) {
+ fprintf (stderr, "mount: no source\n");
+ return 1;
+ }
+
+ if (!target) {
+ fprintf (stderr, "mount: no mount point\n");
+ return 1;
+ }
+
+ /*
+ * Mount the disk.
+ */
+
+ if (mount (source, target, type, options, fsoptions) < 0) {
+ fprintf (stderr, "error: %s\n", strerror(errno));
+ return 1;
+ }
+
+ printf ("mounted %s -> %s\n", source, target);
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_MOUNT_Command = {
+ "mount", /* name */
+ "mount [-t type] [-r] [-L] source target", /* usage */
+ "files", /* topic */
+ rtems_shell_main_mount, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mount_nfs.c b/cpukit/libmisc/shell/main_mount_nfs.c
new file mode 100644
index 0000000000..121d0ca6c2
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mount_nfs.c
@@ -0,0 +1,70 @@
+/*
+ * Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+#include <librtemsNfs.h>
+
+static int
+rtems_shell_nfs_mounter (
+ const char* device,
+ const char* mntpoint,
+ rtems_shell_filesystems_t* fs __attribute__((unused)),
+ rtems_filesystem_options_t options __attribute__((unused)))
+{
+ char* uidhost;
+ char* path;
+ int ret;
+
+ if (strchr (device, ':') == NULL) {
+ fprintf (stderr, "error: nfs mount device is [uid.gid@]host:path\n");
+ return -1;
+ }
+
+ if (rpcUdpInit () < 0) {
+ fprintf (stderr, "error: initialising RPC\n");
+ return -1;
+ }
+
+ nfsInit (0, 0);
+
+ uidhost = strdup (device);
+ path = strchr (uidhost, ':');
+ *path = '\0';
+ path++;
+
+ ret = nfsMount(uidhost, path, (char*) mntpoint);
+
+ free (uidhost);
+
+ return ret;
+}
+
+rtems_shell_filesystems_t rtems_shell_Mount_NFS = {
+ name: "nfs",
+ driver_needed: 1,
+ fs_ops: NULL,
+ mounter: rtems_shell_nfs_mounter
+};
diff --git a/cpukit/libmisc/shell/main_msdosfmt.c b/cpukit/libmisc/shell/main_msdosfmt.c
new file mode 100644
index 0000000000..c682e879eb
--- /dev/null
+++ b/cpukit/libmisc/shell/main_msdosfmt.c
@@ -0,0 +1,185 @@
+/*
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include <rtems/shellconfig.h>
+#include <rtems/dosfs.h>
+#include <rtems/fsmount.h>
+#include "internal.h"
+
+int rtems_shell_main_msdos_format(
+ int argc,
+ char *argv[]
+)
+{
+ msdos_format_request_param_t rqdata = {
+ OEMName: "RTEMS",
+ VolLabel: "RTEMSDisk",
+ sectors_per_cluster: 0,
+ fat_num: 0,
+ files_per_root_dir: 0,
+ fattype: MSDOS_FMT_FATANY,
+ media: 0,
+ quick_format: TRUE,
+ cluster_align: 0,
+ info_level: 0
+ };
+
+ unsigned long tmp;
+ const char* driver = NULL;
+ int arg;
+
+ for (arg = 1; arg < argc; arg++) {
+ if (argv[arg][0] == '-') {
+ switch (argv[arg][1]) {
+ case 'V':
+ arg++;
+ if (arg == argc) {
+ fprintf (stderr, "error: no volume label.\n");
+ return 1;
+ }
+ rqdata.VolLabel = argv[arg];
+ break;
+
+ case 's':
+ arg++;
+ if (arg == argc) {
+ fprintf (stderr, "error: sectors per cluster count.\n");
+ return 1;
+ }
+
+ if ( rtems_string_to_unsigned_long(argv[arg], &tmp, NULL, 0) ) {
+ printf(
+ "sector per cluster argument (%s) is not a number\n",
+ argv[arg]
+ );
+ return -1;
+ }
+
+ rqdata.sectors_per_cluster = (uint32_t) tmp;
+ break;
+
+ case 'r':
+ arg++;
+ if (arg == argc) {
+ fprintf (stderr, "error: no root directory size.\n");
+ return 1;
+ }
+
+ if ( rtems_string_to_unsigned_long(argv[arg], &tmp, NULL, 0) ) {
+ printf(
+ "root directory size argument (%s) is not a number\n",
+ argv[arg]
+ );
+ return -1;
+ }
+
+ rqdata.files_per_root_dir = (uint32_t) tmp;
+ break;
+
+ case 't':
+ arg++;
+ if (arg == argc) {
+ fprintf (stderr, "error: no FAT type.\n");
+ return 1;
+ }
+
+ if (strcmp (argv[arg], "any") == 0)
+ rqdata.fattype = MSDOS_FMT_FATANY;
+ else if (strcmp (argv[arg], "12") == 0)
+ rqdata.fattype = MSDOS_FMT_FAT12;
+ else if (strcmp (argv[arg], "16") == 0)
+ rqdata.fattype = MSDOS_FMT_FAT16;
+ else if (strcmp (argv[arg], "32") == 0)
+ rqdata.fattype = MSDOS_FMT_FAT32;
+ else {
+ fprintf (stderr, "error: invalid type, can any, 12, 16, or 32\n");
+ return 1;
+ }
+ break;
+
+ case 'v':
+ rqdata.info_level++;
+ break;
+
+ default:
+ fprintf (stderr, "error: invalid option: %s\n", argv[arg]);
+ return 1;
+
+ }
+ } else {
+ if (!driver)
+ driver = argv[arg];
+ else {
+ fprintf (stderr, "error: only one driver allowed: %s\n", argv[arg]);
+ return 1;
+ }
+ }
+ }
+
+ if (!driver) {
+ fprintf (stderr, "error: no driver\n");
+ return 1;
+ }
+
+ printf ("msdos format: %s\n", driver);
+
+ if (rqdata.info_level)
+ {
+ printf (" %-20s: %s\n", "OEMName", "RTEMS");
+ printf (" %-20s: %s\n", "VolLabel", "RTEMSDisk");
+ printf (" %-20s: %" PRIu32 "\n", "sectors per cluster", rqdata.sectors_per_cluster);
+ printf (" %-20s: %" PRIu32 "\n", "fats", rqdata.fat_num);
+ printf (" %-20s: %" PRIu32 "\n", "files per root dir", rqdata.files_per_root_dir);
+ printf (" %-20s: %i\n", "fat type", rqdata.fattype);
+ printf (" %-20s: %d\n", "media", rqdata.media);
+ printf (" %-20s: %d\n", "quick_format", rqdata.quick_format);
+ printf (" %-20s: %" PRIu32 "\n", "cluster align", rqdata.cluster_align);
+ }
+
+ if (msdos_format (driver, &rqdata) < 0) {
+ fprintf (stderr, "error: format failed: %s\n", strerror (errno));
+ return 1;
+ }
+
+ printf ("msdos format successful\n");
+
+ return 0;
+}
+
+#define OPTIONS "[-v label] [-r size] [-t any/12/16/32]"
+
+rtems_shell_cmd_t rtems_shell_MSDOSFMT_Command = {
+ "mkdos", /* name */
+ "mkdos " OPTIONS " path # format disk", /* usage */
+ "files", /* topic */
+ rtems_shell_main_msdos_format, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
+
+rtems_shell_cmd_t rtems_shell_MSDOSFMT_Alias = {
+ "msdosfmt", /* name */
+ NULL, /* usage */
+ "files", /* topic */
+ NULL, /* command */
+ &rtems_shell_MSDOSFMT_Command, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mv.c b/cpukit/libmisc/shell/main_mv.c
new file mode 100644
index 0000000000..644900bc17
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mv.c
@@ -0,0 +1,491 @@
+/* $NetBSD: mv.c,v 1.41 2008/07/20 00:52:40 lukem Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ken Smith of The State University of New York at Buffalo.
+ *
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if 0
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mv.c 8.2 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: mv.c,v 1.41 2008/07/20 00:52:40 lukem Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <locale.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pathnames-mv.h"
+
+/* RTEMS specific changes */
+typedef struct {
+ int fflg, iflg, vflg;
+ int stdin_ok;
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_mv_globals;
+
+int copy(char *, char *);
+int do_move(char *, char *);
+int fastcopy(char *, char *, struct stat *);
+void usage(void);
+int main(int, char *[]);
+
+#define fflg globals->fflg
+#define iflg globals->iflg
+#define vflg globals->vflg
+#define stdin_ok globals->stdin_ok
+#define exit_jump &(globals->exit_jmp)
+
+#include <setjmp.h>
+
+#define exit(ec) rtems_shell_mv_exit(globals, ec)
+
+void
+rtems_shell_mv_exit (rtems_shell_mv_globals* globals, int code)
+{
+ globals->exit_code = code;
+ longjmp (globals->exit_jmp, 1);
+}
+
+void strmode(mode_t mode, char *p);
+const char *user_from_uid(uid_t uid, int nouser);
+char *group_from_gid(gid_t gid, int nogroup);
+
+static int main_mv(rtems_shell_mv_globals* globals, int argc, char *argv[]);
+
+int rtems_shell_main_cp(int argc, char *argv[]);
+int rtems_shell_main_rm(int argc, char *argv[]);
+
+int
+rtems_shell_main_mv(int argc, char *argv[])
+{
+ rtems_shell_mv_globals mv_globals;
+ memset (&mv_globals, 0, sizeof (mv_globals));
+ mv_globals.exit_code = 1;
+ if (setjmp (mv_globals.exit_jmp) == 0)
+ return main_mv (&mv_globals, argc, argv);
+ return mv_globals.exit_code;
+}
+
+#define do_move(a1, a2) do_move_mv(globals, a1, a2)
+#define fastcopy(a1, a2, a3) fastcopy_mv(globals, a1, a2, a3)
+#define copy(a1, a2) copy_mv(globals, a1, a2)
+#define usage() usage_mv(globals)
+
+static int do_move_mv(rtems_shell_mv_globals* globals, char *from, char *to);
+static int fastcopy_mv(rtems_shell_mv_globals* globals,
+ char *from, char *to, struct stat *sbp);
+static int copy_mv(rtems_shell_mv_globals* globals, char *from, char *to);
+static void usage_mv(rtems_shell_mv_globals* globals);
+
+/* RTEMS changes */
+
+int
+main_mv(rtems_shell_mv_globals* globals, int argc, char *argv[])
+{
+ int ch, len, rval;
+ char *p, *endp;
+ struct stat sb;
+ char path[MAXPATHLEN + 1];
+ size_t baselen;
+
+ struct getopt_data getopt_reent;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+/* setprogname(argv[0]); */
+
+ (void)setlocale(LC_ALL, "");
+
+ while ((ch = getopt_r(argc, argv, "ifv", &getopt_reent)) != -1)
+ switch (ch) {
+ case 'i':
+ fflg = 0;
+ iflg = 1;
+ break;
+ case 'f':
+ iflg = 0;
+ fflg = 1;
+ break;
+ case 'v':
+ vflg = 1;
+ break;
+ default:
+ usage();
+ }
+ argc -= getopt_reent.optind;
+ argv += getopt_reent.optind;
+
+ if (argc < 2)
+ usage();
+
+ stdin_ok = isatty(STDIN_FILENO);
+
+ /*
+ * If the stat on the target fails or the target isn't a directory,
+ * try the move. More than 2 arguments is an error in this case.
+ */
+ if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) {
+ if (argc > 2)
+ usage();
+ exit(do_move(argv[0], argv[1]));
+ }
+
+ /* It's a directory, move each file into it. */
+ baselen = strlcpy(path, argv[argc - 1], sizeof(path));
+ if (baselen >= sizeof(path))
+ errx(exit_jump, 1, "%s: destination pathname too long", argv[argc - 1]);
+ endp = &path[baselen];
+ if (!baselen || *(endp - 1) != '/') {
+ *endp++ = '/';
+ ++baselen;
+ }
+ for (rval = 0; --argc; ++argv) {
+ p = *argv + strlen(*argv) - 1;
+ while (*p == '/' && p != *argv)
+ *p-- = '\0';
+ if ((p = strrchr(*argv, '/')) == NULL)
+ p = *argv;
+ else
+ ++p;
+
+ if ((baselen + (len = strlen(p))) >= MAXPATHLEN) {
+ warnx("%s: destination pathname too long", *argv);
+ rval = 1;
+ } else {
+ memmove(endp, p, len + 1);
+ if (do_move(*argv, path))
+ rval = 1;
+ }
+ }
+ return rval;
+}
+
+int
+do_move_mv(rtems_shell_mv_globals* globals, char *from, char *to)
+{
+ struct stat sb;
+ char modep[15];
+
+ /*
+ * (1) If the destination path exists, the -f option is not specified
+ * and either of the following conditions are true:
+ *
+ * (a) The permissions of the destination path do not permit
+ * writing and the standard input is a terminal.
+ * (b) The -i option is specified.
+ *
+ * the mv utility shall write a prompt to standard error and
+ * read a line from standard input. If the response is not
+ * affirmative, mv shall do nothing more with the current
+ * source file...
+ */
+ if (!fflg && !access(to, F_OK)) {
+ int ask = 1;
+ int ch;
+
+ if (iflg) {
+ if (access(from, F_OK)) {
+ warn("rename %s", from);
+ return (1);
+ }
+ (void)fprintf(stderr, "overwrite %s? ", to);
+ } else if (stdin_ok && access(to, W_OK) && !stat(to, &sb)) {
+ if (access(from, F_OK)) {
+ warn("rename %s", from);
+ return (1);
+ }
+ strmode(sb.st_mode, modep);
+ (void)fprintf(stderr, "override %s%s%s/%s for %s? ",
+ modep + 1, modep[9] == ' ' ? "" : " ",
+ user_from_uid(sb.st_uid, 0),
+ group_from_gid(sb.st_gid, 0), to);
+ } else
+ ask = 0;
+ if (ask) {
+ if ((ch = getchar()) != EOF && ch != '\n') {
+ int ch2;
+ while ((ch2 = getchar()) != EOF && ch2 != '\n')
+ continue;
+ }
+ if (ch != 'y' && ch != 'Y')
+ return (0);
+ }
+ }
+
+ /*
+ * (2) If rename() succeeds, mv shall do nothing more with the
+ * current source file. If it fails for any other reason than
+ * EXDEV, mv shall write a diagnostic message to the standard
+ * error and do nothing more with the current source file.
+ *
+ * (3) If the destination path exists, and it is a file of type
+ * directory and source_file is not a file of type directory,
+ * or it is a file not of type directory, and source file is
+ * a file of type directory, mv shall write a diagnostic
+ * message to standard error, and do nothing more with the
+ * current source file...
+ */
+ if (!rename(from, to)) {
+ if (vflg)
+ printf("%s -> %s\n", from, to);
+ return (0);
+ }
+
+ if (errno != EXDEV) {
+ warn("rename %s to %s", from, to);
+ return (1);
+ }
+
+ /*
+ * (4) If the destination path exists, mv shall attempt to remove it.
+ * If this fails for any reason, mv shall write a diagnostic
+ * message to the standard error and do nothing more with the
+ * current source file...
+ */
+ if (!lstat(to, &sb)) {
+ if ((S_ISDIR(sb.st_mode)) ? rmdir(to) : unlink(to)) {
+ warn("can't remove %s", to);
+ return (1);
+ }
+ }
+
+ /*
+ * (5) The file hierarchy rooted in source_file shall be duplicated
+ * as a file hierarchy rooted in the destination path...
+ */
+ if (lstat(from, &sb)) {
+ warn("%s", from);
+ return (1);
+ }
+
+ return (S_ISREG(sb.st_mode) ?
+ fastcopy(from, to, &sb) : copy(from, to));
+}
+
+int
+fastcopy_mv(rtems_shell_mv_globals* globals, char *from, char *to, struct stat *sbp)
+{
+ struct timeval tval[2];
+ uint32_t blen;
+ static char *bp;
+ int nread, from_fd, to_fd;
+
+ blen = 0;
+
+ if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
+ warn("%s", from);
+ return (1);
+ }
+ if ((to_fd =
+ open(to, O_CREAT | O_TRUNC | O_WRONLY, sbp->st_mode)) < 0) {
+ warn("%s", to);
+ (void)close(from_fd);
+ return (1);
+ }
+ if (!blen && !(bp = malloc(blen = sbp->st_blksize))) {
+ warn(NULL);
+ blen = 0;
+ (void)close(from_fd);
+ (void)close(to_fd);
+ return (1);
+ }
+ while ((nread = read(from_fd, bp, blen)) > 0)
+ if (write(to_fd, bp, nread) != nread) {
+ warn("%s", to);
+ goto err;
+ }
+ if (nread < 0) {
+ warn("%s", from);
+err: if (unlink(to))
+ warn("%s: remove", to);
+ (void)free(bp);
+ (void)close(from_fd);
+ (void)close(to_fd);
+ return (1);
+ }
+
+ (void)free(bp);
+ (void)close(from_fd);
+#ifdef xBSD4_4
+ TIMESPEC_TO_TIMEVAL(&tval[0], &sbp->st_atimespec);
+ TIMESPEC_TO_TIMEVAL(&tval[1], &sbp->st_mtimespec);
+#else
+ tval[0].tv_sec = sbp->st_atime;
+ tval[1].tv_sec = sbp->st_mtime;
+ tval[0].tv_usec = 0;
+ tval[1].tv_usec = 0;
+#endif
+#if 0
+#ifdef _SRV5
+ if (utimes(to, tval))
+#else
+ if (futimes(to_fd, tval))
+#endif
+ warn("%s: set times", to);
+#endif
+ if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) {
+ if (errno != EPERM)
+ warn("%s: set owner/group", to);
+ sbp->st_mode &= ~(S_ISUID | S_ISGID);
+ }
+ if (fchmod(to_fd, sbp->st_mode))
+ warn("%s: set mode", to);
+#if 0
+ if (fchflags(to_fd, sbp->st_flags) && (errno != EOPNOTSUPP))
+ warn("%s: set flags (was: 0%07o)", to, sbp->st_flags);
+#endif
+ if (close(to_fd)) {
+ warn("%s", to);
+ return (1);
+ }
+
+ if (unlink(from)) {
+ warn("%s: remove", from);
+ return (1);
+ }
+
+ if (vflg)
+ printf("%s -> %s\n", from, to);
+
+ return (0);
+}
+
+int
+copy_mv(rtems_shell_mv_globals* globals, char *from, char *to)
+{
+ char* cp_argv[5] = { "mv", vflg ? "-PRpv" : "-PRp", "--", from, to };
+ char* rm_argv[4] = { "mv", "-rf", "--", from };
+ int result;
+
+ result = rtems_shell_main_cp(5, cp_argv);
+ if (result) {
+ warnx("%s: did not terminate normally", _PATH_CP);
+ return (1);
+ }
+ result = rtems_shell_main_rm(4, rm_argv);
+ if (result) {
+ warnx("%s: did not terminate normally", _PATH_RM);
+ return (1);
+ }
+#if 0
+ pid_t pid;
+ int status;
+
+ if ((pid = vfork()) == 0) {
+ execl(_PATH_CP, "mv", vflg ? "-PRpv" : "-PRp", "--", from, to, NULL);
+ warn("%s", _PATH_CP);
+ _exit(1);
+ }
+ if (waitpid(pid, &status, 0) == -1) {
+ warn("%s: waitpid", _PATH_CP);
+ return (1);
+ }
+ if (!WIFEXITED(status)) {
+ warnx("%s: did not terminate normally", _PATH_CP);
+ return (1);
+ }
+ if (WEXITSTATUS(status)) {
+ warnx("%s: terminated with %d (non-zero) status",
+ _PATH_CP, WEXITSTATUS(status));
+ return (1);
+ }
+ if (!(pid = vfork())) {
+ execl(_PATH_RM, "mv", "-rf", "--", from, NULL);
+ warn("%s", _PATH_RM);
+ _exit(1);
+ }
+ if (waitpid(pid, &status, 0) == -1) {
+ warn("%s: waitpid", _PATH_RM);
+ return (1);
+ }
+ if (!WIFEXITED(status)) {
+ warnx("%s: did not terminate normally", _PATH_RM);
+ return (1);
+ }
+ if (WEXITSTATUS(status)) {
+ warnx("%s: terminated with %d (non-zero) status",
+ _PATH_RM, WEXITSTATUS(status));
+ return (1);
+ }
+#endif
+ return (0);
+}
+
+void
+usage_mv(rtems_shell_mv_globals* globals)
+{
+ (void)fprintf(stderr, "usage: %s [-fiv] source target\n"
+ " %s [-fiv] source ... directory\n",
+ "mv", "mv");
+ exit(1);
+ /* NOTREACHED */
+}
+
+rtems_shell_cmd_t rtems_shell_MV_Command = {
+ "mv", /* name */
+ "[-fiv] source target ...", /* usage */
+ "files", /* topic */
+ rtems_shell_main_mv, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_mwdump.c b/cpukit/libmisc/shell/main_mwdump.c
new file mode 100644
index 0000000000..f3e3cfc27b
--- /dev/null
+++ b/cpukit/libmisc/shell/main_mwdump.c
@@ -0,0 +1,95 @@
+/*
+ * MWDUMP Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include "internal.h"
+
+int rtems_shell_main_mwdump(
+ int argc,
+ char *argv[]
+)
+{
+ unsigned char n;
+ unsigned char m;
+ int max;
+ int res;
+ void *addr = 0;
+ unsigned char *pb;
+
+ if ( argc > 1 ) {
+ if ( rtems_string_to_pointer(argv[1], &addr, NULL) ) {
+ printf( "Address argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+ }
+
+ if ( argc > 2 ) {
+ if ( rtems_string_to_int(argv[2], &max, NULL, 0) ) {
+ printf( "Address argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+
+ if (max <= 0) {
+ max = 1; /* print 1 item if 0 or neg. */
+ res = 0;
+ } else {
+ max--;
+ res = max & 0xf;/* num bytes in last row */
+ max >>= 4; /* div by 16 */
+ max++; /* num of rows to print */
+ if (max > 20) { /* limit to 20 */
+ max = 20;
+ res = 0xf; /* 16 bytes print in last row */
+ }
+ }
+ } else {
+ max = 20;
+ res = 0xf;
+ }
+
+ pb = addr;
+ for (m=0;m<max;m++) {
+ printf("%10p ", pb);
+ for (n=0;n<=(m==(max-1)?res:0xf);n+=2)
+ printf("%04X%c",*((unsigned short*)(pb+n)),n==6?'-':' ');
+ for (;n<=0xf;n+=2)
+ printf(" %c", n==6?'-':' ');
+ for (n=0;n<=(m==(max-1)?res:0xf);n++) {
+ printf("%c", isprint(pb[n]) ? pb[n] : '.');
+ }
+ printf("\n");
+ pb += 16;
+ }
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_WDUMP_Command = {
+ "wdump", /* name */
+ "wdump [address [length]]", /* usage */
+ "mem", /* topic */
+ rtems_shell_main_mwdump, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_netstats.c b/cpukit/libmisc/shell/main_netstats.c
new file mode 100644
index 0000000000..cc9b95a52c
--- /dev/null
+++ b/cpukit/libmisc/shell/main_netstats.c
@@ -0,0 +1,138 @@
+/*
+ * Network Statistics Shell Command Implmentation
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+static void netstats_usage(void)
+{
+ printf(
+ "netstats [-vAimfpcut] where:\n"
+ " -A print All statistics\n"
+ " -i print Inet Routes\n"
+ " -m print MBUF Statistics\n"
+ " -f print IF Statistics\n"
+ " -p print IP Statistics\n"
+ " -c print ICMP Statistics\n"
+ " -u print UDP Statistics\n"
+ " -t print TCP Statistics\n"
+ );
+}
+
+int rtems_shell_main_netstats( /* command */
+ int argc,
+ char *argv[]
+)
+{
+ int option;
+ int doAll = 0;
+ int doInetRoutes = 0;
+ int doMBUFStats = 0;
+ int doIFStats = 0;
+ int doIPStats = 0;
+ int doICMPStats = 0;
+ int doUDPStats = 0;
+ int doTCPStats = 0;
+ int verbose = 0;
+ struct getopt_data getopt_reent;
+
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+ while ( (option = getopt_r( argc, argv, "Aimfpcutv", &getopt_reent)) != -1 ) {
+
+ switch ((char)option) {
+ case 'A': doAll = 1; break;
+ case 'i': doInetRoutes = 1; break;
+ case 'm': doMBUFStats = 1; break;
+ case 'f': doIFStats = 1; break;
+ case 'p': doIPStats = 1; break;
+ case 'c': doICMPStats = 1; break;
+ case 'u': doUDPStats = 1; break;
+ case 't': doTCPStats = 1; break;
+ case 'v': verbose = 1; break;
+ case '?':
+ default:
+ netstats_usage();
+ return -1;
+ }
+ }
+
+ if ( verbose ) {
+ printf(
+ "doAll=%d\n"
+ "doInetRoutes=%d\n"
+ "doMBUFStats=%d\n"
+ "doIFStats=%d\n"
+ "doIPStats=%d\n"
+ "doICMPStats=%d\n"
+ "doUDPStats=%d\n"
+ "doTCPStats=%d\n",
+ doAll,
+ doInetRoutes,
+ doMBUFStats,
+ doIFStats,
+ doIPStats,
+ doICMPStats,
+ doUDPStats,
+ doTCPStats
+ );
+ }
+
+ if ( doInetRoutes == 1 || doAll == 1 ) {
+ rtems_bsdnet_show_inet_routes();
+ }
+
+ if ( doMBUFStats == 1 || doAll == 1 ) {
+ rtems_bsdnet_show_mbuf_stats();
+ }
+
+ if ( doIFStats == 1 || doAll == 1 ) {
+ rtems_bsdnet_show_if_stats();
+ }
+
+ if ( doIPStats == 1 || doAll == 1 ) {
+ rtems_bsdnet_show_ip_stats();
+ }
+
+ if ( doICMPStats == 1 || doAll == 1 ) {
+ rtems_bsdnet_show_icmp_stats();
+ }
+
+ if ( doUDPStats == 1 || doAll == 1 ) {
+ rtems_bsdnet_show_udp_stats();
+ }
+
+ if ( doTCPStats == 1 || doAll == 1 ) {
+ rtems_bsdnet_show_tcp_stats();
+ }
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_NETSTATS_Command = {
+ "netstats", /* name */
+ "netstats [-Aimfpcutv]", /* usage */
+ "network", /* topic */
+ rtems_shell_main_netstats, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_perioduse.c b/cpukit/libmisc/shell/main_perioduse.c
new file mode 100644
index 0000000000..d0f123af1c
--- /dev/null
+++ b/cpukit/libmisc/shell/main_perioduse.c
@@ -0,0 +1,63 @@
+/*
+ * perioduse Command Implementation
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_perioduse(
+ int argc,
+ char *argv[]
+)
+{
+ /*
+ * When invoked with no arguments, print the report.
+ */
+ if ( argc == 1 ) {
+ rtems_rate_monotonic_report_statistics_with_plugin(
+ stdout,
+ (rtems_printk_plugin_t)fprintf
+ );
+ return 0;
+ }
+
+ /*
+ * When invoked with the single argument -r, reset the statistics.
+ */
+ if ( argc == 2 && !strcmp( argv[1], "-r" ) ) {
+ printf( "Resetting Period Usage information\n" );
+ rtems_rate_monotonic_reset_all_statistics();
+ return 0;
+ }
+
+ /*
+ * OK. The user did something wrong.
+ */
+ fprintf( stderr, "%s: [-r]\n", argv[0] );
+ return -1;
+}
+
+rtems_shell_cmd_t rtems_shell_PERIODUSE_Command = {
+ "perioduse", /* name */
+ "[-r] print or reset per period usage", /* usage */
+ "rtems", /* topic */
+ rtems_shell_main_perioduse, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_pwd.c b/cpukit/libmisc/shell/main_pwd.c
new file mode 100644
index 0000000000..3a298f8242
--- /dev/null
+++ b/cpukit/libmisc/shell/main_pwd.c
@@ -0,0 +1,45 @@
+/*
+ * PWD Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_pwd(
+ int argc __attribute__((unused)),
+ char *argv[] __attribute__((unused))
+)
+{
+ char dir[1024];
+
+ getcwd(dir,1024);
+ puts(dir);
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_PWD_Command = {
+ "pwd", /* name */
+ "pwd # print work directory", /* usage */
+ "files", /* topic */
+ rtems_shell_main_pwd, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_rm.c b/cpukit/libmisc/shell/main_rm.c
new file mode 100644
index 0000000000..465a0daf46
--- /dev/null
+++ b/cpukit/libmisc/shell/main_rm.c
@@ -0,0 +1,709 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * 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.
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if 0
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1990, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rm.c 8.5 (Berkeley) 4/18/94";
+#endif /* not lint */
+#endif
+#if 0
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/rm/rm.c,v 1.58 2006/10/31 02:22:36 delphij Exp $");
+#endif
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define rindex(s,c) strrchr(s,c)
+
+/* RTEMS specific changes */
+typedef struct {
+ int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok;
+ int rflag, Iflag;
+ uid_t uid;
+ int exit_code;
+ jmp_buf exit_jmp;
+} rtems_shell_rm_globals;
+
+#define dflag globals->dflag
+#define eval globals->eval
+#define fflag globals->fflag
+#define iflag globals->iflag
+#define Pflag globals->Pflag
+#define vflag globals->vflag
+#define Wflag globals->Wflag
+#define stdin_ok globals->stdin_ok
+#define rflag globals->rflag
+#define Iflag globals->Iflag
+#define xuid globals->uid
+#define exit_jump &(globals->exit_jmp)
+
+#include <setjmp.h>
+
+#define exit(ec) rtems_shell_rm_exit(globals, ec)
+void
+rtems_shell_rm_exit (rtems_shell_rm_globals* globals, int code)
+{
+ globals->exit_code = code;
+ longjmp (globals->exit_jmp, 1);
+}
+
+static int main_rm(rtems_shell_rm_globals* globals, int argc, char *argv[]);
+
+int
+rtems_shell_main_rm(int argc, char *argv[])
+{
+ rtems_shell_rm_globals rm_globals;
+ memset (&rm_globals, 0, sizeof (rm_globals));
+ rm_globals.exit_code = 1;
+ if (setjmp (rm_globals.exit_jmp) == 0)
+ return main_rm (&rm_globals, argc, argv);
+ return rm_globals.exit_code;
+}
+
+#define check(a1, a2, a3) check_rm(globals, a1, a2, a3)
+#define check2(a1) check2_rm(globals, a1)
+#define checkdot(a1) checkdot_rm(globals, a1)
+#define checkslash(a1) checkslash_rm(globals, a1)
+#define rm_file(a1) rm_file_rm(globals, a1)
+#define rm_overwrite(a1, a2) rm_overwrite_rm(globals, a1, a2)
+#define rm_tree(a1) rm_tree_rm(globals, a1)
+#define usage() usage_rm(globals)
+
+
+/* RTEMS changes */
+
+static int check_rm(rtems_shell_rm_globals* globals, char *, char *, struct stat *);
+static int check2_rm(rtems_shell_rm_globals* globals, char **);
+static void checkdot_rm(rtems_shell_rm_globals* globals, char **);
+static void checkslash_rm(rtems_shell_rm_globals* globals, char **);
+static void rm_file_rm(rtems_shell_rm_globals* globals, char **);
+static int rm_overwrite_rm(rtems_shell_rm_globals* globals, char *, struct stat *);
+static void rm_tree_rm(rtems_shell_rm_globals* globals, char **);
+static void usage_rm(rtems_shell_rm_globals* globals);
+
+/*
+ * rm --
+ * This rm is different from historic rm's, but is expected to match
+ * POSIX 1003.2 behavior. The most visible difference is that -f
+ * has two specific effects now, ignore non-existent files and force
+ * file removal.
+ */
+int
+main_rm(rtems_shell_rm_globals* globals, int argc, char *argv[])
+{
+ int ch;
+ char *p;
+
+ struct getopt_data getopt_reent;
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+
+ /*
+ * Test for the special case where the utility is called as
+ * "unlink", for which the functionality provided is greatly
+ * simplified.
+ */
+ if ((p = rindex(argv[0], '/')) == NULL)
+ p = argv[0];
+ else
+ ++p;
+ if (strcmp(p, "unlink") == 0) {
+ while (getopt_r(argc, argv, "", &getopt_reent) != -1)
+ usage();
+ argc -= getopt_reent.optind;
+ argv += getopt_reent.optind;
+ if (argc != 1)
+ usage();
+ rm_file(&argv[0]);
+ exit(eval);
+ }
+
+ Pflag = rflag = 0;
+ while ((ch = getopt_r(argc, argv, "dfiIPRrvW", &getopt_reent)) != -1)
+ switch(ch) {
+ case 'd':
+ dflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ iflag = 0;
+ break;
+ case 'i':
+ fflag = 0;
+ iflag = 1;
+ break;
+ case 'I':
+ Iflag = 1;
+ break;
+ case 'P':
+ Pflag = 1;
+ break;
+ case 'R':
+ case 'r': /* Compatibility. */
+ rflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ case 'W':
+ Wflag = 1;
+ break;
+ default:
+ usage();
+ }
+ argc -= getopt_reent.optind;
+ argv += getopt_reent.optind;
+
+ if (argc < 1) {
+ if (fflag)
+ return (0);
+ usage();
+ }
+
+ checkdot(argv);
+ if (getenv("POSIXLY_CORRECT") == NULL)
+ checkslash(argv);
+ xuid = geteuid();
+
+ if (*argv) {
+ stdin_ok = isatty(STDIN_FILENO);
+
+ if (Iflag) {
+ if (check2(argv) == 0)
+ exit (1);
+ }
+ if (rflag)
+ rm_tree(argv);
+ else
+ rm_file(argv);
+ }
+
+ exit (eval);
+ return 0;
+}
+
+void
+rm_tree_rm(rtems_shell_rm_globals* globals, char **argv)
+{
+ FTS *fts;
+ FTSENT *p;
+ int needstat;
+ int flags;
+ int rval;
+
+ /*
+ * Remove a file hierarchy. If forcing removal (-f), or interactive
+ * (-i) or can't ask anyway (stdin_ok), don't stat the file.
+ */
+ needstat = !xuid || (!fflag && !iflag && stdin_ok);
+
+ /*
+ * If the -i option is specified, the user can skip on the pre-order
+ * visit. The fts_number field flags skipped directories.
+ */
+#define SKIPPED 1
+
+ flags = FTS_PHYSICAL;
+ if (!needstat)
+ flags |= FTS_NOSTAT;
+ if (Wflag)
+ flags |= FTS_WHITEOUT;
+ if (!(fts = fts_open(argv, flags, NULL))) {
+ if (fflag && errno == ENOENT)
+ return;
+ err(exit_jump, 1, "fts_open");
+ }
+ while ((p = fts_read(fts)) != NULL) {
+ switch (p->fts_info) {
+ case FTS_DNR:
+ if (!fflag || p->fts_errno != ENOENT) {
+ warnx("%s: %s",
+ p->fts_path, strerror(p->fts_errno));
+ eval = 1;
+ }
+ continue;
+ case FTS_ERR:
+ errx(exit_jump, 1, "%s: %s", p->fts_path, strerror(p->fts_errno));
+ case FTS_NS:
+ /*
+ * Assume that since fts_read() couldn't stat the
+ * file, it can't be unlinked.
+ */
+ if (!needstat)
+ break;
+ if (!fflag || p->fts_errno != ENOENT) {
+ warnx("%s: %s",
+ p->fts_path, strerror(p->fts_errno));
+ eval = 1;
+ }
+ continue;
+ case FTS_D:
+ /* Pre-order: give user chance to skip. */
+ if (!fflag && !check(p->fts_path, p->fts_accpath,
+ p->fts_statp)) {
+ (void)fts_set(fts, p, FTS_SKIP);
+ p->fts_number = SKIPPED;
+ }
+#if RTEMS_REMOVED
+ else if (!xuid &&
+ (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+ !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
+ chflags(p->fts_accpath,
+ p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
+ goto err;
+#endif
+ continue;
+ case FTS_DP:
+ /* Post-order: see if user skipped. */
+ if (p->fts_number == SKIPPED)
+ continue;
+ break;
+ default:
+ if (!fflag &&
+ !check(p->fts_path, p->fts_accpath, p->fts_statp))
+ continue;
+ }
+
+ rval = 0;
+#if RTEMS_REMOVED
+ if (!xuid &&
+ (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+ !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
+ rval = chflags(p->fts_accpath,
+ p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
+#endif
+ if (rval == 0) {
+ /*
+ * If we can't read or search the directory, may still be
+ * able to remove it. Don't print out the un{read,search}able
+ * message unless the remove fails.
+ */
+ switch (p->fts_info) {
+ case FTS_DP:
+ case FTS_DNR:
+ rval = rmdir(p->fts_accpath);
+ if (rval == 0 || (fflag && errno == ENOENT)) {
+ if (rval == 0 && vflag)
+ (void)printf("%s\n",
+ p->fts_path);
+ continue;
+ }
+ break;
+
+#if RTEMS_REMOVED
+ case FTS_W:
+ rval = undelete(p->fts_accpath);
+ if (rval == 0 && (fflag && errno == ENOENT)) {
+ if (vflag)
+ (void)printf("%s\n",
+ p->fts_path);
+ continue;
+ }
+ break;
+#endif
+
+ case FTS_NS:
+ /*
+ * Assume that since fts_read() couldn't stat
+ * the file, it can't be unlinked.
+ */
+ if (fflag)
+ continue;
+ /* FALLTHROUGH */
+ default:
+ if (Pflag)
+ if (!rm_overwrite(p->fts_accpath, NULL))
+ continue;
+ rval = unlink(p->fts_accpath);
+ if (rval == 0 || (fflag && errno == ENOENT)) {
+ if (rval == 0 && vflag)
+ (void)printf("%s\n",
+ p->fts_path);
+ continue;
+ }
+ }
+ }
+#if RTEMS_REMOVED
+err:
+#endif
+ warn("%s", p->fts_path);
+ eval = 1;
+ }
+ if (errno)
+ err(exit_jump, 1, "fts_read");
+ fts_close(fts);
+}
+
+#define S_ISWHT(m) (0)
+
+void
+rm_file_rm(rtems_shell_rm_globals* globals, char **argv)
+{
+ struct stat sb;
+ int rval;
+ char *f;
+
+ /*
+ * Remove a file. POSIX 1003.2 states that, by default, attempting
+ * to remove a directory is an error, so must always stat the file.
+ */
+ while ((f = *argv++) != NULL) {
+ /* Assume if can't stat the file, can't unlink it. */
+ if (lstat(f, &sb)) {
+#if RTEMS_REMOVED
+ if (Wflag) {
+ sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
+ } else {
+#endif
+ if (!fflag || errno != ENOENT) {
+ warn("%s", f);
+ eval = 1;
+ }
+ continue;
+#if RTEMS_REMOVED
+ }
+#endif
+ } else if (Wflag) {
+ warnx("%s: %s", f, strerror(EEXIST));
+ eval = 1;
+ continue;
+ }
+
+ if (S_ISDIR(sb.st_mode) && !dflag) {
+ warnx("%s: is a directory", f);
+ eval = 1;
+ continue;
+ }
+ if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
+ continue;
+ rval = 0;
+#if RTEMS_REMOVED
+ if (!xuid && !S_ISWHT(sb.st_mode) &&
+ (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+ !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
+ rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
+#endif
+ if (rval == 0) {
+ if (S_ISWHT(sb.st_mode))
+#if RTEMS_REMOVED
+ rval = undelete(f);
+#endif
+ ;
+ else if (S_ISDIR(sb.st_mode))
+ rval = rmdir(f);
+ else {
+ if (Pflag)
+ if (!rm_overwrite(f, &sb))
+ continue;
+ rval = unlink(f);
+ }
+ }
+ if (rval && (!fflag || errno != ENOENT)) {
+ warn("%s", f);
+ eval = 1;
+ }
+ if (vflag && rval == 0)
+ (void)printf("%s\n", f);
+ }
+}
+
+/*
+ * rm_overwrite --
+ * Overwrite the file 3 times with varying bit patterns.
+ *
+ * XXX
+ * This is a cheap way to *really* delete files. Note that only regular
+ * files are deleted, directories (and therefore names) will remain.
+ * Also, this assumes a fixed-block file system (like FFS, or a V7 or a
+ * System V file system). In a logging file system, you'll have to have
+ * kernel support.
+ */
+int
+rm_overwrite_rm(rtems_shell_rm_globals* globals, char *file, struct stat *sbp)
+{
+ struct stat sb;
+#if RTEMS_REMOVED
+ struct statfs fsb;
+#endif
+ off_t len;
+ int bsize, fd, wlen;
+ char *buf = NULL;
+
+ fd = -1;
+ if (sbp == NULL) {
+ if (lstat(file, &sb))
+ goto err;
+ sbp = &sb;
+ }
+ if (!S_ISREG(sbp->st_mode))
+ return (1);
+ if (sbp->st_nlink > 1 && !fflag) {
+ warnx("%s (inode %lu): not overwritten due to multiple links",
+ file, sbp->st_ino);
+ return (0);
+ }
+ if ((fd = open(file, O_WRONLY, 0)) == -1)
+ goto err;
+#if RTEMS_REMOVED
+ if (fstatfs(fd, &fsb) == -1)
+ goto err;
+ bsize = MAX(fsb.f_iosize, 1024);
+#endif
+ bsize = 1024;
+ if ((buf = malloc(bsize)) == NULL)
+ err(exit_jump, 1, "%s: malloc", file);
+
+#define PASS(byte) { \
+ memset(buf, byte, bsize); \
+ for (len = sbp->st_size; len > 0; len -= wlen) { \
+ wlen = len < bsize ? len : bsize; \
+ if (write(fd, buf, wlen) != wlen) \
+ goto err; \
+ } \
+}
+ PASS(0xff);
+ if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
+ goto err;
+ PASS(0x00);
+ if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
+ goto err;
+ PASS(0xff);
+ if (!fsync(fd) && !close(fd)) {
+ free(buf);
+ return (1);
+ }
+
+err: eval = 1;
+ if (buf)
+ free(buf);
+ if (fd != -1)
+ close(fd);
+ warn("%s", file);
+ return (0);
+}
+
+void strmode(mode_t mode, char *p);
+char *fflagstostr(u_long flags);
+const char *user_from_uid(uid_t uid, int nouser);
+
+int
+check_rm(rtems_shell_rm_globals* globals, char *path, char *name, struct stat *sp)
+{
+ int ch, first;
+ char modep[15], *flagsp;
+
+ /* Check -i first. */
+ if (iflag)
+ (void)fprintf(stderr, "remove %s? ", path);
+ else {
+ /*
+ * If it's not a symbolic link and it's unwritable and we're
+ * talking to a terminal, ask. Symbolic links are excluded
+ * because their permissions are meaningless. Check stdin_ok
+ * first because we may not have stat'ed the file.
+ */
+#if RTEMS_REMOVED
+ if (!stdin_ok || S_ISLNK(sp->st_mode) ||
+ (!access(name, W_OK) &&
+ !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
+ (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !xuid)))
+#endif
+ if (!stdin_ok || S_ISLNK(sp->st_mode) ||
+ (!access(name, W_OK)))
+ return (1);
+ strmode(sp->st_mode, modep);
+#if RTEMS_REMOVED
+ if ((flagsp = fflagstostr(sp->st_flags)) == NULL)
+ err(exit_jump, 1, "fflagstostr");
+#else
+ flagsp = "no supported";
+#endif
+ if (Pflag)
+ errx(exit_jump, 1,
+ "%s: -P was specified, but file is not writable",
+ path);
+ (void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ",
+ modep + 1, modep[9] == ' ' ? "" : " ",
+ user_from_uid(sp->st_uid, 0),
+ group_from_gid(sp->st_gid, 0),
+ *flagsp ? flagsp : "", *flagsp ? " " : "",
+ path);
+#if RTEMS_REMOVED
+ free(flagsp);
+#endif
+ }
+ (void)fflush(stderr);
+
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ return (first == 'y' || first == 'Y');
+}
+
+#define ISSLASH(a) ((a)[0] == '/' && (a)[1] == '\0')
+void
+checkslash_rm(rtems_shell_rm_globals* globals, char **argv)
+{
+ char **t, **u;
+ int complained;
+
+ complained = 0;
+ for (t = argv; *t;) {
+ if (ISSLASH(*t)) {
+ if (!complained++)
+ warnx("\"/\" may not be removed");
+ eval = 1;
+ for (u = t; u[0] != NULL; ++u)
+ u[0] = u[1];
+ } else {
+ ++t;
+ }
+ }
+}
+
+int
+check2_rm(rtems_shell_rm_globals* globals, char **argv)
+{
+ struct stat st;
+ int first;
+ int ch;
+ int fcount = 0;
+ int dcount = 0;
+ int i;
+ const char *dname = NULL;
+
+ for (i = 0; argv[i]; ++i) {
+ if (lstat(argv[i], &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ ++dcount;
+ dname = argv[i]; /* only used if 1 dir */
+ } else {
+ ++fcount;
+ }
+ }
+ }
+ first = 0;
+ while (first != 'n' && first != 'N' && first != 'y' && first != 'Y') {
+ if (dcount && rflag) {
+ fprintf(stderr, "recursively remove");
+ if (dcount == 1)
+ fprintf(stderr, " %s", dname);
+ else
+ fprintf(stderr, " %d dirs", dcount);
+ if (fcount == 1)
+ fprintf(stderr, " and 1 file");
+ else if (fcount > 1)
+ fprintf(stderr, " and %d files", fcount);
+ } else if (dcount + fcount > 3) {
+ fprintf(stderr, "remove %d files", dcount + fcount);
+ } else {
+ return(1);
+ }
+ fprintf(stderr, "? ");
+ fflush(stderr);
+
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (ch == EOF)
+ break;
+ }
+ return (first == 'y' || first == 'Y');
+}
+
+#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
+void
+checkdot_rm(rtems_shell_rm_globals* globals, char **argv)
+{
+ char *p, **save, **t;
+ int complained;
+
+ complained = 0;
+ for (t = argv; *t;) {
+ if ((p = strrchr(*t, '/')) != NULL)
+ ++p;
+ else
+ p = *t;
+ if (ISDOT(p)) {
+ if (!complained++)
+ warnx("\".\" and \"..\" may not be removed");
+ eval = 1;
+ for (save = t; (t[0] = t[1]) != NULL; ++t)
+ continue;
+ t = save;
+ } else
+ ++t;
+ }
+}
+
+void
+usage_rm(rtems_shell_rm_globals* globals)
+{
+
+ (void)fprintf(stderr, "%s\n%s\n",
+ "usage: rm [-f | -i] [-dIPRrvW] file ...",
+ " unlink file");
+ exit(1);
+}
+
+rtems_shell_cmd_t rtems_shell_RM_Command = {
+ "rm", /* name */
+ "[-f | -i] [-dIPRrvW] file ...", /* usage */
+ "files", /* topic */
+ rtems_shell_main_rm, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_rmdir.c b/cpukit/libmisc/shell/main_rmdir.c
new file mode 100644
index 0000000000..df94a7efbf
--- /dev/null
+++ b/cpukit/libmisc/shell/main_rmdir.c
@@ -0,0 +1,51 @@
+/*
+ * RMDIR Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_rmdir (int argc, char *argv[])
+{
+ char *dir;
+ int n;
+
+ n = 1;
+ while (n < argc) {
+ dir = argv[n++];
+ if (rmdir(dir)) {
+ fprintf(stderr,"%s: %s: %s\n", argv[0], dir, strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_RMDIR_Command = {
+ "rmdir", /* name */
+ "rmdir dir # remove directory", /* usage */
+ "files", /* topic */
+ rtems_shell_main_rmdir, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_route.c b/cpukit/libmisc/shell/main_route.c
new file mode 100644
index 0000000000..ea503b4ef2
--- /dev/null
+++ b/cpukit/libmisc/shell/main_route.c
@@ -0,0 +1,153 @@
+/*
+ * ROUTE Command Implmentation
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/route.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_route(
+ int argc,
+ char *argv[]
+)
+{
+ int cmd;
+ struct sockaddr_in dst;
+ struct sockaddr_in gw;
+ struct sockaddr_in netmask;
+ int f_host;
+ int f_gw = 0;
+ int cur_idx;
+ int flags;
+ int rc;
+
+ memset(&dst, 0, sizeof(dst));
+ memset(&gw, 0, sizeof(gw));
+ memset(&netmask, 0, sizeof(netmask));
+
+ dst.sin_len = sizeof(dst);
+ dst.sin_family = AF_INET;
+ dst.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+ gw.sin_len = sizeof(gw);
+ gw.sin_family = AF_INET;
+ gw.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+ netmask.sin_len = sizeof(netmask);
+ netmask.sin_family = AF_INET;
+ netmask.sin_addr.s_addr = inet_addr("255.255.255.0");
+
+ if (argc < 2) {
+ rtems_bsdnet_show_inet_routes();
+ return 0;
+ }
+
+ if (strcmp(argv[1], "add") == 0) {
+ cmd = RTM_ADD;
+ } else if (strcmp(argv[1], "del") == 0) {
+ cmd = RTM_DELETE;
+ } else {
+ printf("invalid command: %s\n", argv[1]);
+ printf("\tit should be 'add' or 'del'\n");
+ return -1;
+ }
+
+ if (argc < 3) {
+ printf("not enough arguments\n");
+ return -1;
+ }
+
+ if (strcmp(argv[2], "-host") == 0) {
+ f_host = 1;
+ } else if (strcmp(argv[2], "-net") == 0) {
+ f_host = 0;
+ } else {
+ printf("Invalid type: %s\n", argv[1]);
+ printf("\tit should be '-host' or '-net'\n");
+ return -1;
+ }
+
+ if (argc < 4) {
+ printf("not enough arguments\n");
+ return -1;
+ }
+
+ inet_pton(AF_INET, argv[3], &dst.sin_addr);
+
+ cur_idx = 4;
+ while(cur_idx < argc) {
+ if (strcmp(argv[cur_idx], "gw") == 0) {
+ if ((cur_idx +1) >= argc) {
+ printf("no gateway address\n");
+ return -1;
+ }
+ f_gw = 1;
+ inet_pton(AF_INET, argv[cur_idx + 1], &gw.sin_addr);
+ cur_idx += 1;
+ } else if(strcmp(argv[cur_idx], "netmask") == 0) {
+ if ((cur_idx +1) >= argc) {
+ printf("no netmask address\n");
+ return -1;
+ }
+ f_gw = 1;
+ inet_pton(AF_INET, argv[cur_idx + 1], &netmask.sin_addr);
+ cur_idx += 1;
+ } else {
+ printf("Unknown argument\n");
+ return -1;
+ }
+ cur_idx += 1;
+ }
+
+ flags = RTF_STATIC;
+ if (f_gw != 0) {
+ flags |= RTF_GATEWAY;
+ }
+ if (f_host != 0) {
+ flags |= RTF_HOST;
+ }
+
+ rc = rtems_bsdnet_rtrequest(
+ cmd,
+ (struct sockaddr *)&dst,
+ (struct sockaddr *)&gw,
+ (struct sockaddr *)&netmask,
+ flags,
+ NULL
+ );
+ if (rc < 0) {
+ printf("Error adding route\n");
+ }
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_ROUTE_Command = {
+ "route", /* name */
+ "TBD", /* usage */
+ "network", /* topic */
+ rtems_shell_main_route, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_rtc.c b/cpukit/libmisc/shell/main_rtc.c
new file mode 100644
index 0000000000..139018eb13
--- /dev/null
+++ b/cpukit/libmisc/shell/main_rtc.c
@@ -0,0 +1,173 @@
+/**
+ * @file
+ *
+ * Real time clock shell command.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <rtems.h>
+#include <rtems/rtc.h>
+#include <rtems/error.h>
+#include <rtems/shell.h>
+
+#define RTEMS_RTC_SHELL_ERROR( fmt, ...) \
+ do { \
+ printf( "error: " fmt "\n", ##__VA_ARGS__); \
+ return -1; \
+ } while (0)
+
+#define RTEMS_RTC_SHELL_ERROR_SC( sc, fmt, ...) \
+ if ((sc) != RTEMS_SUCCESSFUL) { \
+ printf( "error: " fmt ": %s\n", ##__VA_ARGS__, rtems_status_text( sc)); \
+ return -1; \
+ }
+
+static const char rtems_rtc_shell_usage [] =
+ "real time clock read and set\n"
+ "\n"
+ "rtc\n"
+ "\tprints the current time of day\n"
+ "\n"
+ "rtc YYYY-MM-DD [HH:MM:SS [TICKS]]\n"
+ "\tsets the time of day and real time clock";
+
+static int rtems_rtc_shell_main( int argc, char **argv)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_time_of_day tod = {
+ .year = 1988,
+ .month = 1,
+ .day = 1,
+ .hour = 0,
+ .minute = 0,
+ .second = 0,
+ .ticks = 0
+ };
+
+ if (argc == 1) {
+ sc = rtems_clock_get_tod( &tod);
+ RTEMS_RTC_SHELL_ERROR_SC( sc, "get time of day");
+
+ printf(
+ "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
+ " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
+ " %02" PRIu32 "\n",
+ tod.year,
+ tod.month,
+ tod.day,
+ tod.hour,
+ tod.minute,
+ tod.second,
+ tod.ticks
+ );
+ } else if (argc > 1 && argc < 5) {
+ int rv = 0;
+ int fd = 0;
+ ssize_t n = 0;
+ uint32_t v [3];
+
+ if (argc > 1) {
+ rv = sscanf(
+ argv [1],
+ "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32,
+ v,
+ v + 1,
+ v + 2
+ );
+
+ if (rv == 3) {
+ tod.year = v [0];
+ tod.month = v [1];
+ tod.day = v [2];
+ } else {
+ RTEMS_RTC_SHELL_ERROR( "unexpected YYYY-MM-DD input: %s", argv [1]);
+ }
+ }
+
+ if (argc > 2) {
+ rv = sscanf(
+ argv [2],
+ "%04" PRIu32 ":%02" PRIu32 ":%02" PRIu32,
+ v,
+ v + 1,
+ v + 2
+ );
+
+ if (rv == 3) {
+ tod.hour = v [0];
+ tod.minute = v [1];
+ tod.second = v [2];
+ } else {
+ RTEMS_RTC_SHELL_ERROR( "unexpected HH:MM:SS input: %s", argv [2]);
+ }
+ }
+
+ if (argc > 3) {
+ rv = sscanf( argv [3], "%5" PRIu32, v);
+
+ if (rv == 1) {
+ tod.ticks = v [0];
+ } else {
+ RTEMS_RTC_SHELL_ERROR( "unexpected TICKS input: %s", argv [3]);
+ }
+ }
+
+ sc = rtems_clock_set( &tod);
+ RTEMS_RTC_SHELL_ERROR_SC( sc, "set time of day");
+
+ fd = open( RTC_DEVICE_NAME, O_WRONLY);
+ if (fd < 0) {
+ perror( "error: open " RTC_DEVICE_NAME);
+ return -1;
+ }
+
+ n = write( fd, &tod, sizeof( tod));
+ if (n != (ssize_t) sizeof( tod)) {
+ perror( "error: write to " RTC_DEVICE_NAME);
+ close( fd);
+ return -1;
+ }
+
+ rv = close( fd);
+ if (rv != 0) {
+ perror( "error: close " RTC_DEVICE_NAME);
+ return -1;
+ }
+ } else {
+ puts( rtems_rtc_shell_usage);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct rtems_shell_cmd_tt rtems_shell_RTC_Command = {
+ .name = "rtc",
+ .usage = rtems_rtc_shell_usage,
+ .topic = "misc",
+ .command = rtems_rtc_shell_main,
+ .alias = NULL,
+ .next = NULL
+};
diff --git a/cpukit/libmisc/shell/main_setenv.c b/cpukit/libmisc/shell/main_setenv.c
new file mode 100644
index 0000000000..5b7c92920f
--- /dev/null
+++ b/cpukit/libmisc/shell/main_setenv.c
@@ -0,0 +1,72 @@
+/*
+ * Set an environment vairable.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_setenv(int argc, char *argv[])
+{
+ char* env = NULL;
+ char* string = NULL;
+ int len = 0;
+ int arg;
+ char* p;
+
+ if (argc <= 2) {
+ printf("error: no variable or string\n");
+ return 1;
+ }
+
+ env = argv[1];
+
+ for (arg = 2; arg < argc; arg++)
+ len += strlen(argv[arg]);
+
+ len += argc - 2 - 1;
+
+ string = malloc(len + 1);
+
+ if (!string) {
+ printf("error: no memory\n");
+ return 1;
+ }
+
+ for (arg = 2, p = string; arg < argc; arg++) {
+ strcpy(p, argv[arg]);
+ p += strlen(argv[arg]);
+ if (arg < (argc - 1)) {
+ *p = ' ';
+ p++;
+ }
+ }
+
+ if (setenv(env, string, 1) < 0) {
+ printf( "error: %s\n", strerror(errno) );
+ free( string );
+ return 1;
+ }
+
+ free( string );
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_SETENV_Command = {
+ "setenv", /* name */
+ "setenv [var] [string]", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_setenv, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_sleep.c b/cpukit/libmisc/shell/main_sleep.c
new file mode 100644
index 0000000000..2dbb66a996
--- /dev/null
+++ b/cpukit/libmisc/shell/main_sleep.c
@@ -0,0 +1,74 @@
+/*
+ * Sleep Shell Command Implmentation
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <time.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include "internal.h"
+
+int rtems_shell_main_sleep(
+ int argc,
+ char *argv[]
+)
+{
+ struct timespec delay;
+ unsigned long tmp;
+
+ if ((argc != 2) && (argc != 3)) {
+ fprintf( stderr, "%s: Usage seconds [nanoseconds]\n", argv[0] );
+ return -1;
+ }
+
+ /*
+ * Convert the seconds argument to a number
+ */
+ if ( rtems_string_to_unsigned_long(argv[1], &tmp, NULL, 0) ) {
+ printf( "Seconds argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+ delay.tv_sec = (time_t) tmp;
+
+ /*
+ * If the user specified a nanoseconds argument, convert it
+ */
+ delay.tv_nsec = 0;
+ if (argc == 3) {
+ if ( rtems_string_to_unsigned_long(argv[2], &tmp, NULL, 0) ) {
+ printf( "Seconds argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+ delay.tv_nsec = tmp;
+ }
+
+ /*
+ * Now sleep as requested.
+ */
+ nanosleep( &delay, NULL );
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_SLEEP_Command = {
+ "sleep", /* name */
+ "sleep seconds [nanoseconds]", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_sleep, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_stackuse.c b/cpukit/libmisc/shell/main_stackuse.c
new file mode 100644
index 0000000000..4d1d944ceb
--- /dev/null
+++ b/cpukit/libmisc/shell/main_stackuse.c
@@ -0,0 +1,44 @@
+/*
+ * stackuse Command Implementation
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <rtems.h>
+#include <rtems/stackchk.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_stackuse(
+ int argc __attribute__((unused)),
+ char *argv[] __attribute__((unused))
+)
+{
+ rtems_stack_checker_report_usage_with_plugin(
+ stdout,
+ (rtems_printk_plugin_t)fprintf
+ );
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_STACKUSE_Command = {
+ "stackuse", /* name */
+ "print per thread stack usage", /* usage */
+ "rtems", /* topic */
+ rtems_shell_main_stackuse, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_time.c b/cpukit/libmisc/shell/main_time.c
new file mode 100644
index 0000000000..7d6cf557ee
--- /dev/null
+++ b/cpukit/libmisc/shell/main_time.c
@@ -0,0 +1,84 @@
+/*
+ * Time Shell Command Implmentation
+ *
+ * Author: Chris Johns <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_time(
+ int argc,
+ char *argv[]
+)
+{
+ rtems_shell_cmd_t* shell_cmd;
+ int errorlevel = 0;
+ struct timespec start;
+ struct timespec end;
+ struct timespec period;
+ rtems_status_code sc;
+
+ argc--;
+
+ sc = rtems_clock_get_uptime(&start);
+ if (sc != RTEMS_SUCCESSFUL)
+ printf("error: cannot read time\n");
+
+ if (argc) {
+ shell_cmd = rtems_shell_lookup_cmd(argv[1]);
+ if ( argv[1] == NULL ) {
+ errorlevel = -1;
+ } else if ( shell_cmd == NULL ) {
+ errorlevel = rtems_shell_script_file(argc, &argv[1]);
+ } else {
+ errorlevel = shell_cmd->command(argc, &argv[1]);
+ }
+ }
+
+ sc = rtems_clock_get_uptime(&end);
+ if (sc != RTEMS_SUCCESSFUL)
+ printf("error: cannot read time\n");
+
+ period.tv_sec = end.tv_sec - start.tv_sec;
+ period.tv_nsec = end.tv_nsec - start.tv_nsec;
+ if (period.tv_nsec < 0)
+ {
+ --period.tv_sec;
+ period.tv_nsec += 1000000000UL;
+ }
+
+ printf("time: %li:%02li:%02li.%03li\n",
+ period.tv_sec / 3600,
+ period.tv_sec / 60, period.tv_sec % 60,
+ period.tv_nsec / 1000000);
+
+ return errorlevel;
+}
+
+rtems_shell_cmd_t rtems_shell_TIME_Command = {
+ "time", /* name */
+ "time command [arguments...]", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_time, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_tty.c b/cpukit/libmisc/shell/main_tty.c
new file mode 100644
index 0000000000..f8313b55f8
--- /dev/null
+++ b/cpukit/libmisc/shell/main_tty.c
@@ -0,0 +1,44 @@
+/*
+ * TTY Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_tty(
+ int argc __attribute__((unused)),
+ char *argv[] __attribute__((unused))
+)
+{
+ printf("%s\n", ttyname(fileno(stdin)));
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_TTY_Command = {
+ "tty", /* name */
+ "show ttyname", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_tty, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_umask.c b/cpukit/libmisc/shell/main_umask.c
new file mode 100644
index 0000000000..8bfbe7e443
--- /dev/null
+++ b/cpukit/libmisc/shell/main_umask.c
@@ -0,0 +1,62 @@
+/*
+ * UMASK Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include "internal.h"
+
+int rtems_shell_main_umask(
+ int argc,
+ char *argv[]
+)
+{
+ unsigned long tmp;
+ mode_t msk = umask(0);
+
+ if (argc == 2) {
+ if ( rtems_string_to_unsigned_long(argv[1], &tmp, NULL, 0) ) {
+ printf( "Mask argument (%s) is not a number\n", argv[1] );
+ return -1;
+ }
+ msk = (mode_t) tmp;
+
+ }
+ umask(msk);
+
+ msk = umask(0);
+ printf("0%o\n", (unsigned int) msk);
+ umask(msk);
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_UMASK_Command = {
+ "umask", /* name */
+ "umask [new_umask]", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_umask, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_unmount.c b/cpukit/libmisc/shell/main_unmount.c
new file mode 100644
index 0000000000..ba101dc014
--- /dev/null
+++ b/cpukit/libmisc/shell/main_unmount.c
@@ -0,0 +1,74 @@
+/*
+ * Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#include <rtems/fsmount.h>
+#include "internal.h"
+
+int rtems_shell_main_unmount(
+ int argc,
+ char *argv[]
+)
+{
+ char* mount_point = NULL;
+ int arg;
+
+ for (arg = 1; arg < argc; arg++) {
+ if (!mount_point)
+ mount_point = argv[arg];
+ else {
+ fprintf (stderr, "error: only one mount path require: %s\n", argv[arg]);
+ return 1;
+ }
+ }
+
+ if (!mount_point) {
+ fprintf (stderr, "error: no mount point\n");
+ return 1;
+ }
+
+ /*
+ * Unmount the disk.
+ */
+
+ if (unmount (mount_point) < 0) {
+ fprintf (stderr, "error: unmount failed: %s: %s\n",
+ mount_point, strerror (errno));
+ return 1;
+ }
+
+ printf ("unmounted %s\n", mount_point);
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_UNMOUNT_Command = {
+ "unmount", /* name */
+ "unmount path # unmount disk", /* usage */
+ "files", /* topic */
+ rtems_shell_main_unmount, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_unsetenv.c b/cpukit/libmisc/shell/main_unsetenv.c
new file mode 100644
index 0000000000..8805ba4341
--- /dev/null
+++ b/cpukit/libmisc/shell/main_unsetenv.c
@@ -0,0 +1,43 @@
+/*
+ * Unset an environment vairable.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_unsetenv(int argc, char *argv[])
+{
+ if (argc != 2)
+ {
+ printf ("error: only argument is the variable name\n");
+ return 1;
+ }
+
+ if (unsetenv (argv[1]) < 0)
+ {
+ printf ("error: %s\n", strerror (errno));
+ return 1;
+ }
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_UNSETENV_Command = {
+ "unsetenv", /* name */
+ "unsetenv [var]", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_unsetenv, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_whoami.c b/cpukit/libmisc/shell/main_whoami.c
new file mode 100644
index 0000000000..ce34ed95ca
--- /dev/null
+++ b/cpukit/libmisc/shell/main_whoami.c
@@ -0,0 +1,48 @@
+/*
+ * WHOAMI Shell Command Implmentation
+ *
+ * Author: Fernando RUIZ CASAS
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+int rtems_shell_main_whoami(
+ int argc __attribute__((unused)),
+ char *argv[] __attribute__((unused))
+)
+{
+ struct passwd *pwd;
+
+ pwd = getpwuid(geteuid());
+ printf( "%s\n", (pwd) ? pwd->pw_name : "nobody");
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_WHOAMI_Command = {
+ "whoami", /* name */
+ "show current user", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_whoami, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/main_wkspaceinfo.c b/cpukit/libmisc/shell/main_wkspaceinfo.c
new file mode 100644
index 0000000000..fd7c531854
--- /dev/null
+++ b/cpukit/libmisc/shell/main_wkspaceinfo.c
@@ -0,0 +1,59 @@
+/*
+ * MALLOC_INFO Shell Command Implmentation
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+
+#include <rtems.h>
+#include <rtems/malloc.h>
+#include <rtems/shell.h>
+#include <rtems/score/protectedheap.h>
+#include "internal.h"
+
+extern bool rtems_unified_work_area;
+
+void rtems_shell_print_unified_work_area_message(void)
+{
+ printf( "\nC Program Heap and RTEMS Workspace are %s.\n",
+ ((rtems_unified_work_area) ? "the same" : "separate")
+ );
+}
+
+int rtems_shell_main_wkspace_info(
+ int argc __attribute__((unused)),
+ char *argv[] __attribute__((unused))
+)
+{
+ Heap_Information_block info;
+
+ rtems_shell_print_unified_work_area_message();
+
+ _Protected_heap_Get_information( &_Workspace_Area, &info );
+ rtems_shell_print_heap_info( "free", &info.Free );
+ rtems_shell_print_heap_info( "used", &info.Used );
+
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_WKSPACE_INFO_Command = {
+ "wkspace", /* name */
+ "Report on RTEMS Executive Workspace", /* usage */
+ "rtems", /* topic */
+ rtems_shell_main_wkspace_info, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/mknod-pack_dev.c b/cpukit/libmisc/shell/mknod-pack_dev.c
new file mode 100644
index 0000000000..043019ad5a
--- /dev/null
+++ b/cpukit/libmisc/shell/mknod-pack_dev.c
@@ -0,0 +1,300 @@
+/* $NetBSD: pack_dev.c,v 1.10 2009/02/13 01:37:23 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#if 0
+#include <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: pack_dev.c,v 1.10 2009/02/13 01:37:23 lukem Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pack_dev.h"
+#endif
+
+static pack_t pack_netbsd;
+static pack_t pack_freebsd;
+static pack_t pack_8_8;
+static pack_t pack_12_20;
+static pack_t pack_14_18;
+static pack_t pack_8_24;
+static pack_t pack_bsdos;
+static int compare_format(const void *, const void *);
+
+static const char iMajorError[] = "invalid major number";
+static const char iMinorError[] = "invalid minor number";
+static const char tooManyFields[] = "too many fields for format";
+
+#define makedev(x,y) rtems_filesystem_make_dev_t(x,y)
+#define major(d) rtems_filesystem_dev_major_t(d)
+#define minor(d) rtems_filesystem_dev_minor_t(d)
+
+ /* exported */
+portdev_t
+pack_native(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev(numbers[0], numbers[1]);
+ if ((u_long)major(dev) != numbers[0])
+ *error = iMajorError;
+ else if ((u_long)minor(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+static portdev_t
+pack_netbsd(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_netbsd(numbers[0], numbers[1]);
+ if ((u_long)major_netbsd(dev) != numbers[0])
+ *error = iMajorError;
+ else if ((u_long)minor_netbsd(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
+#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0))
+#define makedev_freebsd(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \
+ (((y) << 0) & 0xffff00ff)))
+
+static portdev_t
+pack_freebsd(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_freebsd(numbers[0], numbers[1]);
+ if ((u_long)major_freebsd(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_freebsd(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
+#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
+#define makedev_8_8(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \
+ (((y) << 0) & 0x000000ff)))
+
+static portdev_t
+pack_8_8(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_8_8(numbers[0], numbers[1]);
+ if ((u_long)major_8_8(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_8_8(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20))
+#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0))
+#define makedev_12_20(x,y) ((portdev_t)((((x) << 20) & 0xfff00000) | \
+ (((y) << 0) & 0x000fffff)))
+
+static portdev_t
+pack_12_20(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_12_20(numbers[0], numbers[1]);
+ if ((u_long)major_12_20(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_12_20(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18))
+#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0))
+#define makedev_14_18(x,y) ((portdev_t)((((x) << 18) & 0xfffc0000) | \
+ (((y) << 0) & 0x0003ffff)))
+
+static portdev_t
+pack_14_18(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_14_18(numbers[0], numbers[1]);
+ if ((u_long)major_14_18(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_14_18(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24))
+#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0))
+#define makedev_8_24(x,y) ((portdev_t)((((x) << 24) & 0xff000000) | \
+ (((y) << 0) & 0x00ffffff)))
+
+static portdev_t
+pack_8_24(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_8_24(numbers[0], numbers[1]);
+ if ((u_long)major_8_24(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_8_24(dev) != numbers[1])
+ *error = iMinorError;
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20))
+#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8))
+#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
+#define makedev_12_12_8(x,y,z) ((portdev_t)((((x) << 20) & 0xfff00000) | \
+ (((y) << 8) & 0x000fff00) | \
+ (((z) << 0) & 0x000000ff)))
+
+static portdev_t
+pack_bsdos(int n, u_long numbers[], const char **error)
+{
+ portdev_t dev = 0;
+
+ if (n == 2) {
+ dev = makedev_12_20(numbers[0], numbers[1]);
+ if ((u_long)major_12_20(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)minor_12_20(dev) != numbers[1])
+ *error = iMinorError;
+ } else if (n == 3) {
+ dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
+ if ((u_long)major_12_12_8(dev) != numbers[0])
+ *error = iMajorError;
+ if ((u_long)unit_12_12_8(dev) != numbers[1])
+ *error = "invalid unit number";
+ if ((u_long)subunit_12_12_8(dev) != numbers[2])
+ *error = "invalid subunit number";
+ } else
+ *error = tooManyFields;
+ return (dev);
+}
+
+
+ /* list of formats and pack functions */
+ /* this list must be sorted lexically */
+struct format {
+ const char *name;
+ pack_t *pack;
+} formats[] = {
+ {"386bsd", pack_8_8},
+ {"4bsd", pack_8_8},
+ {"bsdos", pack_bsdos},
+ {"freebsd", pack_freebsd},
+ {"hpux", pack_8_24},
+ {"isc", pack_8_8},
+ {"linux", pack_8_8},
+ {"native", pack_native},
+ {"netbsd", pack_netbsd},
+ {"osf1", pack_12_20},
+ {"sco", pack_8_8},
+ {"solaris", pack_14_18},
+ {"sunos", pack_8_8},
+ {"svr3", pack_8_8},
+ {"svr4", pack_14_18},
+ {"ultrix", pack_8_8},
+};
+
+static int
+compare_format(const void *key, const void *element)
+{
+ const char *name;
+ const struct format *format;
+
+ name = key;
+ format = element;
+
+ return (strcmp(name, format->name));
+}
+
+
+pack_t *
+pack_find(const char *name)
+{
+ struct format *format;
+
+ format = bsearch(name, formats,
+ sizeof(formats)/sizeof(formats[0]),
+ sizeof(formats[0]), compare_format);
+ if (format == 0)
+ return (NULL);
+ return (format->pack);
+}
diff --git a/cpukit/libmisc/shell/mknod-pack_dev.h b/cpukit/libmisc/shell/mknod-pack_dev.h
new file mode 100644
index 0000000000..5c6d78af8b
--- /dev/null
+++ b/cpukit/libmisc/shell/mknod-pack_dev.h
@@ -0,0 +1,52 @@
+/* $NetBSD: pack_dev.h,v 1.7 2008/04/28 20:23:09 martin Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _PACK_DEV_H
+#define _PACK_DEV_H
+
+#ifdef __CYGWIN__
+typedef __dev32_t portdev_t;
+#else
+typedef dev_t portdev_t;
+#endif
+typedef portdev_t pack_t(int, u_long [], const char **);
+
+static pack_t *pack_find(const char *);
+static pack_t pack_native;
+
+#define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8)))
+#define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \
+ (((x) & 0x000000ff) >> 0)))
+#define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \
+ (((y) << 12) & 0xfff00000) | \
+ (((y) << 0) & 0x000000ff)))
+
+#endif /* _PACK_DEV_H */
diff --git a/cpukit/libmisc/shell/pathnames-mv.h b/cpukit/libmisc/shell/pathnames-mv.h
new file mode 100644
index 0000000000..a38e4e9450
--- /dev/null
+++ b/cpukit/libmisc/shell/pathnames-mv.h
@@ -0,0 +1,40 @@
+/* $NetBSD: pathnames.h,v 1.8 2004/08/19 22:26:07 christos Exp $ */
+
+/*
+ * 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. 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.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 5/31/93
+ */
+
+#ifdef RESCUEDIR
+#define _PATH_RM RESCUEDIR "/rm"
+#define _PATH_CP RESCUEDIR "/cp"
+#else
+#define _PATH_RM "/bin/rm"
+#define _PATH_CP "/bin/cp"
+#endif
diff --git a/cpukit/libmisc/shell/print-ls.c b/cpukit/libmisc/shell/print-ls.c
new file mode 100644
index 0000000000..c19ce9009c
--- /dev/null
+++ b/cpukit/libmisc/shell/print-ls.c
@@ -0,0 +1,492 @@
+/* $NetBSD: print.c,v 1.40 2004/11/17 17:00:00 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Fischbein.
+ *
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if 0
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)print.c 8.5 (Berkeley) 7/28/94";
+#else
+__RCSID("$NetBSD: print.c,v 1.40 2004/11/17 17:00:00 mycroft Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <inttypes.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+//#include <tzfile.h>
+#include <unistd.h>
+//#include <util.h>
+
+#include "extern-ls.h"
+
+#define DAYSPERNYEAR ((time_t)365)
+#define SECSPERDAY ((time_t)60 * (time_t)60 * (time_t)24)
+
+
+#if RTEMS_REMOVED
+extern int termwidth;
+#endif
+
+static int printaname(rtems_shell_ls_globals* globals, FTSENT *, int, int);
+static void printlink(rtems_shell_ls_globals* globals, FTSENT *);
+static void printtime(rtems_shell_ls_globals* globals, time_t);
+static int printtype(u_int);
+
+#if RTEMS_REMOVED
+static time_t now;
+#endif
+
+#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
+
+void
+printscol(rtems_shell_ls_globals* globals, DISPLAY *dp)
+{
+ FTSENT *p;
+
+ for (p = dp->list; p; p = p->fts_link) {
+ if (IS_NOPRINT(p))
+ continue;
+ (void)printaname(globals, p, dp->s_inode, dp->s_block);
+ (void)putchar('\n');
+ }
+}
+
+void
+printlong(rtems_shell_ls_globals* globals, DISPLAY *dp)
+{
+ struct stat *sp;
+ FTSENT *p;
+ NAMES *np;
+ char buf[20]; //, szbuf[5];
+
+ now = time(NULL);
+
+ if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
+#if RTEMS_REMOVED
+ if (f_humanize) {
+ if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal,
+ "", HN_AUTOSCALE,
+ (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
+ err(exit_jump, 1, "humanize_number");
+ (void)printf("total %s\n", szbuf);
+ } else {
+#endif
+ (void)printf("total %llu\n",
+ (long long)(howmany(dp->btotal, blocksize)));
+#if RTEMS_REMOVED
+ }
+#endif
+ }
+
+ for (p = dp->list; p; p = p->fts_link) {
+ if (IS_NOPRINT(p))
+ continue;
+ sp = p->fts_statp;
+ if (f_inode)
+ (void)printf("%*lu ", dp->s_inode, sp->st_ino);
+ if (f_size && !f_humanize) {
+ (void)printf("%*llu ", dp->s_block,
+ (long long)howmany(sp->st_blocks, blocksize));
+ }
+ (void)strmode(sp->st_mode, buf);
+ np = p->fts_pointer;
+ (void)printf("%s %*lu ", buf, dp->s_nlink,
+ (unsigned long)sp->st_nlink);
+ if (!f_grouponly)
+ (void)printf("%-*s ", dp->s_user, np->user);
+ (void)printf("%-*s ", dp->s_group, np->group);
+ if (f_flags)
+ (void)printf("%-*s ", dp->s_flags, np->flags);
+ if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
+ (void)printf("%*"PRIu32", %*"PRIu32" ",
+ dp->s_major, major(sp->st_rdev), dp->s_minor,
+ minor(sp->st_rdev));
+ else
+#if RTEMS_REMOVED
+ if (f_humanize) {
+ if ((humanize_number(szbuf, sizeof(szbuf),
+ sp->st_size, "", HN_AUTOSCALE,
+ (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
+ err(1, "humanize_number");
+ (void)printf("%*s ", dp->s_size, szbuf);
+ } else {
+#endif
+ {
+ unsigned long long size;
+ if (sp->st_size < 0)
+ size = sp->st_size * -1;
+ else
+ size = sp->st_size;
+ (void)printf("%*llu ", dp->s_size, size);
+ }
+ if (f_accesstime)
+ printtime(globals, sp->st_atime);
+ else if (f_statustime)
+ printtime(globals, sp->st_ctime);
+ else
+ printtime(globals, sp->st_mtime);
+ if (f_octal || f_octal_escape)
+ (void)safe_print(globals, p->fts_name);
+ else if (f_nonprint)
+ (void)printescaped(globals, p->fts_name);
+ else
+ (void)printf("%s", p->fts_name);
+
+ if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
+ (void)printtype(sp->st_mode);
+ if (S_ISLNK(sp->st_mode))
+ printlink(globals, p);
+ (void)putchar('\n');
+ }
+}
+
+void
+printcol(rtems_shell_ls_globals* globals, DISPLAY *dp)
+{
+ static FTSENT **array;
+ static int lastentries = -1;
+ FTSENT *p;
+ int base, chcnt, col, colwidth, num;
+ int numcols, numrows, row;
+ //char szbuf[5];
+
+ colwidth = dp->maxlen;
+ if (f_inode)
+ colwidth += dp->s_inode + 1;
+ if (f_size) {
+ if (f_humanize)
+ colwidth += dp->s_size + 1;
+ else
+ colwidth += dp->s_block + 1;
+ }
+ if (f_type || f_typedir)
+ colwidth += 1;
+
+ colwidth += 1;
+
+ if (termwidth < 2 * colwidth) {
+ printscol(globals, dp);
+ return;
+ }
+
+ /*
+ * Have to do random access in the linked list -- build a table
+ * of pointers.
+ */
+ if (dp->entries > lastentries) {
+ lastentries = dp->entries;
+ if ((array =
+ realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
+ warn(NULL);
+ printscol(globals, dp);
+ }
+ }
+ for (p = dp->list, num = 0; p; p = p->fts_link)
+ if (p->fts_number != NO_PRINT)
+ array[num++] = p;
+
+ numcols = termwidth / colwidth;
+ colwidth = termwidth / numcols; /* spread out if possible */
+ numrows = num / numcols;
+ if (num % numcols)
+ ++numrows;
+
+ if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
+#if RTEMS_REMOVED
+ if (f_humanize) {
+ if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal,
+ "", HN_AUTOSCALE,
+ (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
+ err(1, "humanize_number");
+ (void)printf("total %s\n", szbuf);
+ } else {
+#endif
+ (void)printf("total %llu\n",
+ (long long)(howmany(dp->btotal, blocksize)));
+#if RTEMS_REMOVED
+ }
+#endif
+ }
+ for (row = 0; row < numrows; ++row) {
+ for (base = row, chcnt = col = 0; col < numcols; ++col) {
+ chcnt = printaname(globals, array[base], dp->s_inode,
+ f_humanize && 0 ? dp->s_size : dp->s_block);
+ if ((base += numrows) >= num)
+ break;
+ while (chcnt++ < colwidth)
+ (void)putchar(' ');
+ }
+ (void)putchar('\n');
+ }
+}
+
+void
+printacol(rtems_shell_ls_globals* globals, DISPLAY *dp)
+{
+ FTSENT *p;
+ int chcnt, col, colwidth;
+ int numcols;
+ //char szbuf[5];
+
+ colwidth = dp->maxlen;
+ if (f_inode)
+ colwidth += dp->s_inode + 1;
+ if (f_size) {
+ if (f_humanize)
+ colwidth += dp->s_size + 1;
+ else
+ colwidth += dp->s_block + 1;
+ }
+ if (f_type || f_typedir)
+ colwidth += 1;
+
+ colwidth += 1;
+
+ if (termwidth < 2 * colwidth) {
+ printscol(globals, dp);
+ return;
+ }
+
+ numcols = termwidth / colwidth;
+ colwidth = termwidth / numcols; /* spread out if possible */
+
+ if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
+#if RTEMS_REMOVED
+ if (f_humanize) {
+ if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal,
+ "", HN_AUTOSCALE,
+ (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
+ err(1, "humanize_number");
+ (void)printf("total %s\n", szbuf);
+ } else {
+#endif
+ (void)printf("total %llu\n",
+ (long long)(howmany(dp->btotal, blocksize)));
+#if RTEMS_REMOVED
+ }
+#endif
+ }
+ chcnt = col = 0;
+ for (p = dp->list; p; p = p->fts_link) {
+ if (IS_NOPRINT(p))
+ continue;
+ if (col >= numcols) {
+ chcnt = col = 0;
+ (void)putchar('\n');
+ }
+ chcnt = printaname(globals, p, dp->s_inode,
+ f_humanize && 0 ? dp->s_size : dp->s_block);
+ while (chcnt++ < colwidth)
+ (void)putchar(' ');
+ col++;
+ }
+ (void)putchar('\n');
+}
+
+void
+printstream(rtems_shell_ls_globals* globals, DISPLAY *dp)
+{
+ FTSENT *p;
+ int col;
+ int extwidth;
+
+ extwidth = 0;
+ if (f_inode)
+ extwidth += dp->s_inode + 1;
+ if (f_size) {
+ if (f_humanize)
+ extwidth += dp->s_size + 1;
+ else
+ extwidth += dp->s_block + 1;
+ }
+ if (f_type)
+ extwidth += 1;
+
+ for (col = 0, p = dp->list; p != NULL; p = p->fts_link) {
+ if (IS_NOPRINT(p))
+ continue;
+ if (col > 0) {
+ (void)putchar(','), col++;
+ if (col + 1 + extwidth + p->fts_namelen >= termwidth)
+ (void)putchar('\n'), col = 0;
+ else
+ (void)putchar(' '), col++;
+ }
+ col += printaname(globals, p, dp->s_inode,
+ f_humanize && 0 ? dp->s_size : dp->s_block);
+ }
+ (void)putchar('\n');
+}
+
+/*
+ * print [inode] [size] name
+ * return # of characters printed, no trailing characters.
+ */
+static int
+printaname(rtems_shell_ls_globals* globals,
+ FTSENT *p, int inodefield, int sizefield)
+{
+ struct stat *sp;
+ int chcnt;
+ //char szbuf[5];
+
+ sp = p->fts_statp;
+ chcnt = 0;
+ if (f_inode)
+ chcnt += printf("%*lu ", inodefield, sp->st_ino);
+ if (f_size) {
+#if RTEMS_REMOVED
+ if (f_humanize) {
+ if ((humanize_number(szbuf, sizeof(szbuf), sp->st_size,
+ "", HN_AUTOSCALE,
+ (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
+ err(1, "humanize_number");
+ chcnt += printf("%*s ", sizefield, szbuf);
+ } else {
+#endif
+ chcnt += printf("%*llu ", sizefield,
+ (long long)howmany(sp->st_blocks, blocksize));
+#if RTEMS_REMOVED
+ }
+#endif
+ }
+ if (f_octal || f_octal_escape)
+ chcnt += safe_print(globals, p->fts_name);
+ else if (f_nonprint)
+ chcnt += printescaped(globals, p->fts_name);
+ else
+ chcnt += printf("%s", p->fts_name);
+ if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
+ chcnt += printtype(sp->st_mode);
+ return (chcnt);
+}
+
+static void
+printtime(rtems_shell_ls_globals* globals, time_t ftime)
+{
+ int i;
+ char *longstring;
+
+ longstring = ctime(&ftime);
+ for (i = 4; i < 11; ++i)
+ (void)putchar(longstring[i]);
+
+#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
+ if (f_sectime)
+ for (i = 11; i < 24; i++)
+ (void)putchar(longstring[i]);
+ else if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now)
+ for (i = 11; i < 16; ++i)
+ (void)putchar(longstring[i]);
+ else {
+ (void)putchar(' ');
+ for (i = 20; i < 24; ++i)
+ (void)putchar(longstring[i]);
+ }
+ (void)putchar(' ');
+}
+
+static int
+printtype(u_int mode)
+{
+ switch (mode & S_IFMT) {
+ case S_IFDIR:
+ (void)putchar('/');
+ return (1);
+ case S_IFIFO:
+ (void)putchar('|');
+ return (1);
+ case S_IFLNK:
+ (void)putchar('@');
+ return (1);
+ case S_IFSOCK:
+ (void)putchar('=');
+ return (1);
+#if RTEMS_REMOVED
+ case S_IFWHT:
+ (void)putchar('%');
+ return (1);
+#endif
+ }
+ if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
+ (void)putchar('*');
+ return (1);
+ }
+ return (0);
+}
+
+static void
+printlink(rtems_shell_ls_globals* globals, FTSENT *p)
+{
+ int lnklen;
+ char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
+
+ if (p->fts_level == FTS_ROOTLEVEL)
+ (void)snprintf(name, sizeof(name), "%s", p->fts_name);
+ else
+ (void)snprintf(name, sizeof(name),
+ "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
+ if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
+ (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
+ return;
+ }
+ path[lnklen] = '\0';
+ (void)printf(" -> ");
+ if (f_octal || f_octal_escape)
+ (void)safe_print(globals, path);
+ else if (f_nonprint)
+ (void)printescaped(globals, path);
+ else
+ (void)printf("%s", path);
+}
diff --git a/cpukit/libmisc/shell/print_heapinfo.c b/cpukit/libmisc/shell/print_heapinfo.c
new file mode 100644
index 0000000000..ad6db121d2
--- /dev/null
+++ b/cpukit/libmisc/shell/print_heapinfo.c
@@ -0,0 +1,37 @@
+/*
+ * Print Heap Information Structure
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+void rtems_shell_print_heap_info(
+ const char *c,
+ Heap_Information *h
+)
+{
+ printf(
+ "Number of %s blocks: %" PRId32 "\n"
+ "Largest %s block: %" PRId32 "\n"
+ "Total bytes %s: %" PRId32 "\n",
+ c, h->number,
+ c, h->largest,
+ c, h->total
+ );
+}
diff --git a/cpukit/libmisc/shell/pwcache.c b/cpukit/libmisc/shell/pwcache.c
new file mode 100644
index 0000000000..47b8e96fc6
--- /dev/null
+++ b/cpukit/libmisc/shell/pwcache.c
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)pwcache.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/pwcache.c,v 1.11 2007/01/09 00:27:55 imp Exp $");
+
+#include <sys/types.h>
+
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+//#include <utmp.h>
+
+#define UT_NAMESIZE 64
+
+#define NCACHE 64 /* power of 2 */
+#define MASK (NCACHE - 1) /* bits to store with */
+
+const char *
+user_from_uid(uid_t uid, int nouser)
+{
+ static struct ncache {
+ uid_t uid;
+ int found;
+ char name[UT_NAMESIZE + 1];
+ } c_uid[NCACHE];
+ static int pwopen;
+ struct passwd *pw;
+ struct ncache *cp;
+
+ cp = c_uid + (uid & MASK);
+ if (cp->uid != uid || !*cp->name) {
+ if (pwopen == 0) {
+ //setpassent(1);
+ pwopen = 1;
+ }
+ pw = getpwuid(uid);
+ cp->uid = uid;
+ if (pw != NULL) {
+ cp->found = 1;
+ (void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE);
+ cp->name[UT_NAMESIZE] = '\0';
+ } else {
+ cp->found = 0;
+ (void)snprintf(cp->name, UT_NAMESIZE, "%u", uid);
+ if (nouser)
+ return (NULL);
+ }
+ }
+ return ((nouser && !cp->found) ? NULL : cp->name);
+}
+
+char *
+group_from_gid(gid_t gid, int nogroup)
+{
+ static struct ncache {
+ gid_t gid;
+ int found;
+ char name[UT_NAMESIZE + 1];
+ } c_gid[NCACHE];
+ static int gropen;
+ struct group *gr;
+ struct ncache *cp;
+
+ cp = c_gid + (gid & MASK);
+ if (cp->gid != gid || !*cp->name) {
+ if (gropen == 0) {
+ //setgroupent(1);
+ gropen = 1;
+ }
+ gr = getgrgid(gid);
+ cp->gid = gid;
+ if (gr != NULL) {
+ cp->found = 1;
+ (void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE);
+ cp->name[UT_NAMESIZE] = '\0';
+ } else {
+ cp->found = 0;
+ (void)snprintf(cp->name, UT_NAMESIZE, "%u", gid);
+ if (nogroup)
+ return (NULL);
+ }
+ }
+ return ((nogroup && !cp->found) ? NULL : cp->name);
+}
+
diff --git a/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c
new file mode 100644
index 0000000000..bcc146731b
--- /dev/null
+++ b/cpukit/libmisc/shell/shell.c
@@ -0,0 +1,987 @@
+/*
+ *
+ * Instantatiate a new terminal shell.
+ *
+ * Author:
+ *
+ * WORK: fernando.ruiz@ctv.es
+ * HOME: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <time.h>
+
+#include <rtems.h>
+#include <rtems/error.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/system.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#include <rtems/console.h>
+#include "internal.h"
+
+#include <termios.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pwd.h>
+
+rtems_shell_env_t rtems_global_shell_env = {
+ .magic = rtems_build_name('S', 'E', 'N', 'V'),
+ .devname = CONSOLE_DEVICE_NAME,
+ .taskname = "SHGL",
+ .exit_shell = false,
+ .forever = true,
+ .errorlevel = -1,
+ .echo = false,
+ .cwd = "/",
+ .input = NULL,
+ .output = NULL,
+ .output_append = false,
+ .wake_on_end = RTEMS_ID_NONE,
+ .login_check = NULL
+};
+
+rtems_shell_env_t *rtems_current_shell_env = &rtems_global_shell_env;
+
+/*
+ * Initialize the shell user/process environment information
+ */
+rtems_shell_env_t *rtems_shell_init_env(
+ rtems_shell_env_t *shell_env_p
+)
+{
+ rtems_shell_env_t *shell_env;
+
+ shell_env = malloc(sizeof(rtems_shell_env_t));
+ if ( !shell_env )
+ return NULL;
+ if ( !shell_env_p ) {
+ *shell_env = rtems_global_shell_env;
+ } else {
+ *shell_env = *shell_env_p;
+ }
+ shell_env->taskname = NULL;
+
+ return shell_env;
+}
+
+/*
+ * Completely free a shell_env_t and all associated memory
+ */
+void rtems_shell_env_free(
+ void *ptr
+)
+{
+ rtems_shell_env_t *shell_env;
+ shell_env = (rtems_shell_env_t *) ptr;
+
+ if ( !ptr )
+ return;
+
+ if ( shell_env->input )
+ free((void *)shell_env->input);
+ if ( shell_env->output )
+ free((void *)shell_env->output);
+ free( ptr );
+}
+
+/*
+ * Get a line of user input with modest features
+ */
+int rtems_shell_line_editor(
+ char *cmds[],
+ int count,
+ int size,
+ const char *prompt,
+ FILE *in,
+ FILE *out
+)
+{
+ unsigned int extended_key;
+ int c;
+ int col;
+ int last_col;
+ int output;
+ char line[size];
+ char new_line[size];
+ int up;
+ int cmd = -1;
+ int inserting = 1;
+
+ output = (out && isatty(fileno(in)));
+
+ col = last_col = 0;
+
+ tcdrain(fileno(in));
+ if (out)
+ tcdrain(fileno(out));
+
+ if (output && prompt)
+ fprintf(out, "\r%s", prompt);
+
+ line[0] = 0;
+ new_line[0] = 0;
+
+ for (;;) {
+
+ if (output)
+ fflush(out);
+
+ extended_key = rtems_shell_getchar(in);
+
+ if (extended_key == EOF)
+ return -2;
+
+ c = extended_key & RTEMS_SHELL_KEYS_NORMAL_MASK;
+
+ /*
+ * Make the extended_key usable as a boolean.
+ */
+ extended_key &= ~RTEMS_SHELL_KEYS_NORMAL_MASK;
+
+ up = 0;
+
+ if (extended_key)
+ {
+ switch (c)
+ {
+ case RTEMS_SHELL_KEYS_END:
+ if (output)
+ fprintf(out, "%s", line + col);
+ col = (int) strlen (line);
+ break;
+
+ case RTEMS_SHELL_KEYS_HOME:
+ if (output) {
+ if (prompt)
+ fprintf(out,"\r%s", prompt);
+ }
+ col = 0;
+ break;
+
+ case RTEMS_SHELL_KEYS_LARROW:
+ if (col > 0)
+ {
+ col--;
+ if (output)
+ fputc('\b', out);
+ }
+ break;
+
+ case RTEMS_SHELL_KEYS_RARROW:
+ if ((col < size) && (line[col] != '\0'))
+ {
+ if (output)
+ fprintf(out, "%c", line[col]);
+ col++;
+ }
+ break;
+
+ case RTEMS_SHELL_KEYS_UARROW:
+ if ((cmd >= (count - 1)) || (strlen(cmds[cmd + 1]) == 0)) {
+ if (output)
+ fputc('\x7', out);
+ break;
+ }
+
+ up = 1;
+
+ /* drop through */
+ case RTEMS_SHELL_KEYS_DARROW:
+
+ {
+ int last_cmd = cmd;
+ int clen = strlen (line);
+
+ if (prompt)
+ clen += strlen(prompt);
+
+ if (up) {
+ cmd++;
+ } else {
+ if (cmd < 0) {
+ if (output)
+ fprintf(out, "\x7");
+ break;
+ }
+ else
+ cmd--;
+ }
+
+ if ((last_cmd < 0) || (strcmp(cmds[last_cmd], line) != 0))
+ memcpy (new_line, line, size);
+
+ if (cmd < 0)
+ memcpy (line, new_line, size);
+ else
+ memcpy (line, cmds[cmd], size);
+
+ col = strlen (line);
+
+ if (output) {
+ fprintf(out,"\r%*c", clen, ' ');
+ fprintf(out,"\r%s%s", prompt, line);
+ }
+ }
+ break;
+
+ case RTEMS_SHELL_KEYS_DEL:
+ if (line[col] != '\0')
+ {
+ int end;
+ int bs;
+ strcpy (&line[col], &line[col + 1]);
+ if (output) {
+ fprintf(out,"\r%s%s ", prompt, line);
+ end = (int) strlen (line);
+ for (bs = 0; bs < ((end - col) + 1); bs++)
+ fputc('\b', out);
+ }
+ }
+ break;
+
+ case RTEMS_SHELL_KEYS_INS:
+ inserting = inserting ? 0 : 1;
+ break;
+ }
+ }
+ else
+ {
+ switch (c)
+ {
+ case 1:/*Control-a*/
+ if (output) {
+ if (prompt)
+ fprintf(out,"\r%s", prompt);
+ }
+ col = 0;
+ break;
+
+ case 5:/*Control-e*/
+ if (output)
+ fprintf(out, "%s", line + col);
+ col = (int) strlen (line);
+ break;
+
+ case 11:/*Control-k*/
+ if (line[col]) {
+ if (output) {
+ int end = strlen(line);
+ int bs;
+ fprintf(out,"%*c", end - col, ' ');
+ for (bs = 0; bs < (end - col); bs++)
+ fputc('\b', out);
+ }
+ line[col] = '\0';
+ }
+ break;
+
+ case 0x04:/*Control-d*/
+ if (strlen(line))
+ break;
+ case EOF:
+ if (output)
+ fputc('\n', out);
+ return -2;
+
+ case '\f':
+ if (output) {
+ int end;
+ int bs;
+ fputc('\f',out);
+ fprintf(out,"\r%s%s", prompt, line);
+ end = (int) strlen (line);
+ for (bs = 0; bs < (end - col); bs++)
+ fputc('\b', out);
+ }
+ break;
+
+ case '\b':
+ case '\x7f':
+ if (col > 0)
+ {
+ int bs;
+ col--;
+ strcpy (line + col, line + col + 1);
+ if (output) {
+ fprintf(out,"\b%s \b", line + col);
+ for (bs = 0; bs < ((int) strlen (line) - col); bs++)
+ fputc('\b', out);
+ }
+ }
+ break;
+
+ case '\n':
+ case '\r':
+ {
+ /*
+ * Process the command.
+ */
+ if (output)
+ fprintf(out,"\n");
+
+ /*
+ * Only process the command if we have a command and it is not
+ * repeated in the history.
+ */
+ if (strlen(line) == 0) {
+ cmd = -1;
+ } else {
+ if ((cmd < 0) || (strcmp(line, cmds[cmd]) != 0)) {
+ if (count > 1)
+ memmove(cmds[1], cmds[0], (count - 1) * size);
+ memmove (cmds[0], line, size);
+ cmd = 0;
+ }
+ }
+ }
+ return cmd;
+
+ default:
+ if ((col < (size - 1)) && (c >= ' ') && (c <= '~')) {
+ int end = strlen (line);
+ if (inserting && (col < end) && (end < size)) {
+ int ch, bs;
+ for (ch = end + 1; ch > col; ch--)
+ line[ch] = line[ch - 1];
+ if (output) {
+ fprintf(out, "%s", line + col);
+ for (bs = 0; bs < (end - col + 1); bs++)
+ fputc('\b', out);
+ }
+ }
+ line[col++] = c;
+ if (col > end)
+ line[col] = '\0';
+ if (output)
+ fputc(c, out);
+ }
+ break;
+ }
+ }
+ }
+ return -2;
+}
+
+/* ----------------------------------------------- *
+ * - The shell TASK
+ * Poor but enough..
+ * TODO: Redirection. Tty Signals. ENVVARs. Shell language.
+ * ----------------------------------------------- */
+
+void rtems_shell_init_issue(void)
+{
+ static bool issue_inited=false;
+ struct stat buf;
+
+ if (issue_inited)
+ return;
+ issue_inited = true;
+
+ /* dummy call to init /etc dir */
+ getpwnam("root");
+
+ if (stat("/etc/issue",&buf)) {
+ rtems_shell_write_file("/etc/issue",
+ "\n"
+ "Welcome to @V\\n"
+ "Login into @S\\n");
+ }
+
+ if (stat("/etc/issue.net",&buf)) {
+ rtems_shell_write_file("/etc/issue.net",
+ "\n"
+ "Welcome to %v\n"
+ "running on %m\n");
+ }
+}
+
+static bool rtems_shell_login(FILE * in,FILE * out) {
+ FILE *fd;
+ int c;
+ time_t t;
+
+ rtems_shell_init_issue();
+ setuid(0);
+ setgid(0);
+ rtems_current_user_env->euid =
+ rtems_current_user_env->egid =0;
+
+ if (out) {
+ if ((rtems_current_shell_env->devname[5]!='p')||
+ (rtems_current_shell_env->devname[6]!='t')||
+ (rtems_current_shell_env->devname[7]!='y')) {
+ fd = fopen("/etc/issue","r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) {
+ if (c=='@') {
+ switch(c=fgetc(fd)) {
+ case 'L':
+ fprintf(out,"%s",rtems_current_shell_env->devname);
+ break;
+ case 'B':
+ fprintf(out,"0");
+ break;
+ case 'T':
+ case 'D':
+ time(&t);
+ fprintf(out,"%s",ctime(&t));
+ break;
+ case 'S':
+ fprintf(out,"RTEMS");
+ break;
+ case 'V':
+ fprintf(out,"%s\n%s",_RTEMS_version, _Copyright_Notice);
+ break;
+ case '@':
+ fprintf(out,"@");
+ break;
+ default :
+ fprintf(out,"@%c",c);
+ break;
+ }
+ } else if (c=='\\') {
+ switch(c=fgetc(fd)) {
+ case '\\': fprintf(out,"\\"); break;
+ case 'b': fprintf(out,"\b"); break;
+ case 'f': fprintf(out,"\f"); break;
+ case 'n': fprintf(out,"\n"); break;
+ case 'r': fprintf(out,"\r"); break;
+ case 's': fprintf(out," "); break;
+ case 't': fprintf(out,"\t"); break;
+ case '@': fprintf(out,"@"); break;
+ }
+ } else {
+ fputc(c,out);
+ }
+ }
+ fclose(fd);
+ }
+ } else {
+ fd = fopen("/etc/issue.net","r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) {
+ if (c=='%') {
+ switch(c=fgetc(fd)) {
+ case 't':
+ fprintf(out,"%s",rtems_current_shell_env->devname);
+ break;
+ case 'h':
+ fprintf(out,"0");
+ break;
+ case 'D':
+ fprintf(out," ");
+ break;
+ case 'd':
+ time(&t);
+ fprintf(out,"%s",ctime(&t));
+ break;
+ case 's':
+ fprintf(out,"RTEMS");
+ break;
+ case 'm':
+ fprintf(out,"(" CPU_NAME "/" CPU_MODEL_NAME ")");
+ break;
+ case 'r':
+ fprintf(out,_RTEMS_version);
+ break;
+ case 'v':
+ fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice);
+ break;
+ case '%':fprintf(out,"%%");
+ break;
+ default:
+ fprintf(out,"%%%c",c);
+ break;
+ }
+ } else {
+ fputc(c,out);
+ }
+ }
+ fclose(fd);
+ }
+ }
+ }
+
+ return rtems_shell_login_prompt(
+ in,
+ out,
+ rtems_current_shell_env->devname,
+ rtems_current_shell_env->login_check
+ );
+}
+
+#if defined(SHELL_DEBUG)
+void rtems_shell_print_env(
+ rtems_shell_env_t * shell_env
+)
+{
+ if ( !shell_env ) {
+ printk( "shell_env is NULL\n" );
+ return;
+ }
+ printk( "shell_env=%p\n"
+ "shell_env->magic=0x%08x\t"
+ "shell_env->devname=%s\n"
+ "shell_env->taskname=%s\t"
+ "shell_env->exit_shell=%d\t"
+ "shell_env->forever=%d\n",
+ shell_env->magic,
+ shell_env->devname,
+ ((shell_env->taskname) ? shell_env->taskname : "NOT SET"),
+ shell_env->exit_shell,
+ shell_env->forever
+ );
+}
+#endif
+
+rtems_task rtems_shell_task(rtems_task_argument task_argument)
+{
+ rtems_shell_env_t *shell_env = (rtems_shell_env_t*) task_argument;
+ rtems_id wake_on_end = shell_env->wake_on_end;
+ rtems_shell_main_loop( shell_env );
+ if (wake_on_end != RTEMS_INVALID_ID)
+ rtems_event_send (wake_on_end, RTEMS_EVENT_1);
+ rtems_task_delete( RTEMS_SELF );
+}
+
+#define RTEMS_SHELL_MAXIMUM_ARGUMENTS (128)
+#define RTEMS_SHELL_CMD_SIZE (128)
+#define RTEMS_SHELL_CMD_COUNT (32)
+#define RTEMS_SHELL_PROMPT_SIZE (128)
+
+bool rtems_shell_main_loop(
+ rtems_shell_env_t *shell_env_arg
+)
+{
+ rtems_shell_env_t *shell_env;
+ rtems_shell_cmd_t *shell_cmd;
+ rtems_status_code sc;
+ struct termios term;
+ struct termios previous_term;
+ char *prompt = NULL;
+ int cmd;
+ int cmd_count = 1; /* assume a script and so only 1 command line */
+ char *cmds[RTEMS_SHELL_CMD_COUNT];
+ char *cmd_argv;
+ int argc;
+ char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS];
+ bool result = true;
+ bool input_file = false;
+ int line = 0;
+ FILE *stdinToClose = NULL;
+ FILE *stdoutToClose = NULL;
+
+ rtems_shell_initialize_command_set();
+
+ shell_env =
+ rtems_current_shell_env = rtems_shell_init_env( shell_env_arg );
+
+ /*
+ * @todo chrisj
+ * Remove the use of task variables. Change to have a single
+ * allocation per shell and then set into a notepad register
+ * in the TCB. Provide a function to return the pointer.
+ * Task variables are a virus to embedded systems software.
+ */
+ sc = rtems_task_variable_add(
+ RTEMS_SELF,
+ (void*)&rtems_current_shell_env,
+ rtems_shell_env_free
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"rtems_task_variable_add(current_shell_env):");
+ return false;
+ }
+
+ setuid(0);
+ setgid(0);
+
+ rtems_current_user_env->euid = rtems_current_user_env->egid = 0;
+
+ fileno(stdout);
+
+ /* fprintf( stderr,
+ "-%s-%s-\n", shell_env->input, shell_env->output );
+ */
+
+ if (shell_env->output && strcmp(shell_env->output, "stdout") != 0) {
+ if (strcmp(shell_env->output, "stderr") == 0) {
+ stdout = stderr;
+ } else if (strcmp(shell_env->output, "/dev/null") == 0) {
+ fclose (stdout);
+ } else {
+ FILE *output = fopen(shell_env_arg->output,
+ shell_env_arg->output_append ? "a" : "w");
+ if (!output) {
+ fprintf(stderr, "shell: open output %s failed: %s\n",
+ shell_env_arg->output, strerror(errno));
+ return false;
+ }
+ stdout = output;
+ stdoutToClose = output;
+ }
+ }
+
+ if (shell_env->input && strcmp(shell_env_arg->input, "stdin") != 0) {
+ FILE *input = fopen(shell_env_arg->input, "r");
+ if (!input) {
+ fprintf(stderr, "shell: open input %s failed: %s\n",
+ shell_env_arg->input, strerror(errno));
+ return false;
+ }
+ stdin = input;
+ stdinToClose = input;
+ shell_env->forever = false;
+ input_file =true;
+ }
+ else {
+ /* make a raw terminal,Linux Manuals */
+ if (tcgetattr(fileno(stdin), &previous_term) >= 0) {
+ term = previous_term;
+ term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ term.c_oflag &= ~OPOST;
+ term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */
+ term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ term.c_cflag |= CLOCAL | CREAD;
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+ if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) {
+ fprintf(stderr,
+ "shell:cannot set terminal attributes(%s)\n",shell_env->devname);
+ }
+ }
+ cmd_count = RTEMS_SHELL_CMD_COUNT;
+ prompt = malloc(RTEMS_SHELL_PROMPT_SIZE);
+ if (!prompt)
+ fprintf(stderr,
+ "shell:cannot allocate prompt memory\n");
+ }
+
+ setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/
+ setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/
+
+ rtems_shell_initialize_command_set();
+
+ /*
+ * Allocate the command line buffers.
+ */
+ cmd_argv = malloc (RTEMS_SHELL_CMD_SIZE);
+ if (!cmd_argv) {
+ fprintf(stderr, "no memory for command line buffers\n" );
+ }
+
+ cmds[0] = calloc (cmd_count, RTEMS_SHELL_CMD_SIZE);
+ if (!cmds[0]) {
+ fprintf(stderr, "no memory for command line buffers\n" );
+ }
+
+ if (cmd_argv && cmds[0]) {
+
+ memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
+
+ for (cmd = 1; cmd < cmd_count; cmd++) {
+ cmds[cmd] = cmds[cmd - 1] + RTEMS_SHELL_CMD_SIZE;
+ }
+
+ do {
+ /* Set again root user and root filesystem, side effect of set_priv..*/
+ sc = rtems_libio_set_private_env();
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"rtems_libio_set_private_env():");
+ result = false;
+ break;
+ }
+
+ /*
+ * By using result here, we can fall to the bottom of the
+ * loop when the connection is dropped during login and
+ * keep on trucking.
+ */
+ if (shell_env->login_check != NULL) {
+ result = rtems_shell_login(stdin,stdout);
+ } else {
+ result = true;
+ }
+
+ if (result) {
+ const char *c;
+ memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
+ if (!input_file) {
+ rtems_shell_cat_file(stdout,"/etc/motd");
+ fprintf(stdout, "\n"
+ "RTEMS SHELL (Ver.1.0-FRC):%s. " \
+ __DATE__". 'help' to list commands.\n",
+ shell_env->devname);
+ }
+
+ if (input_file)
+ chdir(shell_env->cwd);
+ else
+ chdir("/"); /* XXX: chdir to getpwent homedir */
+
+ shell_env->exit_shell = false;
+
+ for (;;) {
+ int cmd;
+
+ /* Prompt section */
+ if (prompt) {
+ rtems_shell_get_prompt(shell_env, prompt,
+ RTEMS_SHELL_PROMPT_SIZE);
+ }
+
+ /* getcmd section */
+ cmd = rtems_shell_line_editor(cmds, cmd_count,
+ RTEMS_SHELL_CMD_SIZE, prompt,
+ stdin, stdout);
+
+ if (cmd == -1)
+ continue; /* empty line */
+
+ if (cmd == -2)
+ break; /*EOF*/
+
+ line++;
+
+ if (shell_env->echo)
+ fprintf(stdout, "%d: %s\n", line, cmds[cmd]);
+
+ /* evaluate cmd section */
+ c = cmds[cmd];
+ while (*c) {
+ if (!isblank((unsigned char)*c))
+ break;
+ c++;
+ }
+
+ if (*c == '\0') /* empty line */
+ continue;
+
+ if (*c == '#') { /* comment character */
+ cmds[cmd][0] = 0;
+ continue;
+ }
+
+ if (!strcmp(cmds[cmd],"bye") || !strcmp(cmds[cmd],"exit")) {
+ fprintf(stdout, "Shell exiting\n" );
+ break;
+ } else if (!strcmp(cmds[cmd],"shutdown")) { /* exit application */
+ fprintf(stdout, "System shutting down at user request\n" );
+ exit(0);
+ }
+
+ /* exec cmd section */
+ /* TODO:
+ * To avoid user crash catch the signals.
+ * Open a new stdio files with posibility of redirection *
+ * Run in a new shell task background. (unix &)
+ * Resuming. A little bash.
+ */
+ memcpy (cmd_argv, cmds[cmd], RTEMS_SHELL_CMD_SIZE);
+ if (!rtems_shell_make_args(cmd_argv, &argc, argv,
+ RTEMS_SHELL_MAXIMUM_ARGUMENTS)) {
+ shell_cmd = rtems_shell_lookup_cmd(argv[0]);
+ if ( argv[0] == NULL ) {
+ shell_env->errorlevel = -1;
+ } else if ( shell_cmd == NULL ) {
+ shell_env->errorlevel = rtems_shell_script_file(argc, argv);
+ } else {
+ shell_env->errorlevel = shell_cmd->command(argc, argv);
+ }
+ }
+
+ /* end exec cmd section */
+ if (shell_env->exit_shell)
+ break;
+ }
+
+ fflush( stdout );
+ fflush( stderr );
+ }
+ } while (result && shell_env->forever);
+
+ }
+
+ if (cmds[0])
+ free (cmds[0]);
+ if (cmd_argv)
+ free (cmd_argv);
+ if (prompt)
+ free (prompt);
+
+ if (stdinToClose) {
+ fclose( stdinToClose );
+ } else {
+ if (tcsetattr(fileno(stdin), TCSADRAIN, &previous_term) < 0) {
+ fprintf(
+ stderr,
+ "shell: cannot reset terminal attributes (%s)\n",
+ shell_env->devname
+ );
+ }
+ }
+ if ( stdoutToClose )
+ fclose( stdoutToClose );
+ return result;
+}
+
+/* ----------------------------------------------- */
+static rtems_status_code rtems_shell_run (
+ const char *task_name,
+ size_t task_stacksize,
+ rtems_task_priority task_priority,
+ const char *devname,
+ bool forever,
+ bool wait,
+ const char *input,
+ const char *output,
+ bool output_append,
+ rtems_id wake_on_end,
+ bool echo,
+ rtems_shell_login_check_t login_check
+)
+{
+ rtems_id task_id;
+ rtems_status_code sc;
+ rtems_shell_env_t *shell_env;
+ rtems_name name;
+
+ if ( task_name && strlen(task_name) >= 4)
+ name = rtems_build_name(
+ task_name[0], task_name[1], task_name[2], task_name[3]);
+ else
+ name = rtems_build_name( 'S', 'E', 'N', 'V' );
+
+ sc = rtems_task_create(
+ name,
+ task_priority,
+ task_stacksize,
+ RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
+ RTEMS_LOCAL | RTEMS_FLOATING_POINT,
+ &task_id
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"creating task %s in shell_init()",task_name);
+ return sc;
+ }
+
+ shell_env = rtems_shell_init_env( NULL );
+ if ( !shell_env ) {
+ rtems_error(RTEMS_NO_MEMORY,
+ "allocating shell_env %s in shell_init()",task_name);
+ return RTEMS_NO_MEMORY;
+ }
+ shell_env->devname = devname;
+ shell_env->taskname = task_name;
+ shell_env->exit_shell = false;
+ shell_env->forever = forever;
+ shell_env->echo = echo;
+ shell_env->input = strdup (input);
+ shell_env->output = strdup (output);
+ shell_env->output_append = output_append;
+ shell_env->wake_on_end = wake_on_end;
+ shell_env->login_check = login_check;
+
+ getcwd(shell_env->cwd, sizeof(shell_env->cwd));
+
+ sc = rtems_task_start(task_id, rtems_shell_task,
+ (rtems_task_argument) shell_env);
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"starting task %s in shell_init()",task_name);
+ return sc;
+ }
+
+ if (wait) {
+ rtems_event_set out;
+ sc = rtems_event_receive (RTEMS_EVENT_1, RTEMS_WAIT, 0, &out);
+ }
+
+ return 0;
+}
+
+rtems_status_code rtems_shell_init(
+ const char *task_name,
+ size_t task_stacksize,
+ rtems_task_priority task_priority,
+ const char *devname,
+ bool forever,
+ bool wait,
+ rtems_shell_login_check_t login_check
+)
+{
+ rtems_id to_wake = RTEMS_ID_NONE;
+
+ if ( wait )
+ to_wake = rtems_task_self();
+
+ return rtems_shell_run(
+ task_name, /* task_name */
+ task_stacksize, /* task_stacksize */
+ task_priority, /* task_priority */
+ devname, /* devname */
+ forever, /* forever */
+ wait, /* wait */
+ "stdin", /* input */
+ "stdout", /* output */
+ false, /* output_append */
+ to_wake, /* wake_on_end */
+ false, /* echo */
+ login_check /* login check */
+ );
+}
+
+rtems_status_code rtems_shell_script (
+ const char *task_name,
+ size_t task_stacksize,
+ rtems_task_priority task_priority,
+ const char* input,
+ const char* output,
+ bool output_append,
+ bool wait,
+ bool echo
+)
+{
+ rtems_id current_task = RTEMS_INVALID_ID;
+ rtems_status_code sc;
+
+ if (wait) {
+ sc = rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &current_task);
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+ }
+
+ sc = rtems_shell_run(
+ task_name, /* task_name */
+ task_stacksize, /* task_stacksize */
+ task_priority, /* task_priority */
+ NULL, /* devname */
+ 0, /* forever */
+ wait, /* wait */
+ input, /* input */
+ output, /* output */
+ output_append, /* output_append */
+ current_task, /* wake_on_end */
+ echo, /* echo */
+ NULL /* login check */
+ );
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+
+ return sc;
+}
diff --git a/cpukit/libmisc/shell/shell.h b/cpukit/libmisc/shell/shell.h
new file mode 100644
index 0000000000..759bf71589
--- /dev/null
+++ b/cpukit/libmisc/shell/shell.h
@@ -0,0 +1,292 @@
+/**
+ * @file rtems/shell.h
+ *
+ * Instantatiate a new terminal shell.
+ */
+
+/*
+ * Author:
+ *
+ * WORK: fernando.ruiz@ctv.es
+ * HOME: correo@fernando-ruiz.com
+ *
+ * Thanks at:
+ * Chris Johns
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SHELL_H__
+#define __RTEMS_SHELL_H__
+
+#include <rtems.h>
+#include <stdio.h>
+#include <termios.h>
+#include <rtems/fs.h>
+#include <rtems/libio.h>
+#include <rtems/chain.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Some key labels to define special keys.
+ */
+
+#define RTEMS_SHELL_KEYS_EXTENDED (0x8000)
+#define RTEMS_SHELL_KEYS_NORMAL_MASK (0x00ff)
+#define RTEMS_SHELL_KEYS_INS (0)
+#define RTEMS_SHELL_KEYS_DEL (1)
+#define RTEMS_SHELL_KEYS_UARROW (2)
+#define RTEMS_SHELL_KEYS_DARROW (3)
+#define RTEMS_SHELL_KEYS_LARROW (4)
+#define RTEMS_SHELL_KEYS_RARROW (5)
+#define RTEMS_SHELL_KEYS_HOME (6)
+#define RTEMS_SHELL_KEYS_END (7)
+#define RTEMS_SHELL_KEYS_F1 (8)
+#define RTEMS_SHELL_KEYS_F2 (9)
+#define RTEMS_SHELL_KEYS_F3 (10)
+#define RTEMS_SHELL_KEYS_F4 (11)
+#define RTEMS_SHELL_KEYS_F5 (12)
+#define RTEMS_SHELL_KEYS_F6 (13)
+#define RTEMS_SHELL_KEYS_F7 (14)
+#define RTEMS_SHELL_KEYS_F8 (15)
+#define RTEMS_SHELL_KEYS_F9 (16)
+#define RTEMS_SHELL_KEYS_F10 (17)
+
+typedef bool (*rtems_shell_login_check_t)(
+ const char * /* user */,
+ const char * /* passphrase */
+);
+
+bool rtems_shell_login_prompt(
+ FILE *in,
+ FILE *out,
+ const char *device,
+ rtems_shell_login_check_t check
+);
+
+bool rtems_shell_login_check(
+ const char *user,
+ const char *passphrase
+);
+
+typedef int (*rtems_shell_command_t)(int argc, char **argv);
+
+struct rtems_shell_cmd_tt;
+typedef struct rtems_shell_cmd_tt rtems_shell_cmd_t;
+
+struct rtems_shell_cmd_tt {
+ const char *name;
+ const char *usage;
+ const char *topic;
+ rtems_shell_command_t command;
+ rtems_shell_cmd_t *alias;
+ rtems_shell_cmd_t *next;
+};
+
+typedef struct {
+ const char *name;
+ const char *alias;
+} rtems_shell_alias_t;
+
+/*
+ * The return value has RTEMS_SHELL_KEYS_EXTENDED set if the key
+ * is extended, ie a special key.
+ */
+unsigned int rtems_shell_getchar(FILE *in);
+
+rtems_shell_cmd_t * rtems_shell_lookup_cmd(const char *cmd);
+
+rtems_shell_cmd_t *rtems_shell_add_cmd_struct(
+ rtems_shell_cmd_t *shell_cmd
+);
+
+rtems_shell_cmd_t * rtems_shell_add_cmd(
+ const char *cmd,
+ const char *topic,
+ const char *usage,
+ rtems_shell_command_t command
+);
+
+rtems_shell_cmd_t * rtems_shell_alias_cmd(
+ const char *cmd,
+ const char *alias
+);
+
+int rtems_shell_make_args(
+ char *commandLine,
+ int *argc_p,
+ char **argv_p,
+ int max_args
+);
+
+int rtems_shell_cat_file(
+ FILE *out,
+ const char *name
+);
+
+void rtems_shell_write_file(
+ const char *name,
+ const char *content
+);
+
+int rtems_shell_script_file(
+ int argc,
+ char **argv
+);
+
+/**
+ * Initialise the shell creating tasks to login and run the shell
+ * sessions.
+ *
+ * @param task_name Name of the shell task.
+ * @param task_stacksize The size of the stack. If 0 the default size is used.
+ * @param task_priority The priority the shell runs at.
+ * @param forever Repeat logins.
+ * @param wait Caller should block until shell exits.
+ * @param login_check User login check function, NULL disables login checks.
+ *
+ */
+rtems_status_code rtems_shell_init(
+ const char *task_name,
+ size_t task_stacksize,
+ rtems_task_priority task_priority,
+ const char *devname,
+ bool forever,
+ bool wait,
+ rtems_shell_login_check_t login_check
+);
+
+/**
+ * Run a shell script creating a shell tasks to execute the command under.
+ *
+ * @param task_name Name of the shell task.
+ * @param task_stacksize The size of the stack. If 0 the default size is used.
+ * @param task_priority The priority the shell runs at.
+ * @param input The file of commands. Can be 'stdin' to use stdin.
+ * @param output The output file to write commands to. Can be 'stdout',
+ * 'stderr' or '/dev/null'.
+ * @param output_append Append the output to the file or truncate the file.
+ * Create if it does not exist.
+ * @param wait Wait for the script to finish.
+ */
+rtems_status_code rtems_shell_script(
+ const char *task_name,
+ size_t task_stacksize, /* 0 default*/
+ rtems_task_priority task_priority,
+ const char *input,
+ const char *output,
+ bool output_append,
+ bool wait,
+ bool echo
+);
+
+/**
+ * Private environment associated with each shell instance.
+ */
+typedef struct {
+ /** 'S','E','N','V': Shell Environment */
+ rtems_name magic;
+ const char *devname;
+ const char *taskname;
+ bool exit_shell; /* logout */
+ bool forever; /* repeat login */
+ int errorlevel;
+ bool echo;
+ char cwd[256];
+ const char *input;
+ const char *output;
+ bool output_append;
+ rtems_id wake_on_end;
+ rtems_shell_login_check_t login_check;
+} rtems_shell_env_t;
+
+bool rtems_shell_main_loop(
+ rtems_shell_env_t *rtems_shell_env
+);
+
+extern rtems_shell_env_t rtems_global_shell_env;
+extern rtems_shell_env_t *rtems_current_shell_env;
+
+/*
+ * The types of file systems we can mount. We have them broken out
+ * out like this so they can be configured by shellconfig.h. The
+ * mount command needs special treatment due to some file systems
+ * being dependent on the network stack and some not. If we had
+ * all possible file systems being included it would force the
+ * networking stack into the applcation and this may not be
+ * required.
+ */
+struct rtems_shell_filesystems_tt;
+typedef struct rtems_shell_filesystems_tt rtems_shell_filesystems_t;
+
+typedef int (*rtems_shell_filesystems_mounter_t)(
+ const char* driver,
+ const char* path,
+ rtems_shell_filesystems_t* fs,
+ rtems_filesystem_options_t options
+);
+
+struct rtems_shell_filesystems_tt {
+ rtems_chain_node link;
+ const char *name;
+ int driver_needed;
+ const rtems_filesystem_operations_table *fs_ops;
+ rtems_shell_filesystems_mounter_t mounter;
+};
+
+/**
+ * This method dynamically builds the command line prompt string
+ * and places it in @a prompt.
+ *
+ * @param[in] shell_env is the shell execution environment
+ * @param[in] prompt is a pointer to a string buffer area
+ * @param[in] size is length of the prompt buffer area
+ *
+ * @return This method fills in the memory pointed to by @a prompt.
+ *
+ * @note An application specific implementation can be provided
+ * by the user.
+ */
+void rtems_shell_get_prompt(
+ rtems_shell_env_t *shell_env,
+ char *prompt,
+ size_t size
+);
+
+/**
+ * Helper for the mount command.
+ *
+ * @param[in] driver The path to the driver.
+ * @param[in] path The path to mount on.
+ * @param[in] fs The file system definition.
+ * @param[in] options Special file system options.
+ */
+int rtems_shell_libc_mounter(
+ const char* driver,
+ const char* path,
+ rtems_shell_filesystems_t* fs,
+ rtems_filesystem_options_t options
+);
+
+/**
+ * Add a new file system mount configuration to the mount command.
+ *
+ * @param[in] fs The file system mount data.
+ */
+void rtems_shell_mount_add_fsys(rtems_shell_filesystems_t* fs);
+
+/**
+ * Delete file system mount configuration from the mount command.
+ *
+ * @param[in] fs The file system mount data to remove.
+ */
+void rtems_shell_mount_del_fsys(rtems_shell_filesystems_t* fs);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/shell/shell_cmdset.c b/cpukit/libmisc/shell/shell_cmdset.c
new file mode 100644
index 0000000000..2abaed9242
--- /dev/null
+++ b/cpukit/libmisc/shell/shell_cmdset.c
@@ -0,0 +1,234 @@
+/*
+ *
+ * Shell Command Set Management
+ *
+ * Author:
+ * WORK: fernando.ruiz@ctv.es
+ * HOME: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include <termios.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#include "internal.h"
+
+/*
+ * Common linked list of shell commands.
+ *
+ * Because the help report is very long, there is a topic for each command.
+ *
+ * Help list the topics
+ * help [topic] list the commands for the topic
+ * help [command] help for the command
+ *
+ */
+
+rtems_shell_cmd_t * rtems_shell_first_cmd;
+rtems_shell_topic_t * rtems_shell_first_topic;
+
+/*
+ * Find the topic from the set of topics registered.
+ */
+rtems_shell_topic_t * rtems_shell_lookup_topic(const char * topic) {
+ rtems_shell_topic_t * shell_topic;
+ shell_topic=rtems_shell_first_topic;
+
+ while (shell_topic) {
+ if (!strcmp(shell_topic->topic,topic))
+ return shell_topic;
+ shell_topic=shell_topic->next;
+ }
+ return (rtems_shell_topic_t *) NULL;
+}
+
+/*
+ * Add a new topic to the list of topics
+ */
+rtems_shell_topic_t * rtems_shell_add_topic(const char * topic) {
+ rtems_shell_topic_t * current,*aux;
+
+ if (!rtems_shell_first_topic) {
+ aux = malloc(sizeof(rtems_shell_topic_t));
+ aux->topic = topic;
+ aux->next = (rtems_shell_topic_t*)NULL;
+ return rtems_shell_first_topic = aux;
+ }
+ current=rtems_shell_first_topic;
+ if (!strcmp(topic,current->topic))
+ return current;
+
+ while (current->next) {
+ if (!strcmp(topic,current->next->topic))
+ return current->next;
+ current=current->next;
+ }
+ aux = malloc(sizeof(rtems_shell_topic_t));
+ aux->topic = topic;
+ aux->next = (rtems_shell_topic_t*)NULL;
+ current->next = aux;
+ return aux;
+}
+
+/*
+ * Find the command in the set
+ */
+rtems_shell_cmd_t * rtems_shell_lookup_cmd(const char * cmd) {
+ rtems_shell_cmd_t * shell_cmd;
+ shell_cmd=rtems_shell_first_cmd;
+ while (shell_cmd) {
+ if (!strcmp(shell_cmd->name,cmd)) return shell_cmd;
+ shell_cmd=shell_cmd->next;
+ };
+ return (rtems_shell_cmd_t *) NULL;
+}
+
+/*
+ * Add a command structure to the set of known commands
+ */
+rtems_shell_cmd_t *rtems_shell_add_cmd_struct(
+ rtems_shell_cmd_t *shell_cmd
+)
+{
+ rtems_shell_cmd_t *shell_pvt;
+
+ shell_pvt = rtems_shell_first_cmd;
+ while (shell_pvt) {
+ if (strcmp(shell_pvt->name, shell_cmd->name) == 0)
+ return NULL;
+ shell_pvt = shell_pvt->next;
+ }
+
+ if ( !rtems_shell_first_cmd ) {
+ rtems_shell_first_cmd = shell_cmd;
+ } else {
+ shell_pvt = rtems_shell_first_cmd;
+ while (shell_pvt->next)
+ shell_pvt = shell_pvt->next;
+ shell_pvt->next = shell_cmd;
+ }
+ rtems_shell_add_topic( shell_cmd->topic );
+ return shell_cmd;
+}
+
+/*
+ * Add a command as a set of arguments to the set and
+ * allocate the command structure on the fly.
+ */
+rtems_shell_cmd_t * rtems_shell_add_cmd(
+ const char *name,
+ const char *topic,
+ const char *usage,
+ rtems_shell_command_t command
+)
+{
+ rtems_shell_cmd_t *shell_cmd = NULL;
+ char *my_name = NULL;
+ char *my_topic = NULL;
+ char *my_usage = NULL;
+
+ /* Reject empty commands */
+ if (name == NULL || command == NULL) {
+ return NULL;
+ }
+
+ /* Allocate command stucture */
+ shell_cmd = (rtems_shell_cmd_t *) malloc(sizeof(rtems_shell_cmd_t));
+ if (shell_cmd == NULL) {
+ return NULL;
+ }
+
+ /* Allocate strings */
+ my_name = strdup(name);
+ my_topic = strdup(topic);
+ my_usage = strdup(usage);
+
+ /* Assign values */
+ shell_cmd->name = my_name;
+ shell_cmd->topic = my_topic;
+ shell_cmd->usage = my_usage;
+ shell_cmd->command = command;
+ shell_cmd->alias = NULL;
+ shell_cmd->next = NULL;
+
+ if (rtems_shell_add_cmd_struct(shell_cmd) == NULL) {
+ /* Something is wrong, free allocated resources */
+ free(my_usage);
+ free(my_topic);
+ free(my_name);
+ free(shell_cmd);
+
+ return NULL;
+ }
+
+ return shell_cmd;
+}
+
+
+void rtems_shell_initialize_command_set(void)
+{
+ rtems_shell_cmd_t **c;
+ rtems_shell_alias_t **a;
+
+ for ( c = rtems_shell_Initial_commands ; *c ; c++ ) {
+ rtems_shell_add_cmd_struct( *c );
+ }
+
+ for ( a = rtems_shell_Initial_aliases ; *a ; a++ ) {
+ rtems_shell_alias_cmd( (*a)->name, (*a)->alias );
+ }
+
+ rtems_shell_register_monitor_commands();
+}
+
+/* ----------------------------------------------- *
+ * you can make an alias for every command.
+ * ----------------------------------------------- */
+rtems_shell_cmd_t *rtems_shell_alias_cmd(
+ const char *cmd,
+ const char *alias
+)
+{
+ rtems_shell_cmd_t *shell_cmd, *shell_aux;
+
+ shell_aux = (rtems_shell_cmd_t *) NULL;
+
+ if (alias) {
+ shell_aux = rtems_shell_lookup_cmd(alias);
+ if (shell_aux != NULL) {
+ return NULL;
+ }
+ shell_cmd = rtems_shell_lookup_cmd(cmd);
+ if (shell_cmd != NULL) {
+ shell_aux = rtems_shell_add_cmd(
+ alias,
+ shell_cmd->topic,
+ shell_cmd->usage,
+ shell_cmd->command
+ );
+ if (shell_aux)
+ shell_aux->alias = shell_cmd;
+ }
+ }
+ return shell_aux;
+}
diff --git a/cpukit/libmisc/shell/shell_getchar.c b/cpukit/libmisc/shell/shell_getchar.c
new file mode 100644
index 0000000000..b214a9511f
--- /dev/null
+++ b/cpukit/libmisc/shell/shell_getchar.c
@@ -0,0 +1,176 @@
+/*
+ *
+ * Handle keys for the shell.
+ *
+ * Author:
+ *
+ * Chris Johns (chrisj@rtems.org)
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <time.h>
+
+#include <rtems.h>
+#include <rtems/error.h>
+#include <rtems/system.h>
+#include <rtems/shell.h>
+#include <rtems/shellconfig.h>
+#include "internal.h"
+
+/*
+ * Taken from the monitor code.
+ */
+
+/*
+ * Translation tables. Not sure if this is the best way to
+ * handle this, how-ever I wish to avoid the overhead of
+ * including a more complete and standard environment such
+ * as ncurses.
+ */
+
+struct translation_table
+{
+ char expecting;
+ const struct translation_table *branch;
+ unsigned int key;
+};
+
+static const struct translation_table trans_one[] =
+{
+ { '\x7e', 0, RTEMS_SHELL_KEYS_HOME },
+ { 0, 0, 0 }
+};
+
+static const struct translation_table trans_two[] =
+{
+ { '~', 0, RTEMS_SHELL_KEYS_INS },
+ { 0, 0, 0 }
+};
+
+static const struct translation_table trans_three[] =
+{
+ { '~', 0, RTEMS_SHELL_KEYS_DEL },
+ { 0, 0, 0 }
+};
+
+static const struct translation_table trans_tab_csi[] =
+{
+ { '1', trans_one, 0 },
+ { '2', trans_two, 0 },
+ { '3', trans_three, 0 },
+ { 'A', 0, RTEMS_SHELL_KEYS_UARROW },
+ { 'B', 0, RTEMS_SHELL_KEYS_DARROW },
+ { 'D', 0, RTEMS_SHELL_KEYS_LARROW },
+ { 'C', 0, RTEMS_SHELL_KEYS_RARROW },
+ { 'F', 0, RTEMS_SHELL_KEYS_END },
+ { 'H', 0, RTEMS_SHELL_KEYS_HOME },
+ { 0, 0, 0 }
+};
+
+static const struct translation_table trans_tab_O[] =
+{
+ { '1', 0, RTEMS_SHELL_KEYS_F1 },
+ { '2', 0, RTEMS_SHELL_KEYS_F2 },
+ { '3', 0, RTEMS_SHELL_KEYS_F3 },
+ { '4', 0, RTEMS_SHELL_KEYS_F4 },
+ { '5', 0, RTEMS_SHELL_KEYS_F5 },
+ { '6', 0, RTEMS_SHELL_KEYS_F6 },
+ { '7', 0, RTEMS_SHELL_KEYS_F7 },
+ { '8', 0, RTEMS_SHELL_KEYS_F8 },
+ { '9', 0, RTEMS_SHELL_KEYS_F9 },
+ { ':', 0, RTEMS_SHELL_KEYS_F10 },
+ { 'F', 0, RTEMS_SHELL_KEYS_END },
+ { 'P', 0, RTEMS_SHELL_KEYS_F1 },
+ { 'Q', 0, RTEMS_SHELL_KEYS_F2 },
+ { 'R', 0, RTEMS_SHELL_KEYS_F3 },
+ { 'S', 0, RTEMS_SHELL_KEYS_F4 },
+ { 'T', 0, RTEMS_SHELL_KEYS_F5 },
+ { 'U', 0, RTEMS_SHELL_KEYS_F6 },
+ { 'V', 0, RTEMS_SHELL_KEYS_F7 },
+ { 'W', 0, RTEMS_SHELL_KEYS_F8 },
+ { 'X', 0, RTEMS_SHELL_KEYS_F9 },
+ { 'Y', 0, RTEMS_SHELL_KEYS_F10 },
+ { 0, 0, 0 }
+};
+
+static const struct translation_table trans_tab[] =
+{
+ { '[', trans_tab_csi, 0 }, /* CSI command sequences */
+ { 'O', trans_tab_O, 0 }, /* O are the fuction keys */
+ { 0, 0, 0 }
+};
+
+/*
+ * Perform a basic tranlation for some ANSI/VT100 key codes.
+ * This code could do with a timeout on the ESC as it is
+ * now lost from the input stream. It is not* used by the
+ * line editor below so considiered not worth the effort.
+ */
+
+unsigned int
+rtems_shell_getchar (FILE *in)
+{
+ const struct translation_table *translation = 0;
+ for (;;)
+ {
+ int c = fgetc (in);
+ if (c == EOF)
+ return EOF;
+ if (c == 27)
+ translation = trans_tab;
+ else
+ {
+ /*
+ * If no translation happing just pass through
+ * and return the key.
+ */
+ if (translation)
+ {
+ /*
+ * Scan the current table for the key, and if found
+ * see if this key is a fork. If so follow it and
+ * wait else return the extended key.
+ */
+ int index = 0;
+ int branched = 0;
+ while ((translation[index].expecting != '\0') ||
+ (translation[index].key != '\0'))
+ {
+ if (translation[index].expecting == c)
+ {
+ /*
+ * A branch is take if more keys are to come.
+ */
+ if (translation[index].branch == 0)
+ return RTEMS_SHELL_KEYS_EXTENDED | translation[index].key;
+ else
+ {
+ translation = translation[index].branch;
+ branched = 1;
+ break;
+ }
+ }
+ index++;
+ }
+ /*
+ * Who knows what these keys are, just drop them.
+ */
+ if (!branched)
+ translation = 0;
+ }
+ else
+ return c;
+ }
+ }
+}
+
diff --git a/cpukit/libmisc/shell/shell_getprompt.c b/cpukit/libmisc/shell/shell_getprompt.c
new file mode 100644
index 0000000000..08c628b219
--- /dev/null
+++ b/cpukit/libmisc/shell/shell_getprompt.c
@@ -0,0 +1,49 @@
+/*
+ * Dynamically build the shell prompt
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <time.h>
+
+#include <rtems.h>
+#include <rtems/error.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/system.h>
+#include <rtems/shell.h>
+#include "internal.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pwd.h>
+
+void rtems_shell_get_prompt(
+ rtems_shell_env_t *shell_env,
+ char *prompt,
+ size_t size
+)
+{
+ char curdir[256];
+
+ /* XXX: show_prompt user adjustable */
+ getcwd(curdir,sizeof(curdir));
+ snprintf(prompt, size - 1, "%s%s[%s] %c ",
+ ((shell_env->taskname) ? shell_env->taskname : ""),
+ ((shell_env->taskname) ? " " : ""),
+ curdir,
+ geteuid()?'$':'#');
+}
diff --git a/cpukit/libmisc/shell/shell_makeargs.c b/cpukit/libmisc/shell/shell_makeargs.c
new file mode 100644
index 0000000000..727ea829c9
--- /dev/null
+++ b/cpukit/libmisc/shell/shell_makeargs.c
@@ -0,0 +1,68 @@
+/*
+ * Split string into argc/argv style argument list
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+int rtems_shell_make_args(
+ char *commandLine,
+ int *argc_p,
+ char **argv_p,
+ int max_args
+)
+{
+ int argc;
+ char *ch;
+ int status = 0;
+
+ argc = 0;
+ ch = commandLine;
+
+ while ( *ch ) {
+
+ while ( isspace((unsigned char)*ch) ) ch++;
+
+ if ( *ch == '\0' )
+ break;
+
+ if ( *ch == '"' ) {
+ argv_p[ argc ] = ++ch;
+ while ( ( *ch != '\0' ) && ( *ch != '"' ) ) ch++;
+ } else {
+ argv_p[ argc ] = ch;
+ while ( ( *ch != '\0' ) && ( !isspace((unsigned char)*ch) ) ) ch++;
+ }
+
+ argc++;
+
+ if ( *ch == '\0' )
+ break;
+
+ *ch++ = '\0';
+
+ if ( argc == (max_args-1) ) {
+ status = -1;
+ break;
+ }
+
+
+ }
+ argv_p[ argc ] = NULL;
+ *argc_p = argc;
+ return status;
+}
+
diff --git a/cpukit/libmisc/shell/shell_script.c b/cpukit/libmisc/shell/shell_script.c
new file mode 100644
index 0000000000..8854f4af35
--- /dev/null
+++ b/cpukit/libmisc/shell/shell_script.c
@@ -0,0 +1,351 @@
+/*
+ * Shell Script Invocation
+ *
+ * Pseudo-code from Chris Johns, implemented and debugged
+ * by Joel Sherrill.
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <unistd.h>
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <rtems.h>
+#include <rtems/shell.h>
+#include <rtems/stringto.h>
+#include "internal.h"
+
+static void rtems_shell_joel_usage(void)
+{
+ printf(
+ "joel [args] where args may be:\n"
+ " -o FILE output file (default=stdout)\n"
+ " -p PRIORITY task priority\n"
+ " -s SIZE task stack size\n"
+ " -t NAME task name\n"
+ );
+}
+
+static int findOnPATH(
+ const char *userScriptName,
+ char *scriptFile,
+ size_t scriptFileLength
+)
+{
+ int sc;
+
+ /*
+ * If the user script name starts with a / assume it is a fully
+ * qualified path name and just use it.
+ */
+ if ( userScriptName[0] == '/' ) {
+ strncpy( scriptFile, userScriptName, PATH_MAX );
+ } else {
+ /*
+ * For now, the provided name is just turned into a fully
+ * qualified path name and used. There is no attempt to
+ * search along a path for it.
+ */
+
+ /* XXX should use strncat but what is the limit? */
+ getcwd( scriptFile, PATH_MAX );
+ strncat( scriptFile, "/", PATH_MAX );
+ strncat(
+ scriptFile,
+ ( (userScriptName[0] == '.' && userScriptName[1] == '/') ?
+ &userScriptName[2] : userScriptName),
+ PATH_MAX
+ );
+ }
+
+ sc = access( scriptFile, R_OK );
+ if ( sc ) {
+ return -1;
+ }
+
+ return 0;
+
+#if 0
+ /*
+ * Does the command (argv[0]) contain a path ?, i.e. starts with
+ * '.' or contains a '/'?
+ */
+ /* TODO: Add concept of PATH */
+ if (!contains_path) {
+ /* check PATH environment variable */
+ for (path_part = PATH; path_part; skip to ':')
+ {
+ }
+ if (not found)
+ return -1;
+ }
+#endif
+}
+
+int rtems_shell_main_joel(
+ int argc,
+ char **argv
+);
+
+int rtems_shell_main_joel(
+ int argc,
+ char **argv
+)
+{
+ unsigned long tmp;
+ int option;
+ int sc;
+ int verbose = 0;
+ char *taskName = "JOEL";
+ uint32_t stackSize = RTEMS_MINIMUM_STACK_SIZE * 10;
+ rtems_task_priority taskPriority = 20;
+ char *outputFile = "stdout";
+ rtems_status_code result;
+ char scriptFile[PATH_MAX];
+ struct getopt_data getopt_reent;
+
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+ while ( (option = getopt_r( argc, argv, "o:p:s:t:v", &getopt_reent)) != -1 ) {
+ switch ((char)option) {
+ case 'o':
+ outputFile = getopt_reent.optarg;
+ break;
+ case 'p': {
+ const char *s = getopt_reent.optarg;
+
+ if ( rtems_string_to_unsigned_long( s, &tmp, NULL, 0) ) {
+ printf( "Task Priority argument (%s) is not a number\n", s );
+ return -1;
+ }
+ taskPriority = (rtems_task_priority) tmp;
+ break;
+ }
+ case 's': {
+ const char *s = getopt_reent.optarg;
+
+ if ( rtems_string_to_unsigned_long( s, &tmp, NULL, 0) ) {
+ printf( "Stack size argument (%s) is not a number\n", s );
+ return -1;
+ }
+ stackSize = (uint32_t) tmp;
+ break;
+ }
+ case 't':
+ taskName = getopt_reent.optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ default:
+ rtems_shell_joel_usage();
+ return -1;
+ }
+ }
+
+ if ( verbose ) {
+ fprintf( stderr,
+ "outputFile: %s\n"
+ "taskPriority: %" PRId32 "\n"
+ "stackSize: %" PRId32 "\n"
+ "taskName: %s\n",
+ outputFile,
+ taskPriority,
+ stackSize,
+ taskName
+ );
+ }
+
+ /*
+ * Verify there is a script name past the end of the arguments.
+ * Preincrement to skip program name.
+ */
+ if ( getopt_reent.optind >= argc ) {
+ fprintf( stderr, "Shell: No script to execute\n" );
+ return -1;
+ }
+
+ /*
+ * Find script on the path.
+ *
+ * NOTE: It is terrible that this is done twice but it
+ * seems to be the most expedient thing.
+ */
+ sc = findOnPATH( argv[getopt_reent.optind], scriptFile, PATH_MAX );
+ if ( sc ) {
+ fprintf( stderr, "%s: command not found\n", argv[0] );
+ return -1;
+ }
+
+ /* fprintf( stderr, "SCRIPT: -%s-\n", scriptFile ); */
+
+ /*
+ * I assume that argv[optind...] will have the arguments to
+ * the shell script. But that remains to be implemented.
+ */
+
+ /*
+ * Run the script
+ */
+ result = rtems_shell_script(
+ taskName, /* the name of the task */
+ stackSize, /* stack size */
+ taskPriority, /* task priority */
+ scriptFile, /* the script file */
+ outputFile, /* where to redirect the script */
+ 0, /* run once and exit */
+ 1, /* we will wait */
+ verbose /* do we echo */
+ );
+ if (result)
+ return -1;
+ return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_JOEL_Command = {
+ "joel", /* name */
+ "joel [args] SCRIPT", /* usage */
+ "misc", /* topic */
+ rtems_shell_main_joel, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
+
+/*
+ * This is a helper function which takes a command as arguments
+ * which has not been located as a built-in command and attempts
+ * to find something in the filesystem with the same name that
+ * appears to be a shell script.
+ */
+int rtems_shell_script_file(
+ int argc __attribute__((unused)),
+ char *argv[]
+)
+{
+ #define FIRST_LINE_LENGTH 128
+ #define SCRIPT_ARGV_LIMIT 32
+ char scriptFile[PATH_MAX];
+ char *scriptHead;
+ char scriptHeadBuffer[FIRST_LINE_LENGTH];
+ int sc;
+ FILE *script;
+ size_t length;
+ int scriptArgc;
+ char *scriptArgv[SCRIPT_ARGV_LIMIT];
+
+ /*
+ * Clear argv pointer array
+ */
+ for ( scriptArgc=0 ; scriptArgc<SCRIPT_ARGV_LIMIT ; scriptArgc++ )
+ scriptArgv[scriptArgc] = NULL;
+
+ /*
+ * Find argv[0] on the path
+ */
+ sc = findOnPATH( argv[0], scriptFile, PATH_MAX );
+ if ( sc ) {
+ fprintf( stderr, "%s: command not found\n", argv[0] );
+ return -1;
+ }
+
+ /*
+ * Open the file so we can see if it looks like a script.
+ */
+ script = fopen( scriptFile, "r" );
+ if ( !script ) {
+ fprintf( stderr, "%s: Unable to open %s\n", argv[0], scriptFile );
+ return -1;
+ }
+
+ /*
+ * Is the script OK to run?
+ * Verify the current user has permission to execute it.
+ *
+ * NOTE: May not work on all file systems
+ */
+ sc = access( scriptFile, X_OK );
+ if ( sc ) {
+ fprintf( stderr, "Unable to execute %s\n", scriptFile );
+ fclose( script );
+ return -1;
+ }
+
+ /*
+ * Try to read the first line from the potential script file
+ */
+ scriptHead = fgets(scriptHeadBuffer, FIRST_LINE_LENGTH, script);
+ if ( !scriptHead ) {
+ fprintf(
+ stderr, "%s: Unable to read first line of %s\n", argv[0], scriptFile );
+ fclose( script );
+ return -1;
+ }
+
+ fclose(script);
+
+ length = strnlen(scriptHead, FIRST_LINE_LENGTH);
+ scriptHead[length - 1] = '\0';
+
+ /* fprintf( stderr, "FIRST LINE: -%s-\n", scriptHead ); */
+
+ /*
+ * Verify the name of the "shell" is joel. This means
+ * the line starts with "#! joel".
+ */
+ if (strncmp("#! joel", scriptHead, 7) != 0) {
+ fprintf( stderr, "%s: Not a joel script %s\n", argv[0], scriptFile );
+ return -1;
+ }
+
+ /*
+ * Do not worry about search path further. We have found the
+ * script, it is executable, and we have successfully read the
+ * first line and found out it is a script.
+ */
+
+ /*
+ * Check for arguments in the first line of the script. This changes
+ * how the shell task is run.
+ */
+
+ sc = rtems_shell_make_args(
+ &scriptHead[3],
+ &scriptArgc,
+ scriptArgv,
+ SCRIPT_ARGV_LIMIT - 1
+ );
+ if ( sc ) {
+ fprintf(
+ stderr, "%s: Error parsing joel arguments %s\n", argv[0], scriptFile );
+ return -1;
+ }
+
+ scriptArgv[ scriptArgc++ ] = scriptFile;
+
+ /*
+ * TODO: How do we pass arguments from here to the script?
+ * At this point, it doesn't matter because we don't
+ * have any way for a shell script to access them.
+ */
+ return rtems_shell_main_joel( scriptArgc, scriptArgv );
+
+ return 0;
+}
diff --git a/cpukit/libmisc/shell/shellconfig.c b/cpukit/libmisc/shell/shellconfig.c
new file mode 100644
index 0000000000..0cb0de0b30
--- /dev/null
+++ b/cpukit/libmisc/shell/shellconfig.c
@@ -0,0 +1,21 @@
+/*
+ * RTEMS Shell Command Set -- DEFAULT Configuration
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define CONFIGURE_SHELL_COMMANDS_INIT
+#define CONFIGURE_SHELL_COMMANDS_ALL
+
+#include <rtems/shellconfig.h>
diff --git a/cpukit/libmisc/shell/shellconfig.h b/cpukit/libmisc/shell/shellconfig.h
new file mode 100644
index 0000000000..cfc475095e
--- /dev/null
+++ b/cpukit/libmisc/shell/shellconfig.h
@@ -0,0 +1,438 @@
+/*
+ * RTEMS Shell Command Set Configuration
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_SHELL_CONFIG_h
+#define _RTEMS_SHELL_CONFIG_h
+
+#include <rtems/shell.h>
+
+/*
+ * Externs for all command definition structures
+ */
+extern rtems_shell_cmd_t rtems_shell_HELP_Command;
+extern rtems_shell_cmd_t rtems_shell_ALIAS_Command;
+extern rtems_shell_cmd_t rtems_shell_TIME_Command;
+extern rtems_shell_cmd_t rtems_shell_LOGOFF_Command;
+extern rtems_shell_cmd_t rtems_shell_SETENV_Command;
+extern rtems_shell_cmd_t rtems_shell_GETENV_Command;
+extern rtems_shell_cmd_t rtems_shell_UNSETENV_Command;
+
+extern rtems_shell_cmd_t rtems_shell_MDUMP_Command;
+extern rtems_shell_cmd_t rtems_shell_WDUMP_Command;
+extern rtems_shell_cmd_t rtems_shell_MEDIT_Command;
+extern rtems_shell_cmd_t rtems_shell_MFILL_Command;
+extern rtems_shell_cmd_t rtems_shell_MMOVE_Command;
+
+extern rtems_shell_cmd_t rtems_shell_JOEL_Command;
+extern rtems_shell_cmd_t rtems_shell_DATE_Command;
+extern rtems_shell_cmd_t rtems_shell_ECHO_Command;
+extern rtems_shell_cmd_t rtems_shell_SLEEP_Command;
+extern rtems_shell_cmd_t rtems_shell_ID_Command;
+extern rtems_shell_cmd_t rtems_shell_TTY_Command;
+extern rtems_shell_cmd_t rtems_shell_WHOAMI_Command;
+
+extern rtems_shell_cmd_t rtems_shell_CP_Command;
+extern rtems_shell_cmd_t rtems_shell_PWD_Command;
+extern rtems_shell_cmd_t rtems_shell_LS_Command;
+extern rtems_shell_cmd_t rtems_shell_CHDIR_Command;
+extern rtems_shell_cmd_t rtems_shell_MKDIR_Command;
+extern rtems_shell_cmd_t rtems_shell_RMDIR_Command;
+extern rtems_shell_cmd_t rtems_shell_CHROOT_Command;
+extern rtems_shell_cmd_t rtems_shell_CHMOD_Command;
+extern rtems_shell_cmd_t rtems_shell_CAT_Command;
+extern rtems_shell_cmd_t rtems_shell_MKRFS_Command;
+extern rtems_shell_cmd_t rtems_shell_MSDOSFMT_Command;
+extern rtems_shell_cmd_t rtems_shell_MSDOSFMT_Alias;
+extern rtems_shell_cmd_t rtems_shell_MV_Command;
+extern rtems_shell_cmd_t rtems_shell_RM_Command;
+extern rtems_shell_cmd_t rtems_shell_LN_Command;
+extern rtems_shell_cmd_t rtems_shell_MKNOD_Command;
+extern rtems_shell_cmd_t rtems_shell_UMASK_Command;
+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_DEBUGRFS_Command;
+
+extern rtems_shell_cmd_t rtems_shell_RTC_Command;
+
+extern rtems_shell_cmd_t rtems_shell_HALT_Command;
+extern rtems_shell_cmd_t rtems_shell_CPUUSE_Command;
+extern rtems_shell_cmd_t rtems_shell_STACKUSE_Command;
+extern rtems_shell_cmd_t rtems_shell_PERIODUSE_Command;
+extern rtems_shell_cmd_t rtems_shell_WKSPACE_INFO_Command;
+extern rtems_shell_cmd_t rtems_shell_MALLOC_INFO_Command;
+#if RTEMS_NETWORKING
+ extern rtems_shell_cmd_t rtems_shell_IFCONFIG_Command;
+ extern rtems_shell_cmd_t rtems_shell_ROUTE_Command;
+ extern rtems_shell_cmd_t rtems_shell_NETSTATS_Command;
+#endif
+
+extern rtems_shell_cmd_t *rtems_shell_Initial_commands[];
+
+/*
+ * Extern for alias commands
+ */
+extern rtems_shell_alias_t rtems_shell_DIR_Alias;
+extern rtems_shell_alias_t rtems_shell_CD_Alias;
+extern rtems_shell_alias_t rtems_shell_EXIT_Alias;
+
+extern rtems_shell_alias_t *rtems_shell_Initial_aliases[];
+
+/*
+ * If we are configured to alias a command, then make sure the underlying
+ * command is configured.
+ */
+
+#if !defined(CONFIGURE_SHELL_COMMANDS_ALL)
+ #if defined(CONFIGURE_SHELL_COMMANDS_DIR) && \
+ !defined(CONFIGURE_SHELL_COMMANDS_LS)
+ #define CONFIGURE_SHELL_COMMAND_LS
+ #endif
+
+ #if defined(CONFIGURE_SHELL_COMMANDS_CD) && \
+ !defined(CONFIGURE_SHELL_COMMANDS_CHDIR)
+ #define CONFIGURE_SHELL_COMMAND_CHDIR
+ #endif
+
+ #if defined(CONFIGURE_SHELL_COMMANDS_EXIT) && \
+ !defined(CONFIGURE_SHELL_COMMANDS_LOGOFF)
+ #define CONFIGURE_SHELL_COMMAND_LOGOFF
+ #endif
+#endif
+
+#if defined(CONFIGURE_SHELL_COMMANDS_INIT)
+ rtems_shell_alias_t *rtems_shell_Initial_aliases[] = {
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_DIR)) || \
+ defined(CONFIGURE_SHELL_COMMAND_DIR)
+ &rtems_shell_DIR_Alias,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_CD)) || \
+ defined(CONFIGURE_SHELL_COMMAND_CD)
+ &rtems_shell_CD_Alias,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_EXIT)) || \
+ defined(CONFIGURE_SHELL_COMMAND_EXIT)
+ &rtems_shell_EXIT_Alias,
+ #endif
+
+ /*
+ * User defined shell aliases
+ */
+ #if defined(CONFIGURE_SHELL_USER_ALIASES)
+ CONFIGURE_SHELL_USER_ALIASES,
+ #endif
+ NULL
+ };
+
+ rtems_shell_cmd_t *rtems_shell_Initial_commands[] = {
+ /*
+ * General comamnds that should be present
+ */
+ &rtems_shell_HELP_Command,
+ &rtems_shell_ALIAS_Command,
+ &rtems_shell_TIME_Command,
+
+ /*
+ * Common commands that can be optional
+ */
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_JOEL)) || \
+ defined(CONFIGURE_SHELL_COMMAND_JOEL)
+ &rtems_shell_JOEL_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_DATE)) || \
+ defined(CONFIGURE_SHELL_COMMAND_DATE)
+ &rtems_shell_DATE_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_ECHO)) || \
+ defined(CONFIGURE_SHELL_COMMAND_ECHO)
+ &rtems_shell_ECHO_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_SLEEP)) || \
+ defined(CONFIGURE_SHELL_COMMAND_SLEEP)
+ &rtems_shell_SLEEP_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_ID)) || \
+ defined(CONFIGURE_SHELL_COMMAND_ID)
+ &rtems_shell_ID_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_TTY)) || \
+ defined(CONFIGURE_SHELL_COMMAND_TTY)
+ &rtems_shell_TTY_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_WHOAMI)) || \
+ defined(CONFIGURE_SHELL_COMMAND_WHOAMI)
+ &rtems_shell_WHOAMI_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_LOGOFF)) || \
+ defined(CONFIGURE_SHELL_COMMAND_LOGOFF)
+ &rtems_shell_LOGOFF_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_SETENV)) || \
+ defined(CONFIGURE_SHELL_COMMAND_SETENV)
+ &rtems_shell_SETENV_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_GETENV)) || \
+ defined(CONFIGURE_SHELL_COMMAND_GETENV)
+ &rtems_shell_GETENV_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_CRLENV)) || \
+ defined(CONFIGURE_SHELL_COMMAND_UNSETENV)
+ &rtems_shell_UNSETENV_Command,
+ #endif
+
+ /*
+ * Memory printing/modification family commands
+ */
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MDUMP)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MDUMP)
+ &rtems_shell_MDUMP_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_WDUMP)) || \
+ defined(CONFIGURE_SHELL_COMMAND_WDUMP)
+ &rtems_shell_WDUMP_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MEDIT)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MEDIT)
+ &rtems_shell_MEDIT_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MFILL)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MFILL)
+ &rtems_shell_MFILL_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MMOVE)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MMOVE)
+ &rtems_shell_MMOVE_Command,
+ #endif
+
+ /*
+ * File and directory commands
+ */
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_CP)) || \
+ defined(CONFIGURE_SHELL_COMMAND_CP)
+ &rtems_shell_CP_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_PWD)) || \
+ defined(CONFIGURE_SHELL_COMMAND_PWD)
+ &rtems_shell_PWD_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_LS)) || \
+ defined(CONFIGURE_SHELL_COMMAND_LS)
+ &rtems_shell_LS_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_CHDIR)) || \
+ defined(CONFIGURE_SHELL_COMMAND_CHDIR)
+ &rtems_shell_CHDIR_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MKDIR)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MKDIR)
+ &rtems_shell_MKDIR_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_RMDIR)) || \
+ defined(CONFIGURE_SHELL_COMMAND_RMDIR)
+ &rtems_shell_RMDIR_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_CHROOT)) || \
+ defined(CONFIGURE_SHELL_COMMAND_CHROOT)
+ &rtems_shell_CHROOT_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_CHMOD)) || \
+ defined(CONFIGURE_SHELL_COMMAND_CHMOD)
+ &rtems_shell_CHMOD_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_CAT)) || \
+ defined(CONFIGURE_SHELL_COMMAND_CAT)
+ &rtems_shell_CAT_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MKRFS)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MKRFS)
+ &rtems_shell_MKRFS_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MSDOSFMT)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MSDOSFMT)
+ &rtems_shell_MSDOSFMT_Command,
+ &rtems_shell_MSDOSFMT_Alias,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MV)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MV)
+ &rtems_shell_MV_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_RM)) || \
+ defined(CONFIGURE_SHELL_COMMAND_RM)
+ &rtems_shell_RM_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_LN)) || \
+ defined(CONFIGURE_SHELL_COMMAND_LN)
+ &rtems_shell_LN_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MKNOD)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MKNOD)
+ &rtems_shell_MKNOD_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_UMASK)) || \
+ defined(CONFIGURE_SHELL_COMMAND_UMASK)
+ &rtems_shell_UMASK_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MOUNT)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MOUNT)
+ &rtems_shell_MOUNT_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_UNMOUNT)) || \
+ defined(CONFIGURE_SHELL_COMMAND_UNMOUNT)
+ &rtems_shell_UNMOUNT_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_BLKSYNC)) || \
+ defined(CONFIGURE_SHELL_COMMAND_BLKSYNC)
+ &rtems_shell_BLKSYNC_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_FDISK)) || \
+ 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
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_DEBUGRFS)) || \
+ defined(CONFIGURE_SHELL_COMMAND_DEBUGRFS)
+ &rtems_shell_DEBUGRFS_Command,
+ #endif
+
+ /*
+ * RTEMS Related commands
+ */
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_HALT)) || \
+ defined(CONFIGURE_SHELL_COMMAND_HALT)
+ &rtems_shell_HALT_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_CPUUSE)) || \
+ defined(CONFIGURE_SHELL_COMMAND_CPUUSE)
+ &rtems_shell_CPUUSE_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_STACKUSE)) || \
+ defined(CONFIGURE_SHELL_COMMAND_STACKUSE)
+ &rtems_shell_STACKUSE_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_PERIODUSE)) || \
+ defined(CONFIGURE_SHELL_COMMAND_PERIODUSE)
+ &rtems_shell_PERIODUSE_Command,
+ #endif
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_WKSPACE_INFO)) || \
+ defined(CONFIGURE_SHELL_COMMAND_WKSPACE_INFO)
+ &rtems_shell_WKSPACE_INFO_Command,
+ #endif
+
+ /*
+ * Malloc family commands
+ */
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_MALLOC_INFO)) || \
+ defined(CONFIGURE_SHELL_COMMAND_MALLOC_INFO)
+ &rtems_shell_MALLOC_INFO_Command,
+ #endif
+
+ /*
+ * Network related commands
+ */
+ #if RTEMS_NETWORKING
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL_NETWORKING) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_IFCONFIG)) || \
+ defined(CONFIGURE_SHELL_COMMAND_IFCONFIG)
+ &rtems_shell_IFCONFIG_Command,
+ #endif
+
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL_NETWORKING) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_ROUTE)) || \
+ defined(CONFIGURE_SHELL_COMMAND_ROUTE)
+ &rtems_shell_ROUTE_Command,
+ #endif
+
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL_NETWORKING) && \
+ !defined(CONFIGURE_SHELL_NO_COMMAND_NETSTATS)) || \
+ defined(CONFIGURE_SHELL_COMMAND_NETSTATS)
+ &rtems_shell_NETSTATS_Command,
+ #endif
+ #endif
+
+ /* Miscanellous shell commands */
+ #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) \
+ && !defined(CONFIGURE_SHELL_NO_COMMAND_RTC)) \
+ || defined(CONFIGURE_SHELL_COMMAND_RTC)
+ &rtems_shell_RTC_Command,
+ #endif
+
+ /*
+ * User defined shell commands
+ */
+ #if defined(CONFIGURE_SHELL_USER_COMMANDS)
+ CONFIGURE_SHELL_USER_COMMANDS,
+ #endif
+ NULL
+ };
+
+#endif
+
+#endif
diff --git a/cpukit/libmisc/shell/utils-cp.c b/cpukit/libmisc/shell/utils-cp.c
new file mode 100644
index 0000000000..7b7c7fc771
--- /dev/null
+++ b/cpukit/libmisc/shell/utils-cp.c
@@ -0,0 +1,496 @@
+/* $NetBSD: utils.c,v 1.29 2005/10/15 18:22:18 christos Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if 0
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94";
+#else
+__RCSID("$NetBSD: utils.c,v 1.29 2005/10/15 18:22:18 christos Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#if 0
+#include <sys/mman.h>
+#endif
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <utime.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern-cp.h"
+
+#define lchmod chmod
+#define lchown chown
+
+#define cp_pct(x, y) ((y == 0) ? 0 : (int)(100.0 * (x) / (y)))
+
+int
+set_utimes(const char *file, struct stat *fs)
+{
+ struct utimbuf tv;
+
+ tv.actime = fs->st_atime;
+ tv.modtime = fs->st_mtime;
+
+ if (utime(file, &tv)) {
+ warn("lutimes: %s", file);
+ return (1);
+ }
+ return (0);
+}
+
+int
+copy_file(rtems_shell_cp_globals* cp_globals __attribute__((unused)), FTSENT *entp, int dne)
+{
+#define MAX_READ max_read
+ int max_read;
+ char* buf;
+ struct stat *fs;
+ ssize_t wcount;
+ size_t wresid;
+ off_t wtotal;
+ int ch, checkch, from_fd = 0, rcount, rval, to_fd = 0;
+ char *bufp;
+#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
+ char *p;
+#endif
+
+ fs = entp->fts_statp;
+
+ max_read = fs->st_blksize;
+ if (max_read < (8 * 1024))
+ max_read = 8 * 1024;
+ buf = malloc (max_read);
+ if (!buf)
+ {
+ warn("no memory");
+ return (1);
+ }
+
+ if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
+ warn("%s", entp->fts_path);
+ (void)free(buf);
+ return (1);
+ }
+
+ /*
+ * If the file exists and we're interactive, verify with the user.
+ * If the file DNE, set the mode to be the from file, minus setuid
+ * bits, modified by the umask; arguably wrong, but it makes copying
+ * executables work right and it's been that way forever. (The
+ * other choice is 666 or'ed with the execute bits on the from file
+ * modified by the umask.)
+ */
+ if (!dne) {
+#define YESNO "(y/n [n]) "
+ if (nflag) {
+ if (vflag)
+ printf("%s not overwritten\n", to.p_path);
+ (void)close(from_fd);
+ (void)free(buf);
+ return (0);
+ } else if (iflag) {
+ (void)fprintf(stderr, "overwrite %s? %s",
+ to.p_path, YESNO);
+ checkch = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (checkch != 'y' && checkch != 'Y') {
+ (void)close(from_fd);
+ (void)free(buf);
+ (void)fprintf(stderr, "not overwritten\n");
+ return (1);
+ }
+ }
+
+ if (fflag) {
+ /* remove existing destination file name,
+ * create a new file */
+ (void)unlink(to.p_path);
+ if (!lflag)
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+ fs->st_mode & ~(S_ISUID | S_ISGID));
+ } else {
+ if (!lflag)
+ /* overwrite existing destination file name */
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
+ }
+ } else {
+ if (!lflag)
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+ fs->st_mode & ~(S_ISUID | S_ISGID));
+ }
+
+ if (to_fd == -1) {
+ warn("%s", to.p_path);
+ (void)close(from_fd);
+ (void)free(buf);
+ return (1);
+ }
+
+ rval = 0;
+
+ if (!lflag) {
+ /*
+ * Mmap and write if less than 8M (the limit is so we don't totally
+ * trash memory on big files. This is really a minor hack, but it
+ * wins some CPU back.
+ */
+#ifdef CCJ_REMOVED_VM_AND_BUFFER_CACHE_SYNCHRONIZED
+ if (S_ISREG(fs->st_mode) && fs->st_size > 0 &&
+ fs->st_size <= 8 * 1048576) {
+ if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
+ MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
+ warn("%s", entp->fts_path);
+ rval = 1;
+ } else {
+ wtotal = 0;
+ for (bufp = p, wresid = fs->st_size; ;
+ bufp += wcount, wresid -= (size_t)wcount) {
+ wcount = write(to_fd, bufp, wresid);
+ if (wcount <= 0)
+ break;
+ wtotal += wcount;
+ if (info) {
+ info = 0;
+ (void)fprintf(stderr,
+ "%s -> %s %3d%%\n",
+ entp->fts_path, to.p_path,
+ cp_pct(wtotal, fs->st_size));
+ }
+ if (wcount >= (ssize_t)wresid)
+ break;
+ }
+ if (wcount != (ssize_t)wresid) {
+ warn("%s", to.p_path);
+ rval = 1;
+ }
+ /* Some systems don't unmap on close(2). */
+ if (munmap(p, fs->st_size) < 0) {
+ warn("%s", entp->fts_path);
+ rval = 1;
+ }
+ }
+ } else
+#endif
+ {
+ wtotal = 0;
+ while ((rcount = read(from_fd, buf, MAX_READ)) > 0) {
+ for (bufp = buf, wresid = rcount; ;
+ bufp += wcount, wresid -= wcount) {
+ wcount = write(to_fd, bufp, wresid);
+ if (wcount <= 0)
+ break;
+ wtotal += wcount;
+ if (info) {
+ info = 0;
+ (void)fprintf(stderr,
+ "%s -> %s %3d%%\n",
+ entp->fts_path, to.p_path,
+ cp_pct(wtotal, fs->st_size));
+ }
+ if (wcount >= (ssize_t)wresid)
+ break;
+ }
+ if (wcount != (ssize_t)wresid) {
+ warn("%s", to.p_path);
+ rval = 1;
+ break;
+ }
+ }
+ if (rcount < 0) {
+ warn("%s", entp->fts_path);
+ rval = 1;
+ }
+ }
+ } else {
+ if (link(entp->fts_path, to.p_path)) {
+ warn("%s", to.p_path);
+ rval = 1;
+ }
+ }
+ (void)close(from_fd);
+
+ /*
+ * Don't remove the target even after an error. The target might
+ * not be a regular file, or its attributes might be important,
+ * or its contents might be irreplaceable. It would only be safe
+ * to remove it if we created it and its length is 0.
+ */
+
+ if (!lflag) {
+ if (pflag && setfile(cp_globals, fs, to_fd))
+ rval = 1;
+ if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
+ rval = 1;
+ (void)close(from_fd);
+ if (close(to_fd)) {
+ warn("%s", to.p_path);
+ rval = 1;
+ }
+ }
+ (void)free(buf);
+ return (rval);
+}
+
+int
+copy_link(rtems_shell_cp_globals* cp_globals, FTSENT *p, int exists)
+{
+ ssize_t len;
+ char llink[PATH_MAX];
+
+ if ((len = readlink(p->fts_path, llink, sizeof(llink) - 1)) == -1) {
+ warn("readlink: %s", p->fts_path);
+ return (1);
+ }
+ llink[len] = '\0';
+ if (exists && unlink(to.p_path)) {
+ warn("unlink: %s", to.p_path);
+ return (1);
+ }
+ if (symlink(llink, to.p_path)) {
+ warn("symlink: %s", llink);
+ return (1);
+ }
+ return (pflag ? setfile(cp_globals, p->fts_statp, -1) : 0);
+}
+
+int
+copy_fifo(rtems_shell_cp_globals* cp_globals, struct stat *from_stat, int exists)
+{
+ if (exists && unlink(to.p_path)) {
+ warn("unlink: %s", to.p_path);
+ return (1);
+ }
+ if (mkfifo(to.p_path, from_stat->st_mode)) {
+ warn("mkfifo: %s", to.p_path);
+ return (1);
+ }
+ return (pflag ? setfile(cp_globals, from_stat, -1) : 0);
+}
+
+int
+copy_special(rtems_shell_cp_globals* cp_globals, struct stat *from_stat, int exists)
+{
+ if (exists && unlink(to.p_path)) {
+ warn("unlink: %s", to.p_path);
+ return (1);
+ }
+ if (mknod(to.p_path, from_stat->st_mode, from_stat->st_rdev)) {
+ warn("mknod: %s", to.p_path);
+ return (1);
+ }
+ return (pflag ? setfile(cp_globals, from_stat, -1) : 0);
+}
+
+#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
+ (tv)->tv_sec = *(ts); \
+ (tv)->tv_usec = 0; \
+}
+
+#define st_atimespec st_atime
+#define st_mtimespec st_mtime
+#define lutimes utimes
+
+int
+setfile(rtems_shell_cp_globals* cp_globals, struct stat *fs, int fd)
+{
+ static struct timeval tv[2];
+ struct stat ts;
+ int rval, gotstat, islink, fdval;
+
+ rval = 0;
+ fdval = fd != -1;
+ islink = !fdval && S_ISLNK(fs->st_mode);
+ fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
+ S_IRWXU | S_IRWXG | S_IRWXO;
+
+ TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
+ TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
+#if 0
+ if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
+ warn("%sutimes: %s", islink ? "l" : "", to.p_path);
+ rval = 1;
+ }
+#endif
+ if (fdval ? fstat(fd, &ts) :
+ (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
+ gotstat = 0;
+ else {
+ gotstat = 1;
+ ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX |
+ S_IRWXU | S_IRWXG | S_IRWXO;
+ }
+ /*
+ * Changing the ownership probably won't succeed, unless we're root
+ * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting
+ * the mode; current BSD behavior is to remove all setuid bits on
+ * chown. If chown fails, lose setuid/setgid bits.
+ */
+ if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
+ if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
+ (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
+ chown(to.p_path, fs->st_uid, fs->st_gid))) {
+ if (errno != EPERM) {
+ warn("chown: %s", to.p_path);
+ rval = 1;
+ }
+ fs->st_mode &= ~(S_ISUID | S_ISGID);
+ }
+
+ if (!gotstat || fs->st_mode != ts.st_mode)
+ if (fdval ? fchmod(fd, fs->st_mode) :
+ (islink ? lchmod(to.p_path, fs->st_mode) :
+ chmod(to.p_path, fs->st_mode))) {
+ warn("chmod: %s", to.p_path);
+ rval = 1;
+ }
+
+#if 0
+ if (!gotstat || fs->st_flags != ts.st_flags)
+ if (fdval ?
+ fchflags(fd, fs->st_flags) :
+ (islink ? (errno = ENOSYS) :
+ chflags(to.p_path, fs->st_flags))) {
+ warn("chflags: %s", to.p_path);
+ rval = 1;
+ }
+#endif
+
+ return (rval);
+}
+
+int
+preserve_fd_acls(int source_fd __attribute__((unused)), int dest_fd __attribute__((unused)))
+{
+#if 0
+ struct acl *aclp;
+ acl_t acl;
+
+ if (fpathconf(source_fd, _PC_ACL_EXTENDED) != 1 ||
+ fpathconf(dest_fd, _PC_ACL_EXTENDED) != 1)
+ return (0);
+ acl = acl_get_fd(source_fd);
+ if (acl == NULL) {
+ warn("failed to get acl entries while setting %s", to.p_path);
+ return (1);
+ }
+ aclp = &acl->ats_acl;
+ if (aclp->acl_cnt == 3)
+ return (0);
+ if (acl_set_fd(dest_fd, acl) < 0) {
+ warn("failed to set acl entries for %s", to.p_path);
+ return (1);
+ }
+#endif
+ return (0);
+}
+
+int
+preserve_dir_acls(struct stat *fs __attribute__((unused)), char *source_dir __attribute__((unused)), char *dest_dir __attribute__((unused)))
+{
+#if 0
+ acl_t (*aclgetf)(const char *, acl_type_t);
+ int (*aclsetf)(const char *, acl_type_t, acl_t);
+ struct acl *aclp;
+ acl_t acl;
+
+ if (pathconf(source_dir, _PC_ACL_EXTENDED) != 1 ||
+ pathconf(dest_dir, _PC_ACL_EXTENDED) != 1)
+ return (0);
+ /*
+ * If the file is a link we will not follow it
+ */
+ if (S_ISLNK(fs->st_mode)) {
+ aclgetf = acl_get_link_np;
+ aclsetf = acl_set_link_np;
+ } else {
+ aclgetf = acl_get_file;
+ aclsetf = acl_set_file;
+ }
+ /*
+ * Even if there is no ACL_TYPE_DEFAULT entry here, a zero
+ * size ACL will be returned. So it is not safe to simply
+ * check the pointer to see if the default ACL is present.
+ */
+ acl = aclgetf(source_dir, ACL_TYPE_DEFAULT);
+ if (acl == NULL) {
+ warn("failed to get default acl entries on %s",
+ source_dir);
+ return (1);
+ }
+ aclp = &acl->ats_acl;
+ if (aclp->acl_cnt != 0 && aclsetf(dest_dir,
+ ACL_TYPE_DEFAULT, acl) < 0) {
+ warn("failed to set default acl entries on %s",
+ dest_dir);
+ return (1);
+ }
+ acl = aclgetf(source_dir, ACL_TYPE_ACCESS);
+ if (acl == NULL) {
+ warn("failed to get acl entries on %s", source_dir);
+ return (1);
+ }
+ aclp = &acl->ats_acl;
+ if (aclsetf(dest_dir, ACL_TYPE_ACCESS, acl) < 0) {
+ warn("failed to set acl entries on %s", dest_dir);
+ return (1);
+ }
+#endif
+ return (0);
+}
+
+void
+usage(rtems_shell_cp_globals* cp_globals)
+{
+ (void)fprintf(stderr, "%s\n%s\n",
+"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file target_file",
+" cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file ... "
+"target_directory");
+ longjmp (cp_globals->exit_jmp, 1);
+}
diff --git a/cpukit/libmisc/shell/utils-ls.c b/cpukit/libmisc/shell/utils-ls.c
new file mode 100644
index 0000000000..7ff0d1b4bd
--- /dev/null
+++ b/cpukit/libmisc/shell/utils-ls.c
@@ -0,0 +1,117 @@
+/* $NetBSD: util.c,v 1.28 2005/06/17 14:36:16 hira Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Fischbein.
+ *
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if 0
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)util.c 8.5 (Berkeley) 4/28/95";
+#else
+__RCSID("$NetBSD: util.c,v 1.28 2005/06/17 14:36:16 hira Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fts.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vis.h>
+
+#include "extern-ls.h"
+
+#define SIZE_T_MAX 255
+
+int
+safe_print(rtems_shell_ls_globals* globals, const char *src)
+{
+ size_t len;
+ char *name;
+ int flags;
+
+ flags = VIS_NL | VIS_OCTAL;
+ if (f_octal_escape)
+ flags |= VIS_CSTYLE;
+
+ len = strlen(src);
+ if (len != 0 && SIZE_T_MAX/len <= 4) {
+ errx(exit_jump, EXIT_FAILURE, "%s: name too long", src);
+ /* NOTREACHED */
+ }
+
+ name = (char *)malloc(4*len+1);
+ if (name != NULL) {
+ len = strvis(name, src, flags);
+ printf("%s", name);
+ free(name);
+ return len;
+ } else
+ errx(exit_jump, EXIT_FAILURE, "out of memory!");
+ /* NOTREACHED */
+}
+
+int
+printescaped(rtems_shell_ls_globals* globals __attribute__((unused)), const char *src)
+{
+ unsigned char c;
+ int n;
+
+ for (n = 0; (c = *src) != '\0'; ++src, ++n)
+ if (isprint(c))
+ (void)putchar(c);
+ else
+ (void)putchar('?');
+ return n;
+}
+
+void
+usage(rtems_shell_ls_globals* globals)
+{
+
+ (void)fprintf(stderr,
+ "usage: %s [-AaBbCcdFfghikLlmnopqRrSsTtuWwx1] [file ...]\n",
+ "ls");
+ exit(EXIT_FAILURE);
+ /* NOTREACHED */
+}
diff --git a/cpukit/libmisc/shell/verr.c b/cpukit/libmisc/shell/verr.c
new file mode 100644
index 0000000000..301e229a1c
--- /dev/null
+++ b/cpukit/libmisc/shell/verr.c
@@ -0,0 +1,75 @@
+/* $NetBSD: verr.c,v 1.13 2005/09/13 01:44:09 christos Exp $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: verr.c,v 1.13 2005/09/13 01:44:09 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __weak_alias
+__weak_alias(verr, _verr)
+#endif
+
+__dead void
+verr(jmp_buf* exit_jmp, int eval __attribute__((unused)), const char *fmt, _BSD_VA_LIST_ ap)
+{
+ int sverrno;
+
+ sverrno = errno;
+#if 0
+ (void)fprintf(stderr, "%s: ", getprogname());
+#endif
+ if (fmt != NULL) {
+ (void)vfprintf(stdout, fmt, ap);
+ (void)fprintf(stdout, ": ");
+ }
+ (void)fprintf(stdout, "%s\n", strerror(sverrno));
+ longjmp (*exit_jmp, 1);
+}
diff --git a/cpukit/libmisc/shell/verrx.c b/cpukit/libmisc/shell/verrx.c
new file mode 100644
index 0000000000..30355dd31c
--- /dev/null
+++ b/cpukit/libmisc/shell/verrx.c
@@ -0,0 +1,68 @@
+/* $NetBSD: verrx.c,v 1.13 2005/09/13 01:44:09 christos Exp $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: verrx.c,v 1.13 2005/09/13 01:44:09 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef __weak_alias
+__weak_alias(verrx, _verrx)
+#endif
+
+__dead void
+verrx(jmp_buf* exit_jmp, int eval __attribute__((unused)), const char *fmt, _BSD_VA_LIST_ ap)
+{
+#if 0
+ (void)fprintf(stderr, "%s: ", getprogname());
+#endif
+ if (fmt != NULL)
+ (void)vfprintf(stdout, fmt, ap);
+ (void)fprintf(stdout, "\n");
+ longjmp (*exit_jmp, 1);
+}
diff --git a/cpukit/libmisc/shell/vis.c b/cpukit/libmisc/shell/vis.c
new file mode 100644
index 0000000000..6316555279
--- /dev/null
+++ b/cpukit/libmisc/shell/vis.c
@@ -0,0 +1,387 @@
+/* $NetBSD: vis.c,v 1.33 2005/05/28 13:11:14 lukem Exp $ */
+
+/*-
+ * 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. 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.
+ */
+
+/*-
+ * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define _DIAGASSERT(a)
+
+#if 0
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: vis.c,v 1.33 2005/05/28 13:11:14 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#include <sys/types.h>
+
+#include <vis.h>
+#include <stdlib.h>
+
+#if !HAVE_VIS || !HAVE_SVIS
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef BELL
+#define BELL '\a'
+
+#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+#define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
+#define issafe(c) (c == '\b' || c == BELL || c == '\r')
+#define xtoa(c) "0123456789abcdef"[c]
+
+#define MAXEXTRAS 5
+
+
+#define MAKEEXTRALIST(flag, extra, orig) \
+do { \
+ const char *o = orig; \
+ char *e; \
+ while (*o++) \
+ continue; \
+ extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \
+ if (!extra) break; \
+ for (o = orig, e = extra; (*e++ = *o++) != '\0';) \
+ continue; \
+ e--; \
+ if (flag & VIS_SP) *e++ = ' '; \
+ if (flag & VIS_TAB) *e++ = '\t'; \
+ if (flag & VIS_NL) *e++ = '\n'; \
+ if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \
+ *e = '\0'; \
+} while (/*CONSTCOND*/0)
+
+
+/*
+ * This is HVIS, the macro of vis used to HTTP style (RFC 1808)
+ */
+#define HVIS(dst, c, flag, nextc, extra) \
+do \
+ if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { \
+ *dst++ = '%'; \
+ *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); \
+ *dst++ = xtoa((unsigned int)c & 0xf); \
+ } else { \
+ SVIS(dst, c, flag, nextc, extra); \
+ } \
+while (/*CONSTCOND*/0)
+
+/*
+ * This is SVIS, the central macro of vis.
+ * dst: Pointer to the destination buffer
+ * c: Character to encode
+ * flag: Flag word
+ * nextc: The character following 'c'
+ * extra: Pointer to the list of extra characters to be
+ * backslash-protected.
+ */
+#define SVIS(dst, c, flag, nextc, extra) \
+do { \
+ int isextra; \
+ isextra = strchr(extra, c) != NULL; \
+ if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \
+ ((flag & VIS_SAFE) && issafe(c)))) { \
+ *dst++ = c; \
+ break; \
+ } \
+ if (flag & VIS_CSTYLE) { \
+ switch (c) { \
+ case '\n': \
+ *dst++ = '\\'; *dst++ = 'n'; \
+ continue; \
+ case '\r': \
+ *dst++ = '\\'; *dst++ = 'r'; \
+ continue; \
+ case '\b': \
+ *dst++ = '\\'; *dst++ = 'b'; \
+ continue; \
+ case BELL: \
+ *dst++ = '\\'; *dst++ = 'a'; \
+ continue; \
+ case '\v': \
+ *dst++ = '\\'; *dst++ = 'v'; \
+ continue; \
+ case '\t': \
+ *dst++ = '\\'; *dst++ = 't'; \
+ continue; \
+ case '\f': \
+ *dst++ = '\\'; *dst++ = 'f'; \
+ continue; \
+ case ' ': \
+ *dst++ = '\\'; *dst++ = 's'; \
+ continue; \
+ case '\0': \
+ *dst++ = '\\'; *dst++ = '0'; \
+ if (isoctal(nextc)) { \
+ *dst++ = '0'; \
+ *dst++ = '0'; \
+ } \
+ continue; \
+ default: \
+ if (isgraph(c)) { \
+ *dst++ = '\\'; *dst++ = c; \
+ continue; \
+ } \
+ } \
+ } \
+ if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \
+ *dst++ = '\\'; \
+ *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; \
+ *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; \
+ *dst++ = (c & 07) + '0'; \
+ } else { \
+ if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \
+ if (c & 0200) { \
+ c &= 0177; *dst++ = 'M'; \
+ } \
+ if (iscntrl(c)) { \
+ *dst++ = '^'; \
+ if (c == 0177) \
+ *dst++ = '?'; \
+ else \
+ *dst++ = c + '@'; \
+ } else { \
+ *dst++ = '-'; *dst++ = c; \
+ } \
+ } \
+} while (/*CONSTCOND*/0)
+
+
+/*
+ * svis - visually encode characters, also encoding the characters
+ * pointed to by `extra'
+ */
+char *
+svis(char *dst, int c, int flag, int nextc, const char *extra)
+{
+ char *nextra = NULL;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(extra != NULL);
+ MAKEEXTRALIST(flag, nextra, extra);
+ if (!nextra) {
+ *dst = '\0'; /* can't create nextra, return "" */
+ return dst;
+ }
+ if (flag & VIS_HTTPSTYLE)
+ HVIS(dst, c, flag, nextc, nextra);
+ else
+ SVIS(dst, c, flag, nextc, nextra);
+ free(nextra);
+ *dst = '\0';
+ return dst;
+}
+
+
+/*
+ * strsvis, strsvisx - visually encode characters from src into dst
+ *
+ * Extra is a pointer to a \0-terminated list of characters to
+ * be encoded, too. These functions are useful e. g. to
+ * encode strings in such a way so that they are not interpreted
+ * by a shell.
+ *
+ * Dst must be 4 times the size of src to account for possible
+ * expansion. The length of dst, not including the trailing NULL,
+ * is returned.
+ *
+ * Strsvisx encodes exactly len bytes from src into dst.
+ * This is useful for encoding a block of data.
+ */
+int
+strsvis(char *dst, const char *csrc, int flag, const char *extra)
+{
+ int c;
+ char *start;
+ char *nextra = NULL;
+ const unsigned char *src = (const unsigned char *)csrc;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(src != NULL);
+ _DIAGASSERT(extra != NULL);
+ MAKEEXTRALIST(flag, nextra, extra);
+ if (!nextra) {
+ *dst = '\0'; /* can't create nextra, return "" */
+ return 0;
+ }
+ if (flag & VIS_HTTPSTYLE) {
+ for (start = dst; (c = *src++) != '\0'; /* empty */)
+ HVIS(dst, c, flag, *src, nextra);
+ } else {
+ for (start = dst; (c = *src++) != '\0'; /* empty */)
+ SVIS(dst, c, flag, *src, nextra);
+ }
+ free(nextra);
+ *dst = '\0';
+ return (dst - start);
+}
+
+
+int
+strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra)
+{
+ unsigned char c;
+ char *start;
+ char *nextra = NULL;
+ const unsigned char *src = (const unsigned char *)csrc;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(src != NULL);
+ _DIAGASSERT(extra != NULL);
+ MAKEEXTRALIST(flag, nextra, extra);
+ if (! nextra) {
+ *dst = '\0'; /* can't create nextra, return "" */
+ return 0;
+ }
+
+ if (flag & VIS_HTTPSTYLE) {
+ for (start = dst; len > 0; len--) {
+ c = *src++;
+ HVIS(dst, c, flag, len ? *src : '\0', nextra);
+ }
+ } else {
+ for (start = dst; len > 0; len--) {
+ c = *src++;
+ SVIS(dst, c, flag, len ? *src : '\0', nextra);
+ }
+ }
+ free(nextra);
+ *dst = '\0';
+ return (dst - start);
+}
+#endif
+
+#if !HAVE_VIS
+/*
+ * vis - visually encode characters
+ */
+char *
+vis(char *dst, int c, int flag, int nextc)
+{
+ char *extra = NULL;
+ unsigned char uc = (unsigned char)c;
+
+ _DIAGASSERT(dst != NULL);
+
+ MAKEEXTRALIST(flag, extra, "");
+ if (! extra) {
+ *dst = '\0'; /* can't create extra, return "" */
+ return dst;
+ }
+ if (flag & VIS_HTTPSTYLE)
+ HVIS(dst, uc, flag, nextc, extra);
+ else
+ SVIS(dst, uc, flag, nextc, extra);
+ free(extra);
+ *dst = '\0';
+ return dst;
+}
+
+
+/*
+ * strvis, strvisx - visually encode characters from src into dst
+ *
+ * Dst must be 4 times the size of src to account for possible
+ * expansion. The length of dst, not including the trailing NULL,
+ * is returned.
+ *
+ * Strvisx encodes exactly len bytes from src into dst.
+ * This is useful for encoding a block of data.
+ */
+int
+strvis(char *dst, const char *src, int flag)
+{
+ char *extra = NULL;
+ int rv;
+
+ MAKEEXTRALIST(flag, extra, "");
+ if (!extra) {
+ *dst = '\0'; /* can't create extra, return "" */
+ return 0;
+ }
+ rv = strsvis(dst, src, flag, extra);
+ free(extra);
+ return rv;
+}
+
+
+int
+strvisx(char *dst, const char *src, size_t len, int flag)
+{
+ char *extra = NULL;
+ int rv;
+
+ MAKEEXTRALIST(flag, extra, "");
+ if (!extra) {
+ *dst = '\0'; /* can't create extra, return "" */
+ return 0;
+ }
+ rv = strsvisx(dst, src, len, flag, extra);
+ free(extra);
+ return rv;
+}
+#endif
diff --git a/cpukit/libmisc/shell/vis.h b/cpukit/libmisc/shell/vis.h
new file mode 100644
index 0000000000..fb0aa6dc2a
--- /dev/null
+++ b/cpukit/libmisc/shell/vis.h
@@ -0,0 +1,91 @@
+/* $NetBSD: vis.h,v 1.16 2005/09/13 01:44:32 christos Exp $ */
+
+/*-
+ * 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. 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.
+ *
+ * @(#)vis.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _VIS_H_
+#define _VIS_H_
+
+#include <sys/types.h>
+
+/*
+ * to select alternate encoding format
+ */
+#define VIS_OCTAL 0x01 /* use octal \ddd format */
+#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropiate */
+
+/*
+ * to alter set of characters encoded (default is to encode all
+ * non-graphic except space, tab, and newline).
+ */
+#define VIS_SP 0x04 /* also encode space */
+#define VIS_TAB 0x08 /* also encode tab */
+#define VIS_NL 0x10 /* also encode newline */
+#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
+#define VIS_SAFE 0x20 /* only encode "unsafe" characters */
+
+/*
+ * other
+ */
+#define VIS_NOSLASH 0x40 /* inhibit printing '\' */
+#define VIS_HTTPSTYLE 0x80 /* http-style escape % HEX HEX */
+
+/*
+ * unvis return codes
+ */
+#define UNVIS_VALID 1 /* character valid */
+#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */
+#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */
+#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */
+#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */
+
+/*
+ * unvis flags
+ */
+#define UNVIS_END 1 /* no more characters */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+char *vis(char *, int, int, int);
+char *svis(char *, int, int, int, const char *);
+int strvis(char *, const char *, int);
+int strsvis(char *, const char *, int, const char *);
+int strvisx(char *, const char *, size_t, int);
+int strsvisx(char *, const char *, size_t, int, const char *);
+int strunvis(char *, const char *);
+int strunvisx(char *, const char *, int);
+#ifndef __LIBC12_SOURCE__
+//int unvis(char *, int, int *, int) __RENAME(__unvis13);
+#endif
+__END_DECLS
+
+#endif /* !_VIS_H_ */
diff --git a/cpukit/libmisc/shell/vwarn.c b/cpukit/libmisc/shell/vwarn.c
new file mode 100644
index 0000000000..df214c5db9
--- /dev/null
+++ b/cpukit/libmisc/shell/vwarn.c
@@ -0,0 +1,74 @@
+/* $NetBSD: vwarn.c,v 1.13 2005/09/13 01:44:09 christos Exp $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: vwarn.c,v 1.13 2005/09/13 01:44:09 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __weak_alias
+__weak_alias(vwarn, _vwarn)
+#endif
+
+void
+vwarn(const char *fmt, _BSD_VA_LIST_ ap)
+{
+ int sverrno;
+
+ sverrno = errno;
+#if 0
+ (void)fprintf(stderr, "%s: ", getprogname());
+#endif
+ if (fmt != NULL) {
+ (void)vfprintf(stdout, fmt, ap);
+ (void)fprintf(stdout, ": ");
+ }
+ (void)fprintf(stdout, "%s\n", strerror(sverrno));
+}
diff --git a/cpukit/libmisc/shell/vwarnx.c b/cpukit/libmisc/shell/vwarnx.c
new file mode 100644
index 0000000000..34737a17f1
--- /dev/null
+++ b/cpukit/libmisc/shell/vwarnx.c
@@ -0,0 +1,67 @@
+/* $NetBSD: vwarnx.c,v 1.13 2005/09/13 01:44:09 christos Exp $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: vwarnx.c,v 1.13 2005/09/13 01:44:09 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef __weak_alias
+__weak_alias(vwarnx, _vwarnx)
+#endif
+
+void
+vwarnx(const char *fmt, _BSD_VA_LIST_ ap)
+{
+#if 0
+ (void)fprintf(stderr, "%s: ", getprogname());
+#endif
+ if (fmt != NULL)
+ (void)vfprintf(stdout, fmt, ap);
+ (void)fprintf(stdout, "\n");
+}
diff --git a/cpukit/libmisc/shell/warn.c b/cpukit/libmisc/shell/warn.c
new file mode 100644
index 0000000000..f32edfb630
--- /dev/null
+++ b/cpukit/libmisc/shell/warn.c
@@ -0,0 +1,64 @@
+/* $NetBSD: warn.c,v 1.13 2005/09/13 13:51:50 christos Exp $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: warn.c,v 1.13 2005/09/13 13:51:50 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <stdarg.h>
+
+#ifdef __weak_alias
+__weak_alias(warn, _warn)
+#endif
+
+void
+warn(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vwarn(fmt, ap);
+ va_end(ap);
+}
diff --git a/cpukit/libmisc/shell/warnx.c b/cpukit/libmisc/shell/warnx.c
new file mode 100644
index 0000000000..efcbd8b0f1
--- /dev/null
+++ b/cpukit/libmisc/shell/warnx.c
@@ -0,0 +1,64 @@
+/* $NetBSD: warnx.c,v 1.13 2005/09/13 13:51:50 christos Exp $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: warnx.c,v 1.13 2005/09/13 13:51:50 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <stdarg.h>
+
+#ifdef __weak_alias
+__weak_alias(warnx, _warnx)
+#endif
+
+void
+warnx(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+}
diff --git a/cpukit/libmisc/shell/write_file.c b/cpukit/libmisc/shell/write_file.c
new file mode 100644
index 0000000000..f9e72f4645
--- /dev/null
+++ b/cpukit/libmisc/shell/write_file.c
@@ -0,0 +1,43 @@
+/*
+ *
+ * Write buffer to a file
+ *
+ * Author:
+ *
+ * WORK: fernando.ruiz@ctv.es
+ * HOME: correo@fernando-ruiz.com
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+void rtems_shell_write_file(
+ const char *name,
+ const char *content
+)
+{
+ FILE * fd;
+
+ fd = fopen(name,"w");
+ if ( !fd ) {
+ fprintf( stderr, "Unable to write %s\n", name );
+ }
+
+ if (fd) {
+ fwrite(content,1,strlen(content),fd);
+ fclose(fd);
+ }
+}
+
+