summaryrefslogtreecommitdiffstats
path: root/cpukit/libmisc
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libmisc')
-rw-r--r--cpukit/libmisc/.cvsignore2
-rw-r--r--cpukit/libmisc/Makefile.am161
-rw-r--r--cpukit/libmisc/README23
-rw-r--r--cpukit/libmisc/bspcmdline/bspcmdline.h128
-rw-r--r--cpukit/libmisc/bspcmdline/bspcmdline_get.c23
-rw-r--r--cpukit/libmisc/bspcmdline/bspcmdline_getparam.c67
-rw-r--r--cpukit/libmisc/bspcmdline/bspcmdline_getparamraw.c37
-rw-r--r--cpukit/libmisc/bspcmdline/bspcmdline_getparamrhs.c48
-rw-r--r--cpukit/libmisc/capture/README255
-rw-r--r--cpukit/libmisc/capture/capture-cli.c1622
-rw-r--r--cpukit/libmisc/capture/capture-cli.h56
-rw-r--r--cpukit/libmisc/capture/capture.c1938
-rw-r--r--cpukit/libmisc/capture/capture.h1042
-rw-r--r--cpukit/libmisc/cpuuse/README21
-rw-r--r--cpukit/libmisc/cpuuse/cpuusagedata.c28
-rw-r--r--cpukit/libmisc/cpuuse/cpuusagereport.c205
-rw-r--r--cpukit/libmisc/cpuuse/cpuusagereset.c60
-rw-r--r--cpukit/libmisc/cpuuse/cpuuse.h51
-rw-r--r--cpukit/libmisc/devnull/devnull.c184
-rw-r--r--cpukit/libmisc/devnull/devnull.h73
-rw-r--r--cpukit/libmisc/dummy/README23
-rw-r--r--cpukit/libmisc/dummy/dummy-networking.c44
-rw-r--r--cpukit/libmisc/dummy/dummy.c38
-rw-r--r--cpukit/libmisc/dumpbuf/dumpbuf.c80
-rw-r--r--cpukit/libmisc/dumpbuf/dumpbuf.h39
-rw-r--r--cpukit/libmisc/fb/fb.h91
-rw-r--r--cpukit/libmisc/fb/mw_print.c92
-rw-r--r--cpukit/libmisc/fb/mw_uid.c150
-rw-r--r--cpukit/libmisc/fb/mw_uid.h185
-rw-r--r--cpukit/libmisc/fsmount/README24
-rw-r--r--cpukit/libmisc/fsmount/fsmount.c138
-rw-r--r--cpukit/libmisc/fsmount/fsmount.h209
-rw-r--r--cpukit/libmisc/monitor/README97
-rw-r--r--cpukit/libmisc/monitor/mon-command.c244
-rw-r--r--cpukit/libmisc/monitor/mon-config.c136
-rw-r--r--cpukit/libmisc/monitor/mon-driver.c144
-rw-r--r--cpukit/libmisc/monitor/mon-editor.c643
-rw-r--r--cpukit/libmisc/monitor/mon-extension.c102
-rw-r--r--cpukit/libmisc/monitor/mon-itask.c121
-rw-r--r--cpukit/libmisc/monitor/mon-manager.c55
-rw-r--r--cpukit/libmisc/monitor/mon-monitor.c529
-rw-r--r--cpukit/libmisc/monitor/mon-mpci.c163
-rw-r--r--cpukit/libmisc/monitor/mon-network.c342
-rw-r--r--cpukit/libmisc/monitor/mon-object.c423
-rw-r--r--cpukit/libmisc/monitor/mon-part.c72
-rw-r--r--cpukit/libmisc/monitor/mon-prmisc.c259
-rw-r--r--cpukit/libmisc/monitor/mon-queue.c68
-rw-r--r--cpukit/libmisc/monitor/mon-region.c73
-rw-r--r--cpukit/libmisc/monitor/mon-sema.c84
-rw-r--r--cpukit/libmisc/monitor/mon-server.c309
-rw-r--r--cpukit/libmisc/monitor/mon-symbols.c490
-rw-r--r--cpukit/libmisc/monitor/mon-task.c105
-rw-r--r--cpukit/libmisc/monitor/monitor.h531
-rw-r--r--cpukit/libmisc/monitor/symbols.h64
-rw-r--r--cpukit/libmisc/mouse/README214
-rw-r--r--cpukit/libmisc/mouse/mouse_parser.c311
-rw-r--r--cpukit/libmisc/mouse/mouse_parser.h108
-rw-r--r--cpukit/libmisc/mouse/serial_mouse.c184
-rw-r--r--cpukit/libmisc/mouse/serial_mouse.h156
-rw-r--r--cpukit/libmisc/preinstall.am9
-rw-r--r--cpukit/libmisc/serdbg/README138
-rw-r--r--cpukit/libmisc/serdbg/serdbg.c92
-rw-r--r--cpukit/libmisc/serdbg/serdbg.h187
-rw-r--r--cpukit/libmisc/serdbg/serdbgcnf.h89
-rw-r--r--cpukit/libmisc/serdbg/serdbgio.c256
-rw-r--r--cpukit/libmisc/serdbg/termios_printk.c241
-rw-r--r--cpukit/libmisc/serdbg/termios_printk.h104
-rw-r--r--cpukit/libmisc/serdbg/termios_printk_cnf.h78
-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
-rw-r--r--cpukit/libmisc/stackchk/README53
-rw-r--r--cpukit/libmisc/stackchk/check.c515
-rw-r--r--cpukit/libmisc/stackchk/internal.h95
-rw-r--r--cpukit/libmisc/stackchk/stackchk.h135
-rw-r--r--cpukit/libmisc/stringto/stringto.h246
-rw-r--r--cpukit/libmisc/stringto/stringtodouble.c58
-rw-r--r--cpukit/libmisc/stringto/stringtofloat.c58
-rw-r--r--cpukit/libmisc/stringto/stringtoint.c73
-rw-r--r--cpukit/libmisc/stringto/stringtolong.c59
-rw-r--r--cpukit/libmisc/stringto/stringtolongdouble.c58
-rw-r--r--cpukit/libmisc/stringto/stringtolonglong.c68
-rw-r--r--cpukit/libmisc/stringto/stringtopointer.c47
-rw-r--r--cpukit/libmisc/stringto/stringtounsignedchar.c66
-rw-r--r--cpukit/libmisc/stringto/stringtounsignedint.c66
-rw-r--r--cpukit/libmisc/stringto/stringtounsignedlong.c59
-rw-r--r--cpukit/libmisc/stringto/stringtounsignedlonglong.c64
-rw-r--r--cpukit/libmisc/untar/README26
-rw-r--r--cpukit/libmisc/untar/untar.c384
-rw-r--r--cpukit/libmisc/untar/untar.h49
-rw-r--r--cpukit/libmisc/uuid/COPYING25
-rw-r--r--cpukit/libmisc/uuid/README14
-rw-r--r--cpukit/libmisc/uuid/clear.c47
-rw-r--r--cpukit/libmisc/uuid/compare.c59
-rw-r--r--cpukit/libmisc/uuid/copy.c49
-rw-r--r--cpukit/libmisc/uuid/gen_uuid.c670
-rw-r--r--cpukit/libmisc/uuid/isnull.c52
-rw-r--r--cpukit/libmisc/uuid/pack.c73
-rw-r--r--cpukit/libmisc/uuid/parse.c83
-rw-r--r--cpukit/libmisc/uuid/unpack.c67
-rw-r--r--cpukit/libmisc/uuid/unparse.c80
-rw-r--r--cpukit/libmisc/uuid/uuid.h103
-rw-r--r--cpukit/libmisc/uuid/uuidP.h63
-rw-r--r--cpukit/libmisc/uuid/uuid_time.c175
-rw-r--r--cpukit/libmisc/uuid/uuidd.h53
211 files changed, 37431 insertions, 0 deletions
diff --git a/cpukit/libmisc/.cvsignore b/cpukit/libmisc/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/libmisc/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
new file mode 100644
index 0000000000..f288f14f2b
--- /dev/null
+++ b/cpukit/libmisc/Makefile.am
@@ -0,0 +1,161 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+EXTRA_DIST = README
+
+noinst_LIBRARIES =
+
+## bspcmdline
+noinst_LIBRARIES += libbspcmdline.a
+libbspcmdline_a_SOURCES = bspcmdline/bspcmdline_get.c \
+ bspcmdline/bspcmdline_getparam.c bspcmdline/bspcmdline_getparamraw.c \
+ bspcmdline/bspcmdline_getparamrhs.c
+
+## capture
+EXTRA_DIST += capture/README
+
+noinst_LIBRARIES += libcapture.a
+libcapture_a_SOURCES = capture/capture.c capture/capture-cli.c \
+ capture/capture.h capture/capture-cli.h
+
+## cpuuse
+EXTRA_DIST += cpuuse/README
+
+noinst_LIBRARIES += libcpuuse.a
+libcpuuse_a_SOURCES = cpuuse/cpuusagereport.c cpuuse/cpuusagereset.c \
+ cpuuse/cpuuse.h cpuuse/cpuusagedata.c
+
+## devnull
+noinst_LIBRARIES += libdevnull.a
+libdevnull_a_SOURCES = devnull/devnull.c devnull/devnull.h
+
+## dummy
+EXTRA_DIST += dummy/README
+
+noinst_LIBRARIES += libdummy.a
+libdummy_a_SOURCES = dummy/dummy.c dummy/dummy-networking.c
+
+## dumpbuf
+noinst_LIBRARIES += libdumpbuf.a
+libdumpbuf_a_SOURCES = dumpbuf/dumpbuf.c dumpbuf/dumpbuf.h
+
+## monitor
+noinst_LIBRARIES += libmonitor.a
+libmonitor_a_SOURCES = monitor/mon-command.c monitor/mon-symbols.c \
+ monitor/mon-prmisc.c monitor/mon-monitor.c monitor/mon-object.c \
+ monitor/mon-server.c monitor/mon-task.c monitor/mon-queue.c \
+ monitor/mon-driver.c monitor/mon-itask.c monitor/mon-extension.c \
+ monitor/mon-manager.c monitor/mon-config.c monitor/mon-part.c \
+ monitor/mon-region.c monitor/mon-sema.c monitor/mon-editor.c \
+ monitor/symbols.h monitor/monitor.h
+if LIBNETWORKING
+libmonitor_a_SOURCES += monitor/mon-network.c
+endif
+if HAS_MP
+libmonitor_a_SOURCES += monitor/mon-mpci.c
+endif
+
+EXTRA_DIST += monitor/README
+
+## fb
+noinst_LIBRARIES += libmw-fb.a
+libmw_fb_a_SOURCES = fb/mw_print.c fb/mw_uid.c fb/fb.h fb/mw_uid.h
+
+## mouse
+noinst_LIBRARIES += libmouse.a
+libmouse_a_SOURCES = mouse/mouse_parser.c mouse/serial_mouse.c
+EXTRA_DIST += mouse/README
+
+## shell
+if LIBSHELL
+noinst_LIBRARIES += libshell.a
+libshell_a_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/shell
+libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \
+ shell/main_alias.c shell/main_cat.c shell/main_cd.c shell/cmp-ls.c \
+ shell/main_chdir.c shell/main_chmod.c shell/main_chroot.c \
+ shell/main_cp.c shell/main_cpuuse.c shell/main_date.c shell/main_dir.c \
+ shell/main_echo.c shell/main_exit.c shell/main_halt.c shell/main_help.c \
+ shell/main_id.c shell/main_logoff.c shell/main_ln.c shell/main_ls.c \
+ shell/main_mallocinfo.c shell/main_mdump.c shell/main_medit.c \
+ shell/main_mfill.c shell/main_mkdir.c shell/main_mount.c \
+ shell/main_mmove.c shell/main_msdosfmt.c \
+ shell/main_mv.c shell/main_mwdump.c shell/main_perioduse.c \
+ shell/main_pwd.c shell/main_rm.c shell/main_rmdir.c shell/main_sleep.c \
+ shell/main_stackuse.c shell/main_tty.c shell/main_umask.c \
+ shell/main_unmount.c shell/main_blksync.c shell/main_whoami.c \
+ shell/shell.c shell/shell_cmdset.c shell/shell_getchar.c \
+ shell/shell_getprompt.c shell/shellconfig.c \
+ shell/shellconfig.h shell/shell.h shell/shell_makeargs.c \
+ shell/filemode.c shell/pwcache.c shell/print-ls.c \
+ shell/write_file.c shell/utils-cp.c shell/utils-ls.c \
+ shell/err.c shell/errx.c shell/verr.c shell/vis.c \
+ shell/verrx.c shell/vwarn.c shell/vwarnx.c shell/warn.c shell/warnx.c \
+ shell/fts.c shell/print_heapinfo.c shell/main_wkspaceinfo.c \
+ shell/shell_script.c shell/login_prompt.c shell/login_check.c \
+ shell/fdisk.c shell/main_rtc.c \
+ shell/dd-args.c shell/main_dd.c shell/dd-conv.c shell/dd-conv_tab.c \
+ shell/dd-misc.c shell/dd-position.c \
+ shell/main_hexdump.c shell/hexdump-conv.c shell/hexdump-display.c \
+ shell/hexdump-odsyntax.c shell/hexdump-parse.c shell/hexsyntax.c \
+ shell/main_time.c shell/main_mknod.c \
+ shell/main_setenv.c shell/main_getenv.c shell/main_unsetenv.c \
+ shell/main_mkrfs.c shell/main_debugrfs.c
+
+if LIBNETWORKING
+libshell_a_SOURCES += \
+ shell/main_ifconfig.c shell/main_route.c shell/main_netstats.c
+endif
+endif
+
+EXTRA_DIST += shell/README
+
+## serdbg
+
+if LIBSERDBG
+noinst_LIBRARIES += libserdbg.a
+libserdbg_a_SOURCES = serdbg/serdbg.c serdbg/serdbgio.c \
+ serdbg/termios_printk.c serdbg/serdbgcnf.h serdbg/serdbg.h \
+ serdbg/termios_printk_cnf.h serdbg/termios_printk.h
+endif
+
+EXTRA_DIST += serdbg/README
+
+## stackchk
+noinst_LIBRARIES += libstackchk.a
+libstackchk_a_SOURCES = stackchk/check.c stackchk/internal.h \
+ stackchk/stackchk.h
+
+EXTRA_DIST += stackchk/README
+
+## libuntar
+noinst_LIBRARIES += libuntar.a
+libuntar_a_SOURCES = untar/untar.c untar/untar.h
+
+EXTRA_DIST += untar/README
+
+## stringto
+noinst_LIBRARIES += libstringto.a
+libstringto_a_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/stringto
+libstringto_a_SOURCES = stringto/stringtodouble.c stringto/stringtofloat.c \
+ stringto/stringtolongdouble.c \
+ stringto/stringtoint.c stringto/stringtolong.c stringto/stringtolonglong.c \
+ stringto/stringtopointer.c stringto/stringtounsignedint.c \
+ stringto/stringtounsignedchar.c stringto/stringtounsignedlong.c \
+ stringto/stringtounsignedlonglong.c
+
+## fsmount
+noinst_LIBRARIES += libfsmount.a
+libfsmount_a_SOURCES = fsmount/fsmount.c fsmount/fsmount.h
+
+## uuid
+noinst_LIBRARIES += libuuid.a
+libuuid_a_SOURCES = uuid/clear.c uuid/compare.c uuid/copy.c uuid/gen_uuid.c \
+ uuid/isnull.c uuid/pack.c uuid/parse.c uuid/unpack.c uuid/unparse.c \
+ uuid/uuid_time.c uuid/uuidd.h uuid/uuidP.h
+
+## ---
+include $(srcdir)/preinstall.am
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libmisc/README b/cpukit/libmisc/README
new file mode 100644
index 0000000000..bbde4feeae
--- /dev/null
+++ b/cpukit/libmisc/README
@@ -0,0 +1,23 @@
+#
+# $Id$
+#
+
+This directory contains for the "miscellaneous" library. Currently
+this library contains a number of useful support libraries:
+
+ + Task Stack Overflow Checker
+ + Workspace Consistency Checker
+ + Task Execution Time Monitor
+ + Period Statistics Monitor
+ + Debug Monitor
+
+The following ideas have been mentioned for items which could go
+in this library, but this list is not all inclusive:
+
+ + there are no outstanding suggestions.
+
+The intent of this library is to provide a home for useful utility routines
+which are dependent upon RTEMS.
+
+--joel
+16 Sept 97
diff --git a/cpukit/libmisc/bspcmdline/bspcmdline.h b/cpukit/libmisc/bspcmdline/bspcmdline.h
new file mode 100644
index 0000000000..6d5f716aeb
--- /dev/null
+++ b/cpukit/libmisc/bspcmdline/bspcmdline.h
@@ -0,0 +1,128 @@
+/**
+ * @file rtems/bspcmdline.h
+ *
+ * This include file contains all prototypes and specifications
+ * related to the BSP Command Line String and associated helper
+ * routines. The helpers are useful for locating command line
+ * type arguments (e.g. --mode) and their associated right
+ * hand side (e.g. FAST in --mode=FAST).
+ */
+
+/*
+ * 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$
+ */
+
+#ifndef __BSP_COMMAND_LINE_h
+#define __BSP_COMMAND_LINE_h
+
+/**
+ * @defgroup BSPCommandLine BSP Command Line Helpers
+ *
+ * The BSP Command Line Handler provides a set of routines which assist
+ * in examining and decoding the Command Line String passed to the BSP
+ * at boot time.
+ */
+/**@{*/
+
+#include <stddef.h> /* for size_t */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief Obtain Pointer to BSP Boot Command String
+ *
+ * This method returns a pointer to the BSP Boot Command String. It
+ * is as likely to be NULL as point to a string as most BSPs do not
+ * have a start environment that provides a boot string.
+ *
+ * @return This method returns the pointer to the BSP Boot Command String.
+ */
+const char *rtems_bsp_cmdline_get(void);
+
+/**
+ * @brief Obtain COPY of the Entire Matching Argument
+ *
+ * This method searches for the argument @a name in the BSP Boot Command
+ * String and returns a copy of the entire string associated with it in
+ * @a value up to a string of @a length. This will include the argument
+ * and any right hand side portion of the string. For example, one might
+ * be returned --mode=FAST if
+ * searching for --mode.
+ *
+ * @param[in] name is the arugment to search for
+ * @param[in] value points to where the contents will
+ * be placed if located.
+ * @param[in] length is the maximum length to copy
+ *
+ * @return This method returns NULL if not found and
+ * @a value if found.
+ */
+const char *rtems_bsp_cmdline_get_param(
+ const char *name,
+ char *value,
+ size_t length
+);
+
+
+/**
+ * @brief Obtain COPY of the Right Hand Side of the Matching Argument
+ *
+ * This method searches for the argument @a name in
+ * the BSP Boot Command String and returns the right hand side
+ * associated with it in @a value up to a maximum string @a length.
+ * This will NOT include the argument but only any right hand side
+ * portion of the string. * For example, one might be returned FAST if
+ * searching for --mode.
+ *
+ * @param[in] name is the arugment to search for
+ * @param[in] value points to where the contents will
+ * be placed if located.
+ * @param[in] length is the maximum length to copy
+ *
+ * @return This method returns NULL if not found and
+ * @a value if found.
+ */
+const char *rtems_bsp_cmdline_get_param_rhs(
+ const char *name,
+ char *value,
+ size_t length
+);
+
+/**
+ * @brief Obtain Pointer to the Entire Matching Argument
+ *
+ * This method searches for the argument @a name in
+ * the BSP Boot Command String and returns a pointer to the
+ * entire string associated with it. This will include the
+ * argument and any right hand side portion of the string.
+ * For example, one might be returned --mode=FAST if
+ * searching for --mode.
+ *
+ * @param[in] name is the arugment to search for
+ *
+ * @return This method returns NULL if not found and a pointer
+ * into the BSP Boot Command String if found.
+ *
+ * @note The pointer will be to the original BSP Command
+ * Line string. Exercise caution when using this.
+ */
+const char *rtems_bsp_cmdline_get_param_raw(
+ const char *name
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+#endif
diff --git a/cpukit/libmisc/bspcmdline/bspcmdline_get.c b/cpukit/libmisc/bspcmdline/bspcmdline_get.c
new file mode 100644
index 0000000000..7e06aa47bd
--- /dev/null
+++ b/cpukit/libmisc/bspcmdline/bspcmdline_get.c
@@ -0,0 +1,23 @@
+/*
+ * 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 <rtems/bspcmdline.h>
+
+extern const char *bsp_boot_cmdline;
+
+const char *rtems_bsp_cmdline_get(void)
+{
+ return bsp_boot_cmdline;
+}
diff --git a/cpukit/libmisc/bspcmdline/bspcmdline_getparam.c b/cpukit/libmisc/bspcmdline/bspcmdline_getparam.c
new file mode 100644
index 0000000000..288128bf8d
--- /dev/null
+++ b/cpukit/libmisc/bspcmdline/bspcmdline_getparam.c
@@ -0,0 +1,67 @@
+/*
+ * 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 <rtems/bspcmdline.h>
+
+static void copy_string(
+ const char *start,
+ char *value,
+ size_t length
+)
+{
+ int i;
+ int quotes;
+ const char *p = start;
+
+ quotes=0;
+ for (i=0 ; *p && i<length-1; ) {
+ if ( *p == '\"' ) {
+ quotes++;
+ } else if ( ((quotes % 2) == 0) && *p == ' ' )
+ break;
+ value[i++] = *p++;
+ value[i] = '\0';
+ }
+
+}
+
+const char *rtems_bsp_cmdline_get_param(
+ const char *name,
+ char *value,
+ size_t length
+)
+{
+ const char *p;
+
+ if ( !name )
+ return NULL;
+
+ if ( !value )
+ return NULL;
+
+ if ( !length )
+ return NULL;
+
+ value[0] = '\0';
+
+ p = rtems_bsp_cmdline_get_param_raw( name );
+
+ if ( !p )
+ return NULL;
+
+ copy_string( p, value, length );
+
+ return value;
+}
diff --git a/cpukit/libmisc/bspcmdline/bspcmdline_getparamraw.c b/cpukit/libmisc/bspcmdline/bspcmdline_getparamraw.c
new file mode 100644
index 0000000000..18bda9143f
--- /dev/null
+++ b/cpukit/libmisc/bspcmdline/bspcmdline_getparamraw.c
@@ -0,0 +1,37 @@
+/*
+ * 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 <string.h>
+
+#include <rtems/bspcmdline.h>
+
+extern const char *bsp_boot_cmdline;
+
+const char *rtems_bsp_cmdline_get_param_raw(
+ const char *name
+)
+{
+ const char *p;
+
+ if ( !name )
+ return NULL;
+
+ if ( !bsp_boot_cmdline )
+ return NULL;
+
+ p = strstr(bsp_boot_cmdline, name);
+ /* printf( "raw: %p (%s)\n", p, p ); */
+ return p;
+}
diff --git a/cpukit/libmisc/bspcmdline/bspcmdline_getparamrhs.c b/cpukit/libmisc/bspcmdline/bspcmdline_getparamrhs.c
new file mode 100644
index 0000000000..38269dc44a
--- /dev/null
+++ b/cpukit/libmisc/bspcmdline/bspcmdline_getparamrhs.c
@@ -0,0 +1,48 @@
+/*
+ * 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 <string.h>
+
+#include <rtems/bspcmdline.h>
+
+const char *rtems_bsp_cmdline_get_param_rhs(
+ const char *name,
+ char *value,
+ size_t length
+)
+{
+ const char *p;
+ const char *rhs;
+ char *d;
+
+ p = rtems_bsp_cmdline_get_param( name, value, length );
+ if ( !p )
+ return NULL;
+
+ rhs = &p[strlen(name)];
+ if ( *rhs != '=' )
+ return NULL;
+
+ rhs++;
+ if ( *rhs == '\"' )
+ rhs++;
+ for ( d=value ; *rhs ; )
+ *d++ = *rhs++;
+ if ( *(d-1) == '\"' )
+ d--;
+ *d = '\0';
+
+ return value;
+}
diff --git a/cpukit/libmisc/capture/README b/cpukit/libmisc/capture/README
new file mode 100644
index 0000000000..d12b5570d6
--- /dev/null
+++ b/cpukit/libmisc/capture/README
@@ -0,0 +1,255 @@
+#
+# $Id$
+#
+
+ RTEMS Performance Monitoring and Measurement Framework
+
+ Copyright 2002-2007 Chris Johns (chrisj@rtems.org)
+ 23 April 2002
+
+This directory contains the source code for the performance monitoring and
+measurement framework. It is more commonly know as the capture engine.
+
+The capture engine is in an early phase of development. Please review the Status
+section of this document for the current status.
+
+Performance.
+
+The capture engine is designed to not effect the system it is
+monitoring. Resources such as memory are used as well as a small performance
+hit in task creation, deletion and context switch. The overhead is small and
+will not be noticed unless the system is operating close to the performance
+limit of the target.
+
+Structure.
+
+The capture engine is implemented in a couple of layers. This lowest layer is
+the capture engine. Its interface is in the file 'capture.h'. Typically this
+interface is directly used unless you are implementing a target interface. The
+user interface is via a target interface.
+
+Command Line Interface (CLI).
+
+This is a target interface that provides a number of user commands via the
+RTEMS monitor. To use you need to provide the following in your
+application initialisation:
+
+ #include <rtems/monitor.h>
+ #include <rtems/capture-cli.h>
+
+ rtems_monitor_init (0);
+ rtems_capture_cli_init (0);
+
+Check the file capture-cli.h for documentation of the interface. The parameter
+is a pointer to your board support package's time stamp handler. The time stamp
+handler is yet to be tested so it is recommended this is left as 0, unless you
+wish to test this part of the engine.
+
+The commands are:
+
+ copen - Open the capture engine.
+ cclose - Close the capture engine.
+ cenable - Enable the capture engine.
+ cdisable - Disable the capture engine.
+ ctlist - List the tasks known to the capture engine.
+ ctload - Display the current load (sort of top).
+ cwlist - List the watch and trigger controls.
+ cwadd - Add a watch.
+ cwdel - Delete a watch.
+ cwctl - Enable or disable a watch.
+ cwglob - Enable or disable the global watch.
+ cwceil - Set the watch ceiling.
+ cwfloor - Set the watch floor.
+ ctrace - Dump the trace records.
+ ctrig - Define a trigger.
+
+Open
+
+ usage: copen [-i] size
+
+Open the capture engine. The size parameter is the size of the capture engine
+trace buffer. A single record hold a single event, for example a task create or
+a context in or out. The option '-i' will enable the capture engine after it is
+opened.
+
+Close
+
+ usage: cclose
+
+Close the capture engine and release all resources held by the capture engine.
+
+Enable
+
+ usage: cenable
+
+Enable the capture engine if it has been opened.
+
+Disable
+
+ usage: cdisable
+
+Disable the capture engine. The enable and disable commands provide a means of
+removing the overhead of the capture engine from the context switch. This may
+be needed when testing if it is felt the capture engines overhead is effecting
+the system.
+
+Task List
+
+ usage: ctlist
+
+List the tasks the capture engine knows about. This may contain tasks that have
+been deleted.
+
+Task Load
+
+ usage: ctload
+
+List the tasks in the order of load in a similar way top does on Unix. The
+command sends ANSI terminal codes. You press enter to stop the update. The
+update period is fixed at 5 seconds. The output looks like:
+
+ Press ENTER to exit.
+
+ PID NAME RPRI CPRI STATE %CPU %STK FLGS EXEC TIME
+04010001 IDLE 255 255 READY 96.012% 0% a-----g 1
+08010009 CPlt 1 1 READY 3.815% 15% a------ 0
+08010003 ntwk 20 20 Wevnt 0.072% 0% at----g 0
+08010004 CSr0 20 20 Wevnt 0.041% 0% at----g 0
+08010001 main 250 250 DELAY 0.041% 0% a-----g 0
+08010008 test 100 100 Wevnt 0.000% 20% at-T-+g 0
+08010007 test 100 100 Wevnt 0.000% 0% at-T-+g 0
+08010005 CSt0 20 20 Wevnt 0.000% 0% at----g 0
+08010006 RMON 1 1 Wsem 0.000% 0% a------ 0
+
+There are 7 flags and from left to right are:
+
+1) 'a' the task is active, and 'd' the task has been deleted.
+2) 't' the task has been traced.
+3) 'F' the task has a from (TO_ANY) trigger.
+4) 'T' the task has a to (FROM_ANY) trigger.
+5) 'E' the task has an edge (FROM_TO) trigger.
+6) '+' the task as a watch control attached, 'w' a watch is enabled.
+7) 'g' the task is part of a global trigger.
+
+The %STK is the percentage of stack used by a task. Currently only tasks
+created while the capture engine is enabled can be monitored.
+
+The RPRI is the real priority. This is the priority set for the task. The
+current priority is the executing priority that may reflect a level set as a
+result of priority inversion.
+
+Watch List
+
+ usage: cwlist
+
+This command lists the watch and trigger controls the capture engine has. A
+control is a structure used by the capture engine to determine if a task is
+watched or triggers capturing.
+
+Watch Add
+
+ usage: cwadd [task name] [id]
+
+Add a watch for a task. You can provide a name or id or both. A name will cause
+all tasks with that name to have the watch added. An id results in a watch
+being for a specific task.
+
+Using a name is useful when the task is not yet created.
+
+Watch Delete
+
+ usage: cwdel [task name] [id]
+
+Delete a watch that has been added.
+
+Watch Control
+
+ usage: cwctl [task name] [id] on/off
+
+Enable or disable a watch. The name and id parameters are the same as the watch
+add command.
+
+Global Watch
+
+ usage: cwglob on/off
+
+Enable or disable the global watch. A global watch is an easy way to enable
+watches for all tasks with real priorities between the watch ceiling and floor
+priorities.
+
+Watch Priority Ceiling
+
+ usage: cwceil priority
+
+Set the watch priority ceiling. All tasks with a priority less than the ceiling
+priority are not watched. This allow you to ignore high priority system and
+driver tasks.
+
+Watch Priority Floor
+
+ usage: cwfloor priority
+
+Set the watch priority floor. All tasks with a priority greater than the floor
+priority level are not watched. This allows you to remove tasks such as IDLE
+from being monitored.
+
+Trace
+
+ usage: ctrace [-c] [-r records]
+
+Dump the trace record. The option '-c' will output the records in comma
+separated variables (CSV). The '-r' option controls the number of records
+dumped. This can help stop the command looping for-ever.
+
+Trigger
+
+ usage: ctrig type [from name] [from id] [to name] [to id]
+
+Set a trigger. The types of triggers are :
+
+ from : trigger on a context switch from a task
+ to : trigger on a context switch to a task
+ edge : trigger on a context switch from a task to a task
+
+The from and to trigger types requires a task name or task id or both be
+provided. The edge requires a from name and/or id and a to name and/or id be
+provided.
+
+Flush
+
+ usage: cflush [-n]
+
+Flush the trace record. The option '-n' stops the capture engine be
+primed. This means an exising trigger state will not be cleared and tracing
+will continue.
+
+Status.
+
+The following is a list of outstanding issues or bugs.
+
+1) The capture engine does not scan the existing list of tasks in the kernel
+ when initialised. This means tasks that exist but are not active are not
+ seen. Not sure how to implement this one.
+
+2) The blocking read of trace records has not been completely implemented or
+ tested. This will wait until I complete the csv support for the cli for a
+ serial UI or the tcp server is implemented.
+
+3) Task control block clean up is not implemented. The control block should be
+ dumped to the trace buffer. This requires extended record formats. This can
+ be implemented using an event flag to indicate an extended record follows
+ the trace record. This would allow a task delete record to be directly
+ followed by the task information.
+
+4) Complete csv (comma separated variable) support for the CLI.
+
+5) Implement a tcp server interface.
+
+6) Complete the capture engine API documentation.
+
+7) Test the user supplied time stamp handler.
+
+8) Task name support is only for the rtems_name type. This means the only the
+ classic API tasks are currently supported. Partial support for the different
+ task names is provided how-ever this is not clean and does not support the
+ variable length task name such as found in the POSIX tasks.
diff --git a/cpukit/libmisc/capture/capture-cli.c b/cpukit/libmisc/capture/capture-cli.c
new file mode 100644
index 0000000000..98f76764f3
--- /dev/null
+++ b/cpukit/libmisc/capture/capture-cli.c
@@ -0,0 +1,1622 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Target Interface Command Line Interface. You need
+ start the RTEMS monitor.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <rtems.h>
+#include <rtems/capture-cli.h>
+#include <rtems/monitor.h>
+
+#define RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS (20)
+
+/*
+ * The user capture timestamper.
+ */
+static rtems_capture_timestamp capture_timestamp;
+
+/*
+ * Common variable to sync the load monitor task.
+ */
+static volatile int cli_load_thread_active;
+
+/*
+ * rtems_capture_cli_open
+ *
+ * DESCRIPTION:
+ *
+ * This function opens the capture engine. We need the size of the
+ * capture buffer.
+ *
+ */
+
+static const char* open_usage = "usage: copen [-i] size\n";
+
+static void
+rtems_capture_cli_open (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ uint32_t size = 0;
+ bool enable = false;
+ rtems_status_code sc;
+ int arg;
+
+ if (argc <= 1)
+ {
+ fprintf (stdout, open_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ if (argv[arg][1] == 'i')
+ enable = true;
+ else
+ fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ size = strtoul (argv[arg], 0, 0);
+
+ if (size < 100)
+ {
+ fprintf (stdout, "error: size must be greater than or equal to 100\n");
+ return;
+ }
+ }
+ }
+
+ sc = rtems_capture_open (size, capture_timestamp);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: open failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "capture engine opened.\n");
+
+ if (!enable)
+ return;
+
+ sc = rtems_capture_control (enable);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: open enable failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "capture engine enabled.\n");
+}
+
+/*
+ * rtems_capture_cli_close
+ *
+ * DESCRIPTION:
+ *
+ * This function closes the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_close (int argc __attribute__((unused)),
+ char** argv __attribute__((unused)),
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+
+ sc = rtems_capture_close ();
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: close failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "capture engine closed.\n");
+}
+
+/*
+ * rtems_capture_cli_enable
+ *
+ * DESCRIPTION:
+ *
+ * This function enables the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_enable (int argc __attribute__((unused)),
+ char** argv __attribute__((unused)),
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+
+ sc = rtems_capture_control (1);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: enable failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "capture engine enabled.\n");
+}
+
+/*
+ * rtems_capture_cli_disable
+ *
+ * DESCRIPTION:
+ *
+ * This function disables the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_disable (int argc __attribute__((unused)),
+ char** argv __attribute__((unused)),
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+
+ sc = rtems_capture_control (0);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: disable failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "capture engine disabled.\n");
+}
+
+/*
+ * rtems_capture_cli_task_list
+ *
+ * DESCRIPTION:
+ *
+ * This function lists the tasks the capture engine knows about.
+ *
+ */
+
+static void
+rtems_capture_cli_task_list (int argc __attribute__((unused)),
+ char** argv __attribute__((unused)),
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_task_priority ceiling = rtems_capture_watch_get_ceiling ();
+ rtems_task_priority floor = rtems_capture_watch_get_floor ();
+ rtems_capture_task_t* task = rtems_capture_get_task_list ();
+ uint32_t ticks;
+ uint32_t tick_offset;
+ unsigned long long total_time;
+ int count = rtems_capture_task_count ();
+
+ if (capture_timestamp)
+ capture_timestamp (&ticks, &tick_offset);
+ else
+ {
+ ticks = _Watchdog_Ticks_since_boot;
+ tick_offset = 0;
+ }
+
+ fprintf (stdout, "total %i\n", count);
+
+ while (task)
+ {
+ rtems_task_priority priority;
+ int32_t stack_used;
+ int32_t time_used;
+
+ stack_used = rtems_capture_task_stack_usage (task);
+ if (stack_used)
+ stack_used = (stack_used * 100) / stack_used;
+
+ if (stack_used > 100)
+ stack_used = 100;
+
+ total_time = (ticks * rtems_capture_task_time (task)) + tick_offset;
+
+ time_used = (rtems_capture_task_time (task) * 100) / total_time;
+
+ if (time_used > 100)
+ time_used = 100;
+
+ priority = rtems_capture_task_real_priority (task);
+
+ fprintf (stdout, " ");
+ rtems_monitor_dump_id (rtems_capture_task_id (task));
+ fprintf (stdout, " ");
+ rtems_monitor_dump_name (rtems_capture_task_name (task));
+ fprintf (stdout, " ");
+ rtems_monitor_dump_priority (rtems_capture_task_start_priority (task));
+ fprintf (stdout, " ");
+ rtems_monitor_dump_priority (rtems_capture_task_real_priority (task));
+ fprintf (stdout, " ");
+ rtems_monitor_dump_priority (rtems_capture_task_curr_priority (task));
+ fprintf (stdout, " ");
+ rtems_monitor_dump_state (rtems_capture_task_state (task));
+ fprintf (stdout, " %c%c",
+ rtems_capture_task_valid (task) ? 'a' : 'd',
+ rtems_capture_task_flags (task) & RTEMS_CAPTURE_TRACED ? 't' : '-');
+
+ if ((floor > ceiling) && (ceiling > priority))
+ fprintf (stdout, "--");
+ else
+ {
+ uint32_t flags = rtems_capture_task_control_flags (task);
+ fprintf (stdout, "%c%c",
+ rtems_capture_task_control (task) ?
+ (flags & RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-',
+ rtems_capture_watch_global_on () ? 'g' : '-');
+ }
+ fprintf (stdout, " %3" PRId32 "%% %3" PRId32 "%% (%" PRIu32 ")\n",
+ stack_used, time_used, rtems_capture_task_ticks (task));
+
+ task = rtems_capture_next_task (task);
+ }
+}
+
+/*
+ * rtems_capture_cli_task_load_thread
+ *
+ * DESCRIPTION:
+ *
+ * This function displays the load of the tasks on an ANSI terminal.
+ *
+ */
+
+static void
+rtems_capture_cli_task_load_thread (rtems_task_argument arg __attribute__((unused)))
+{
+ rtems_task_priority ceiling = rtems_capture_watch_get_ceiling ();
+ rtems_task_priority floor = rtems_capture_watch_get_floor ();
+ int last_count = 0;
+
+ for (;;)
+ {
+ rtems_capture_task_t* tasks[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1];
+ unsigned long long load[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1];
+ rtems_capture_task_t* task;
+ unsigned long long total_time;
+ int count = 0;
+ int i;
+ int j;
+
+ cli_load_thread_active = 1;
+
+ /*
+ * Iterate over the tasks and sort the highest load tasks
+ * into our local arrays. We only handle a limited number of
+ * tasks.
+ */
+
+ memset (tasks, 0, sizeof (tasks));
+ memset (load, 0, sizeof (load));
+
+ task = rtems_capture_get_task_list ();
+
+ total_time = 0;
+
+ while (task)
+ {
+ if (rtems_capture_task_valid (task))
+ {
+ unsigned long long l = rtems_capture_task_delta_time (task);
+
+ count++;
+
+ total_time += l;
+
+ for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++)
+ {
+ if (tasks[i])
+ {
+ if ((l == 0) || (l < load[i]))
+ continue;
+
+ for (j = (RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - 1); j >= i; j--)
+ {
+ tasks[j + 1] = tasks[j];
+ load[j + 1] = load[j];
+ }
+ }
+
+ tasks[i] = task;
+ load[i] = l;
+ break;
+ }
+ }
+ task = rtems_capture_next_task (task);
+ }
+
+ fprintf (stdout, "\x1b[H\x1b[J Press ENTER to exit.\n\n");
+ fprintf (stdout,
+ " PID NAME RPRI CPRI STATE %%CPU %%STK FLGS EXEC TIME\n");
+
+ if (count > last_count)
+ j = count;
+ else
+ j = last_count;
+
+ for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++)
+ {
+ rtems_task_priority priority;
+ int stack_used;
+ int task_load;
+ int k;
+
+ if (!tasks[i])
+ break;
+
+ j--;
+
+ stack_used = rtems_capture_task_stack_usage (tasks[i]);
+ if (stack_used)
+ stack_used = (stack_used * 100) / stack_used;
+
+ if (stack_used > 100)
+ stack_used = 100;
+
+ task_load = (int) ((load[i] * 100000) / total_time);
+
+ priority = rtems_capture_task_real_priority (tasks[i]);
+
+ fprintf (stdout, "\x1b[K");
+ rtems_monitor_dump_id (rtems_capture_task_id (tasks[i]));
+ fprintf (stdout, " ");
+ rtems_monitor_dump_name (rtems_capture_task_name (tasks[i]));
+ fprintf (stdout, " ");
+ rtems_monitor_dump_priority (priority);
+ fprintf (stdout, " ");
+ rtems_monitor_dump_priority (rtems_capture_task_curr_priority (tasks[i]));
+ fprintf (stdout, " ");
+ k = rtems_monitor_dump_state (rtems_capture_task_state (tasks[i]));
+ fprintf (stdout, "%*c %3i.%03i%% ", 6 - k, ' ',
+ task_load / 1000, task_load % 1000);
+ fprintf (stdout, "%3i%% %c%c", stack_used,
+ rtems_capture_task_valid (tasks[i]) ? 'a' : 'd',
+ rtems_capture_task_flags (tasks[i]) & RTEMS_CAPTURE_TRACED ? 't' : '-');
+
+ if ((floor > ceiling) && (ceiling > priority))
+ fprintf (stdout, "--");
+ else
+ fprintf (stdout, "%c%c",
+ rtems_capture_task_control (tasks[i]) ?
+ (rtems_capture_task_control_flags (tasks[i]) &
+ RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-',
+ rtems_capture_watch_global_on () ? 'g' : '-');
+
+ fprintf (stdout, " %qi\n", rtems_capture_task_time (tasks[i]));
+ }
+
+ if (count < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS)
+ {
+ j = RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - count;
+ while (j > 0)
+ {
+ fprintf (stdout, "\x1b[K\n");
+ j--;
+ }
+ }
+
+ last_count = count;
+
+ cli_load_thread_active = 0;
+
+ rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (5000000));
+ }
+}
+
+/*
+ * rtems_capture_cli_task_load
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command.
+ *
+ */
+
+static void
+rtems_capture_cli_task_load (int argc __attribute__((unused)),
+ char** argv __attribute__((unused)),
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+ rtems_task_priority priority;
+ rtems_name name;
+ rtems_id id;
+
+ sc = rtems_task_set_priority (RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &priority);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: cannot obtain the current priority: %s\n",
+ rtems_status_text (sc));
+ return;
+ }
+
+ name = rtems_build_name('C', 'P', 'l', 't');
+
+ sc = rtems_task_create (name, priority, 4 * 1024,
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
+ &id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: cannot create helper thread: %s\n",
+ rtems_status_text (sc));
+ return;
+ }
+
+ sc = rtems_task_start (id, rtems_capture_cli_task_load_thread, 0);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: cannot start helper thread: %s\n",
+ rtems_status_text (sc));
+ rtems_task_delete (id);
+ return;
+ }
+
+ for (;;)
+ {
+ int c = getchar ();
+
+ if ((c == '\r') || (c == '\n'))
+ {
+ int loops = 20;
+
+ while (loops && cli_load_thread_active)
+ rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (100000));
+
+ rtems_task_delete (id);
+
+ fprintf (stdout, "load monitoring stopped.\n");
+
+ return;
+ }
+ }
+}
+
+/*
+ * rtems_capture_cli_watch_list
+ *
+ * DESCRIPTION:
+ *
+ * This function lists the controls in the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_watch_list (int argc __attribute__((unused)),
+ char** argv __attribute__((unused)),
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_capture_control_t* control = rtems_capture_get_control_list ();
+ rtems_task_priority ceiling = rtems_capture_watch_get_ceiling ();
+ rtems_task_priority floor = rtems_capture_watch_get_floor ();
+
+ fprintf (stdout, "watch priority ceiling is %" PRId32 "\n", ceiling);
+ fprintf (stdout, "watch priority floor is %" PRId32 "\n", floor);
+ fprintf (stdout, "global watch is %s\n",
+ rtems_capture_watch_global_on () ? "enabled" : "disabled");
+ fprintf (stdout, "total %" PRId32 "\n", rtems_capture_control_count ());
+
+ while (control)
+ {
+ uint32_t flags;
+ int f;
+ int fshowed;
+ int lf;
+
+ fprintf (stdout, " ");
+ rtems_monitor_dump_id (rtems_capture_control_id (control));
+ fprintf (stdout, " ");
+ rtems_monitor_dump_name (rtems_capture_control_name (control));
+ flags = rtems_capture_control_flags (control);
+ fprintf (stdout, " %c%c ",
+ rtems_capture_watch_global_on () ? 'g' : '-',
+ flags & RTEMS_CAPTURE_WATCH ? 'w' : '-');
+ flags = rtems_capture_control_to_triggers (control);
+ fprintf (stdout, " T:%c%c%c%c%c%c%c",
+ flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-',
+ flags & RTEMS_CAPTURE_CREATE ? 'C' : '-',
+ flags & RTEMS_CAPTURE_START ? 'S' : '-',
+ flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',
+ flags & RTEMS_CAPTURE_DELETE ? 'D' : '-',
+ flags & RTEMS_CAPTURE_BEGIN ? 'B' : '-',
+ flags & RTEMS_CAPTURE_EXITTED ? 'E' : '-');
+ flags = rtems_capture_control_from_triggers (control);
+ fprintf (stdout, " F:%c%c%c%c%c",
+ flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-',
+ flags & RTEMS_CAPTURE_CREATE ? 'C' : '-',
+ flags & RTEMS_CAPTURE_START ? 'S' : '-',
+ flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',
+ flags & RTEMS_CAPTURE_DELETE ? 'D' : '-');
+
+ for (f = 0, fshowed = 0, lf = 1; f < RTEMS_CAPTURE_TRIGGER_TASKS; f++)
+ {
+ if (rtems_capture_control_by_valid (control, f))
+ {
+ if (lf && ((fshowed % 3) == 0))
+ {
+ fprintf (stdout, "\n");
+ lf = 0;
+ }
+
+ fprintf (stdout, " %2i:", f);
+ rtems_monitor_dump_name (rtems_capture_control_by_name (control, f));
+ fprintf (stdout, "/");
+ rtems_monitor_dump_id (rtems_capture_control_by_id (control, f));
+ flags = rtems_capture_control_by_triggers (control, f);
+ fprintf (stdout, ":%c%c%c%c%c",
+ flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-',
+ flags & RTEMS_CAPTURE_CREATE ? 'C' : '-',
+ flags & RTEMS_CAPTURE_START ? 'S' : '-',
+ flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',
+ flags & RTEMS_CAPTURE_DELETE ? 'D' : '-');
+ fshowed++;
+ lf = 1;
+ }
+ }
+
+ if (lf)
+ fprintf (stdout, "\n");
+
+ control = rtems_capture_next_control (control);
+ }
+}
+
+/*
+ * rtems_capture_cli_get_name_id
+ *
+ * DESCRIPTION:
+ *
+ * This function checks arguments for a name or an id.
+ *
+ */
+
+static bool
+rtems_capture_cli_get_name_id (char* arg,
+ bool* valid_name,
+ bool* valid_id,
+ rtems_name* name,
+ rtems_id* id)
+{
+ size_t l;
+ size_t i;
+
+ if (*valid_name && *valid_id)
+ {
+ fprintf (stdout, "error: too many arguments\n");
+ return 0;
+ }
+
+ /*
+ * See if the arg is all hex digits.
+ */
+
+ l = strlen (arg);
+
+ for (i = 0; i < l; i++)
+ if (!isxdigit ((unsigned char)arg[i]))
+ break;
+
+ if (i == l)
+ {
+ *id = strtoul (arg, 0, 16);
+ *valid_id = true;
+ }
+ else
+ {
+ /*
+ * This is a bit of hack but it should work on all platforms
+ * as it is what the score does with names.
+ *
+ * @warning The extra assigns play with the byte order so do not
+ * remove unless the score has been updated.
+ */
+ rtems_name rname;
+
+ rname = rtems_build_name(arg[0], arg[1], arg[2], arg[3]);
+ *name = rname;
+ *valid_name = true;
+ }
+
+ return 1;
+}
+
+/*
+ * rtems_capture_cli_watch_add
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that add a watch to the capture
+ * engine.
+ *
+ */
+
+static char const * watch_add_usage = "usage: cwadd [task name] [id]\n";
+
+static void
+rtems_capture_cli_watch_add (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ bool valid_name = false;
+ bool valid_id = false;
+
+ if (argc <= 1)
+ {
+ fprintf (stdout, watch_add_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id,
+ &name, &id))
+ return;
+ }
+ }
+
+ if (!valid_name && !valid_id)
+ {
+ fprintf (stdout, "error: no valid name or task id located\n");
+ return;
+ }
+
+ sc = rtems_capture_watch_add (name, id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout,
+ "error: watch add failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "watch added.\n");
+}
+
+/*
+ * rtems_capture_cli_watch_del
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that deletes a watch from the capture
+ * engine.
+ *
+ */
+
+static char const * watch_del_usage = "usage: cwdel [task name] [id]\n";
+
+static void
+rtems_capture_cli_watch_del (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ bool valid_name = false;
+ bool valid_id = false;
+
+ if (argc <= 1)
+ {
+ fprintf (stdout, watch_del_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id,
+ &name, &id))
+ return;
+ }
+ }
+
+ if (!valid_name && !valid_id)
+ {
+ fprintf (stdout, "error: no valid name or task id located\n");
+ return;
+ }
+
+ sc = rtems_capture_watch_del (name, id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: watch delete failed: %s\n",
+ rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "watch delete.\n");
+}
+
+/*
+ * rtems_capture_cli_watch_control
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that controls a watch.
+ *
+ */
+
+static char const * watch_control_usage = "usage: cwctl [task name] [id] on/off\n";
+
+static void
+rtems_capture_cli_watch_control (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ bool valid_name = false;
+ bool valid_id = false;
+ bool enable = false;
+
+ if (argc <= 2)
+ {
+ fprintf (stdout, watch_control_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (strcmp (argv[arg], "on") == 0)
+ enable = true;
+ else if (strcmp (argv[arg], "off") == 0)
+ enable = false;
+ else if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name,
+ &valid_id, &name, &id))
+ return;
+ }
+ }
+
+ if (!valid_name && !valid_id)
+ {
+ fprintf (stdout, "error: no valid name or task id located\n");
+ return;
+ }
+
+ sc = rtems_capture_watch_ctrl (name, id, enable);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: watch control failed: %s\n",
+ rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "watch %s.\n", enable ? "enabled" : "disabled");
+}
+
+/*
+ * rtems_capture_cli_watch_global
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets a global watch.
+ *
+ */
+
+static char const * watch_global_usage = "usage: cwglob on/off\n";
+
+static void
+rtems_capture_cli_watch_global (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+ int arg;
+ bool enable = false;
+
+ if (argc <= 1)
+ {
+ fprintf (stdout, watch_global_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (strcmp (argv[arg], "on") == 0)
+ enable = true;
+ else if (strcmp (argv[arg], "off") == 0)
+ enable = false;
+ }
+ }
+
+ sc = rtems_capture_watch_global (enable);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: global watch failed: %s\n",
+ rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "global watch %s.\n", enable ? "enabled" : "disabled");
+}
+
+/*
+ * rtems_capture_cli_watch_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets watch ceiling.
+ *
+ */
+
+static char const * watch_ceiling_usage = "usage: cwceil priority\n";
+
+static void
+rtems_capture_cli_watch_ceiling (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_task_priority priority = 0;
+
+ if (argc <= 1)
+ {
+ fprintf (stdout, watch_ceiling_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ priority = strtoul (argv[arg], 0, 0);
+ }
+ }
+
+ sc = rtems_capture_watch_ceiling (priority);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: watch ceiling failed: %s\n",
+ rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "watch ceiling is %" PRId32 ".\n", priority);
+}
+
+/*
+ * rtems_capture_cli_watch_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets watch floor.
+ *
+ */
+
+static char const * watch_floor_usage = "usage: cwfloor priority\n";
+
+static void
+rtems_capture_cli_watch_floor (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_task_priority priority = 0;
+
+ if (argc <= 1)
+ {
+ fprintf (stdout, watch_floor_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ priority = strtoul (argv[arg], 0, 0);
+ }
+ }
+
+ sc = rtems_capture_watch_floor (priority);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: watch floor failed: %s\n",
+ rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "watch floor is %" PRId32 ".\n", priority);
+}
+
+/*
+ * rtems_capture_cli_trigger_worker
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets or clears a trigger.
+ *
+ */
+
+static char const *trigger_set_usage =
+ "usage: %s [-?] type [to name/id] [from] [from name/id]\n";
+
+static char const *trigger_set_types =
+ " You can say 'type TASK' or 'type TO from FROM'\n" \
+ " where TASK is the task the event is happening to\n" \
+ " or you can say the event TO this task FROM this task.\n" \
+ " No type defaults to 'switch'.\n" \
+ " switch : context switch TASK or FROM or FROM->TO\n" \
+ " create : create TASK, or create TO from FROM\n" \
+ " start : start TASK, or start TO from FROM\n" \
+ " restart : restart TASK, or restart TO from FROM\n" \
+ " delete : delete TASK or delete TO from FROM\n" \
+ " begin : begin TASK\n" \
+ " exitted : exitted TASK\n";
+
+/*
+ * Structure to handle the parsing of the trigger command line.
+ */
+typedef struct rtems_capture_cli_triggers_s
+{
+ char const * name;
+ rtems_capture_trigger_t type;
+ int to_only;
+} rtems_capture_cli_triggers_t;
+
+static rtems_capture_cli_triggers_t rtems_capture_cli_triggers[] =
+{
+ { "switch", rtems_capture_switch, 0 }, /* must be first */
+ { "create", rtems_capture_create, 0 },
+ { "start", rtems_capture_start, 0 },
+ { "restart", rtems_capture_restart, 0 },
+ { "delete", rtems_capture_delete, 0 },
+ { "begin", rtems_capture_begin, 1 },
+ { "exitted", rtems_capture_exitted, 1 }
+};
+
+typedef enum rtems_capture_cli_trig_state_e
+{
+ trig_type,
+ trig_to,
+ trig_from_from,
+ trig_from
+} rtems_capture_cli_trig_state_t;
+
+#define RTEMS_CAPTURE_CLI_TRIGGERS_NUM \
+ (sizeof (rtems_capture_cli_triggers) / sizeof (rtems_capture_cli_triggers_t))
+
+static void
+rtems_capture_cli_trigger_worker (int set, int argc, char** argv)
+{
+ rtems_status_code sc;
+ int arg;
+ int trigger = 0; /* switch */
+ rtems_capture_trigger_mode_t trigger_mode = rtems_capture_from_any;
+ bool trigger_set = false;
+ bool is_from = false;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ bool valid_name = false;
+ bool valid_id = false;
+ rtems_name from_name = 0;
+ rtems_id from_id = 0;
+ bool from_valid_name = false;
+ bool from_valid_id = false;
+ rtems_name to_name = 0;
+ rtems_id to_id = 0;
+ bool to_valid_name = false;
+ bool to_valid_id = false;
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ switch (argv[arg][1])
+ {
+ case '?':
+ fprintf (stdout, trigger_set_usage, set ? "ctset" : "ctclear");
+ fprintf (stdout, trigger_set_types);
+ return;
+ default:
+ fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
+ break;
+ }
+ }
+ else
+ {
+ if (!trigger_set)
+ {
+ bool found = false;
+ int t;
+
+ for (t = 0; t < RTEMS_CAPTURE_CLI_TRIGGERS_NUM; t++)
+ if (strcmp (argv[arg], rtems_capture_cli_triggers[t].name) == 0)
+ {
+ trigger = t;
+ found = true;
+ break;
+ }
+
+ trigger_set = true;
+
+ /*
+ * If a trigger was not found assume the default and
+ * assume the parameter is a task name or id.
+ */
+ if (found)
+ continue;
+ }
+
+ if (strcmp (arg[argv], "from") == 0)
+ {
+ if (is_from)
+ fprintf (stdout, "warning: extra 'from' ignored\n");
+
+ is_from = 1;
+ continue;
+ }
+
+ if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id,
+ &name, &id))
+ return;
+
+ if (valid_name)
+ {
+ if (is_from)
+ {
+ if (!from_valid_name && !from_valid_id)
+ {
+ from_valid_name = true;
+ from_name = name;
+ }
+ else
+ fprintf (stdout, "warning: extra arguments ignored\n");
+ }
+ else if (!to_valid_name && !to_valid_id)
+ {
+ to_valid_name = true;
+ to_name = name;
+ }
+ else
+ fprintf (stdout, "warning: extra arguments ignored\n");
+ }
+
+ if (valid_id)
+ {
+ if (is_from)
+ {
+ if (!from_valid_name && !from_valid_id)
+ {
+ from_valid_id = true;
+ from_id = id;
+ }
+ else
+ fprintf (stdout, "warning: extra arguments ignored\n");
+ }
+ else if (!to_valid_name && !to_valid_id)
+ {
+ to_valid_id = true;
+ to_id = id;
+ }
+ else
+ fprintf (stdout, "warning: extra arguments ignored\n");
+ }
+ }
+ }
+
+ if (is_from && rtems_capture_cli_triggers[trigger].to_only)
+ {
+ fprintf (stdout, "error: a %s trigger can be a TO trigger\n",
+ rtems_capture_cli_triggers[trigger].name);
+ return;
+ }
+
+ if (!to_valid_name && !to_valid_id && !from_valid_name && !from_valid_id)
+ {
+ fprintf (stdout, trigger_set_usage);
+ return;
+ }
+
+ if (!is_from && !to_valid_name && !to_valid_id)
+ {
+ fprintf (stdout, "error: a %s trigger needs a TO name or id\n",
+ rtems_capture_cli_triggers[trigger].name);
+ return;
+ }
+
+ if (is_from && !from_valid_name && !from_valid_id)
+ {
+ fprintf (stdout, "error: a %s trigger needs a FROM name or id\n",
+ rtems_capture_cli_triggers[trigger].name);
+ return;
+ }
+
+ if ((from_valid_name || from_valid_id) && (to_valid_name || to_valid_id))
+ trigger_mode = rtems_capture_from_to;
+ else if (from_valid_name || from_valid_id)
+ trigger_mode = rtems_capture_to_any;
+ else if (to_valid_name || to_valid_id)
+ trigger_mode = rtems_capture_from_any;
+
+ if (set)
+ sc = rtems_capture_set_trigger (from_name, from_id, to_name, to_id,
+ trigger_mode,
+ rtems_capture_cli_triggers[trigger].type);
+ else
+ sc = rtems_capture_clear_trigger (from_name, from_id, to_name, to_id,
+ trigger_mode,
+ rtems_capture_cli_triggers[trigger].type);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: %sing the trigger failed: %s\n",
+ set ? "sett" : "clear", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "trigger %s.\n", set ? "set" : "cleared");
+}
+
+/*
+ * rtems_capture_cli_trigger_set
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets a trigger.
+ *
+ */
+
+static void
+rtems_capture_cli_trigger_set (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_capture_cli_trigger_worker (1, argc, argv);
+}
+
+/*
+ * rtems_capture_cli_trigger_clear
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that clears a trigger.
+ *
+ */
+
+static void
+rtems_capture_cli_trigger_clear (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_capture_cli_trigger_worker (0, argc, argv);
+}
+
+/*
+ * rtems_capture_cli_trace_records
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that dumps trace records.
+ *
+ */
+
+static void
+rtems_capture_cli_trace_records (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+ bool csv = false;
+ static int dump_total = 22;
+ int total;
+ int count;
+ uint32_t read;
+ rtems_capture_record_t* rec;
+ int arg;
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ if (argv[arg][1] == 'c')
+ csv = true;
+ else
+ fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ size_t i;
+ size_t l;
+
+ l = strlen (argv[arg]);
+
+ for (i = 0; i < l; i++)
+ if (!isdigit ((unsigned char)argv[arg][i]))
+ {
+ fprintf (stdout, "error: not a number\n");
+ return;
+ }
+
+ dump_total = strtoul (argv[arg], 0, 0);
+ }
+ }
+
+ total = dump_total;
+
+ while (total)
+ {
+ sc = rtems_capture_read (0, 0, &read, &rec);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: trace read failed: %s\n", rtems_status_text (sc));
+ rtems_capture_flush (0);
+ return;
+ }
+
+ /*
+ * If we have no records then just exist. We still need to release
+ * the reader lock.
+ */
+
+ if (read == 0)
+ {
+ rtems_capture_release (read);
+ break;
+ }
+
+ count = total < read ? total : read;
+
+ while (count--)
+ {
+ if (csv)
+ fprintf (stdout, "%08" PRIxPTR ",%03" PRIu32
+ ",%03" PRIu32 ",%04" PRIx32 ",%" PRId32 ",%" PRId32 "\n",
+ (uintptr_t) rec->task,
+ (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
+ (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff,
+ (rec->events >> RTEMS_CAPTURE_EVENT_START),
+ rec->ticks, rec->tick_offset);
+ else
+ {
+ unsigned long long t;
+ uint32_t event;
+ int e;
+
+ event = rec->events >> RTEMS_CAPTURE_EVENT_START;
+
+ t = rec->ticks;
+ t *= rtems_capture_tick_time ();
+ t += rec->tick_offset;
+
+ for (e = RTEMS_CAPTURE_EVENT_START; e < RTEMS_CAPTURE_EVENT_END; e++)
+ {
+ if (event & 1)
+ {
+ fprintf (stdout, "%9li.%06li ", (unsigned long) (t / 1000000),
+ (unsigned long) (t % 1000000));
+ rtems_monitor_dump_id (rtems_capture_task_id (rec->task));
+ fprintf (stdout, " ");
+ rtems_monitor_dump_name (rtems_capture_task_name (rec->task));
+ fprintf (stdout, " %3" PRId32 " %3" PRId32 " %s\n",
+ (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
+ (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff,
+ rtems_capture_event_text (e));
+ }
+ event >>= 1;
+ }
+ }
+ rec++;
+ }
+
+ count = total < read ? total : read;
+
+ if (count < total)
+ total -= count;
+ else
+ total = 0;
+
+ rtems_capture_release (count);
+ }
+}
+
+/*
+ * rtems_capture_cli_flush
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that flushes and primes the capture
+ * engine.
+ *
+ */
+
+static void
+rtems_capture_cli_flush (int argc,
+ char** argv,
+ const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ rtems_status_code sc;
+ bool prime = true;
+ int arg;
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ if (argv[arg][1] == 'n')
+ prime = false;
+ else
+ fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
+ }
+ }
+
+ sc = rtems_capture_flush (prime);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf (stdout, "error: flush failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf (stdout, "trace buffer flushed and %s.\n",
+ prime ? "primed" : "not primed");
+}
+
+static rtems_monitor_command_entry_t rtems_capture_cli_cmds[] =
+{
+ {
+ "copen",
+ "usage: copen [-i] size\n",
+ 0,
+ rtems_capture_cli_open,
+ { 0 },
+ 0
+ },
+ {
+ "cclose",
+ "usage: cclose\n",
+ 0,
+ rtems_capture_cli_close,
+ { 0 },
+ 0
+ },
+ {
+ "cenable",
+ "usage: cenable\n",
+ 0,
+ rtems_capture_cli_enable,
+ { 0 },
+ 0
+ },
+ {
+ "cdisable",
+ "usage: cdisable\n",
+ 0,
+ rtems_capture_cli_disable,
+ { 0 },
+ 0
+ },
+ {
+ "ctlist",
+ "usage: ctlist \n",
+ 0,
+ rtems_capture_cli_task_list,
+ { 0 },
+ 0
+ },
+ {
+ "ctload",
+ "usage: ctload \n",
+ 0,
+ rtems_capture_cli_task_load,
+ { 0 },
+ 0
+ },
+ {
+ "cwlist",
+ "usage: cwlist\n",
+ 0,
+ rtems_capture_cli_watch_list,
+ { 0 },
+ 0
+ },
+ {
+ "cwadd",
+ "usage: cwadd [task name] [id]\n",
+ 0,
+ rtems_capture_cli_watch_add,
+ { 0 },
+ 0
+ },
+ {
+ "cwdel",
+ "usage: cwdel [task name] [id]\n",
+ 0,
+ rtems_capture_cli_watch_del,
+ { 0 },
+ 0
+ },
+ {
+ "cwctl",
+ "usage: cwctl [task name] [id] on/off\n",
+ 0,
+ rtems_capture_cli_watch_control,
+ { 0 },
+ 0
+ },
+ {
+ "cwglob",
+ "usage: cwglob on/off\n",
+ 0,
+ rtems_capture_cli_watch_global,
+ { 0 },
+ 0
+ },
+ {
+ "cwceil",
+ "usage: cwceil priority\n",
+ 0,
+ rtems_capture_cli_watch_ceiling,
+ { 0 },
+ 0
+ },
+ {
+ "cwfloor",
+ "usage: cwfloor priority\n",
+ 0,
+ rtems_capture_cli_watch_floor,
+ { 0 },
+ 0
+ },
+ {
+ "ctrace",
+ "usage: ctrace [-c] [-r records]\n",
+ 0,
+ rtems_capture_cli_trace_records,
+ { 0 },
+ 0
+ },
+ {
+ "ctset",
+ "usage: ctset -h\n",
+ 0,
+ rtems_capture_cli_trigger_set,
+ { 0 },
+ 0
+ },
+ {
+ "ctclear",
+ "usage: ctclear -?\n",
+ 0,
+ rtems_capture_cli_trigger_clear,
+ { 0 },
+ 0
+ },
+ {
+ "cflush",
+ "usage: cflush [-n]\n",
+ 0,
+ rtems_capture_cli_flush,
+ { 0 },
+ 0
+ }
+};
+
+/*
+ * rtems_capture_cli_init
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the command line interface to the capture
+ * engine.
+ *
+ */
+
+rtems_status_code
+rtems_capture_cli_init (rtems_capture_timestamp timestamp)
+{
+ size_t cmd;
+
+ capture_timestamp = timestamp;
+
+ for (cmd = 0;
+ cmd < sizeof (rtems_capture_cli_cmds) / sizeof (rtems_monitor_command_entry_t);
+ cmd++)
+ rtems_monitor_insert_cmd (&rtems_capture_cli_cmds[cmd]);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/capture/capture-cli.h b/cpukit/libmisc/capture/capture-cli.h
new file mode 100644
index 0000000000..99c4e2252c
--- /dev/null
+++ b/cpukit/libmisc/capture/capture-cli.h
@@ -0,0 +1,56 @@
+/**
+ * @file rtems/capture-cli.h
+ */
+
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Target Interface Command Line Interface. You need
+ start the RTEMS monitor.
+
+*/
+
+#ifndef __CAPTURE_CLI_H_
+#define __CAPTURE_CLI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/capture.h>
+
+/**
+ * rtems_capture_cli_init
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the command line interface to the capture
+ * engine.
+ *
+ */
+rtems_status_code
+rtems_capture_cli_init (rtems_capture_timestamp timestamp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/capture/capture.c b/cpukit/libmisc/capture/capture.c
new file mode 100644
index 0000000000..ac1acc01ac
--- /dev/null
+++ b/cpukit/libmisc/capture/capture.c
@@ -0,0 +1,1938 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ 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.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Capture Engine component.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "capture.h"
+#include <rtems/score/states.inl>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/wkspace.inl>
+
+/*
+ * These events are always recorded and are not part of the
+ * watch filters.
+ *
+ * This feature has been disabled as it becomes confusing when
+ * setting up filters and some event leak.
+ */
+#if defined (RTEMS_CAPTURE_ENGINE_ALLOW_RELATED_EVENTS)
+#define RTEMS_CAPTURE_RECORD_EVENTS (RTEMS_CAPTURE_CREATED_BY_EVENT | \
+ RTEMS_CAPTURE_CREATED_EVENT | \
+ RTEMS_CAPTURE_STARTED_BY_EVENT | \
+ RTEMS_CAPTURE_STARTED_EVENT | \
+ RTEMS_CAPTURE_RESTARTED_BY_EVENT | \
+ RTEMS_CAPTURE_RESTARTED_EVENT | \
+ RTEMS_CAPTURE_DELETED_BY_EVENT | \
+ RTEMS_CAPTURE_DELETED_EVENT | \
+ RTEMS_CAPTURE_BEGIN_EVENT | \
+ RTEMS_CAPTURE_EXITTED_EVENT)
+#else
+#define RTEMS_CAPTURE_RECORD_EVENTS (0)
+#endif
+
+/*
+ * Global capture flags.
+ */
+#define RTEMS_CAPTURE_ON (1 << 0)
+#define RTEMS_CAPTURE_NO_MEMORY (1 << 1)
+#define RTEMS_CAPTURE_OVERFLOW (1 << 2)
+#define RTEMS_CAPTURE_TRIGGERED (1 << 3)
+#define RTEMS_CAPTURE_READER_ACTIVE (1 << 4)
+#define RTEMS_CAPTURE_READER_WAITING (1 << 5)
+#define RTEMS_CAPTURE_GLOBAL_WATCH (1 << 6)
+#define RTEMS_CAPTURE_ONLY_MONITOR (1 << 7)
+
+/*
+ * RTEMS Capture Data.
+ */
+static rtems_capture_record_t* capture_records;
+static uint32_t capture_size;
+static uint32_t capture_count;
+static rtems_capture_record_t* capture_in;
+static uint32_t capture_out;
+static uint32_t capture_flags;
+static rtems_capture_task_t* capture_tasks;
+static rtems_capture_control_t* capture_controls;
+static int capture_extension_index;
+static rtems_id capture_id;
+static rtems_capture_timestamp capture_timestamp;
+static rtems_task_priority capture_ceiling;
+static rtems_task_priority capture_floor;
+static uint32_t capture_tick_period;
+static rtems_id capture_reader;
+
+/*
+ * RTEMS Event text.
+ */
+static const char* capture_event_text[] =
+{
+ "CREATED_BY",
+ "CREATED",
+ "STARTED_BY",
+ "STARTED",
+ "RESTARTED_BY",
+ "RESTARTED",
+ "DELETED_BY",
+ "DELETED",
+ "BEGIN",
+ "EXITTED",
+ "SWITCHED_OUT",
+ "SWITCHED_IN",
+ "TIMESTAMP"
+};
+
+/*
+ * rtems_capture_get_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current time. If a handler is provided
+ * by the user get the time from that.
+ */
+static inline void rtems_capture_get_time (uint32_t* ticks,
+ uint32_t* tick_offset)
+{
+ if (capture_timestamp)
+ capture_timestamp (ticks, tick_offset);
+ else
+ {
+ *ticks = _Watchdog_Ticks_since_boot;
+ *tick_offset = 0;
+ }
+}
+
+/*
+ * rtems_capture_match_names
+ *
+ * DESCRIPTION:
+ *
+ * This function compares rtems_names. It protects the
+ * capture engine from a change to the way names are supported
+ * in RTEMS.
+ *
+ */
+static inline bool
+rtems_capture_match_names (rtems_name lhs, rtems_name rhs)
+{
+ return lhs == rhs;
+}
+
+/*
+ * rtems_capture_match_id
+ *
+ * DESCRIPTION:
+ *
+ * This function compares rtems_ids. It protects the
+ * capture engine from a change to the way id are supported
+ * in RTEMS.
+ *
+ */
+static inline bool
+rtems_capture_match_ids (rtems_id lhs, rtems_id rhs)
+{
+ return lhs == rhs;
+}
+
+/*
+ * rtems_capture_match_name_id
+ *
+ * DESCRIPTION:
+ *
+ * This function matches a name and/or id.
+ */
+static inline bool
+rtems_capture_match_name_id (rtems_name lhs_name,
+ rtems_id lhs_id,
+ rtems_name rhs_name,
+ rtems_id rhs_id)
+{
+ /*
+ * The left hand side name or id could be 0 which means a wildcard.
+ */
+ if ((lhs_name == 0) && (lhs_id == rhs_id))
+ return 1;
+ else if ((lhs_id == 0) || (lhs_id == rhs_id))
+ {
+ if (rtems_capture_match_names (lhs_name, rhs_name))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * rtems_capture_dup_name
+ *
+ * DESCRIPTION:
+ *
+ * This function duplicates an rtems_names. It protects the
+ * capture engine from a change to the way names are supported
+ * in RTEMS.
+ *
+ */
+static inline void
+rtems_capture_dup_name (rtems_name* dst, rtems_name src)
+{
+ *dst = src;
+}
+
+/*
+ * rtems_capture_by_in_to
+ *
+ * DESCRIPTION:
+ *
+ * This function sees if a BY control is in the BY names. The use
+ * of the valid_mask in this way assumes the number of trigger
+ * tasks is the number of bits in uint32_t.
+ *
+ */
+static inline bool
+rtems_capture_by_in_to (uint32_t events,
+ rtems_capture_task_t* by,
+ rtems_capture_control_t* to)
+{
+ uint32_t valid_mask = RTEMS_CAPTURE_CONTROL_FROM_MASK (0);
+ uint32_t valid_remainder = 0xffffffff;
+ int i;
+
+ for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
+ {
+ /*
+ * If there are no more valid BY entries then
+ * we are finished.
+ */
+ if ((valid_remainder & to->by_valid) == 0)
+ break;
+
+ /*
+ * Is the froby entry valid and does its name or id match.
+ */
+ if ((valid_mask & to->by_valid) &&
+ (to->by[i].trigger & events))
+ {
+ /*
+ * We have the BY task on the right hand side so we
+ * match with id's first then labels if the id's are
+ * not set.
+ */
+ if (rtems_capture_match_name_id (to->by[i].name, to->by[i].id,
+ by->name, by->id))
+ return 1;
+ }
+
+ valid_mask >>= 1;
+ valid_remainder >>= 1;
+ }
+
+ return 0;
+}
+
+/*
+ * rtems_capture_refcount_up
+ *
+ * DESCRIPTION:
+ *
+ * This function raises the reference count.
+ *
+ */
+static inline void
+rtems_capture_refcount_up (rtems_capture_task_t* task)
+{
+ task->refcount++;
+}
+
+/*
+ * rtems_capture_refcount_down
+ *
+ * DESCRIPTION:
+ *
+ * This function lowers the reference count and if the count
+ * reaches 0 the task control block is returned to the heap.
+ *
+ */
+static inline void
+rtems_capture_refcount_down (rtems_capture_task_t* task)
+{
+ if (task->refcount)
+ task->refcount--;
+}
+
+/*
+ * rtems_capture_init_stack_usage
+ *
+ * DESCRIPTION:
+ *
+ * This function setups a stack so its usage can be monitored.
+ */
+static inline void
+rtems_capture_init_stack_usage (rtems_capture_task_t* task)
+{
+ if (task->tcb)
+ {
+ uint32_t* s;
+ uint32_t i;
+
+ task->stack_size = task->tcb->Start.Initial_stack.size;
+ task->stack_clean = task->stack_size;
+
+ s = task->tcb->Start.Initial_stack.area;
+
+ for (i = 0; i < (task->stack_size - 128); i += 4)
+ *(s++) = 0xdeaddead;
+ }
+}
+
+/*
+ * rtems_capture_find_control
+ *
+ * DESCRIPTION:
+ *
+ * This function searches for a trigger given a name.
+ *
+ */
+static inline rtems_capture_control_t*
+rtems_capture_find_control (rtems_name name, rtems_id id)
+{
+ rtems_capture_control_t* control;
+
+ for (control = capture_controls; control != NULL; control = control->next)
+ if (rtems_capture_match_name_id (name, id, control->name, control->id))
+ break;
+ return control;
+}
+
+/*
+ * rtems_capture_create_control
+ *
+ * DESCRIPTION:
+ *
+ * This function creates a capture control for the capture engine.
+ *
+ */
+static inline rtems_capture_control_t*
+rtems_capture_create_control (rtems_name name, rtems_id id)
+{
+ rtems_interrupt_level level;
+ rtems_capture_control_t* control;
+ rtems_capture_task_t* task;
+
+ if ((name == 0) && (id == 0))
+ return NULL;
+
+ control = rtems_capture_find_control (name, id);
+
+ if (control == NULL)
+ {
+ control = _Workspace_Allocate (sizeof (rtems_capture_control_t));
+
+ if (control == NULL)
+ {
+ capture_flags |= RTEMS_CAPTURE_NO_MEMORY;
+ return NULL;
+ }
+
+ control->name = name;
+ control->id = id;
+ control->flags = 0;
+ control->to_triggers = 0;
+ control->from_triggers = 0;
+ control->by_valid = 0;
+
+ memset (control->by, 0, sizeof (control->by));
+
+ rtems_interrupt_disable (level);
+
+ control->next = capture_controls;
+ capture_controls = control;
+
+ /*
+ * We need to scan the task list as set the control to the
+ * tasks.
+ */
+ for (task = capture_tasks; task != NULL; task = task->forw)
+ if (rtems_capture_match_name_id (name, id, task->name, task->id))
+ task->control = control;
+
+ rtems_interrupt_enable (level);
+ }
+
+ return control;
+}
+
+/*
+ * rtems_capture_create_capture_task
+ *
+ * DESCRIPTION:
+ *
+ * This function create the task control.
+ *
+ */
+static inline rtems_capture_task_t*
+rtems_capture_create_capture_task (rtems_tcb* new_task)
+{
+ rtems_interrupt_level level;
+ rtems_capture_task_t* task;
+ rtems_capture_control_t* control;
+ rtems_name name;
+
+ task = _Workspace_Allocate (sizeof (rtems_capture_task_t));
+
+ if (task == NULL)
+ {
+ capture_flags |= RTEMS_CAPTURE_NO_MEMORY;
+ return NULL;
+ }
+
+ /*
+ * Check the type of name the object has.
+ */
+
+ rtems_object_get_classic_name( new_task->Object.id, &name );
+
+ rtems_capture_dup_name (&task->name, name);
+
+ task->id = new_task->Object.id;
+ task->flags = 0;
+ task->in = 0;
+ task->refcount = 0;
+ task->out = 0;
+ task->tcb = new_task;
+ task->ticks = 0;
+ task->tick_offset = 0;
+ task->ticks_in = 0;
+ task->tick_offset_in = 0;
+ task->control = 0;
+ task->last_ticks = 0;
+ task->last_tick_offset = 0;
+
+ task->tcb->extensions[capture_extension_index] = task;
+
+ task->start_priority = new_task->Start.initial_priority;
+ task->stack_size = new_task->Start.Initial_stack.size;
+ task->stack_clean = task->stack_size;
+
+ rtems_interrupt_disable (level);
+
+ task->forw = capture_tasks;
+ if (task->forw)
+ task->forw->back = task;
+ task->back = NULL;
+ capture_tasks = task;
+
+ rtems_interrupt_enable (level);
+
+ /*
+ * We need to scan the default control list to initialise
+ * this control.
+ */
+
+ for (control = capture_controls; control != NULL; control = control->next)
+ if (rtems_capture_match_name_id (control->name, control->id,
+ task->name, task->id))
+ task->control = control;
+
+ return task;
+}
+
+/*
+ * rtems_capture_destroy_capture_task
+ *
+ * DESCRIPTION:
+ *
+ * This function destroy the task structure if the reference count
+ * is 0 and the tcb has been cleared signalling the task has been
+ * deleted.
+ *
+ */
+static inline void
+rtems_capture_destroy_capture_task (rtems_capture_task_t* task)
+{
+ if (task)
+ {
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (task->tcb || task->refcount)
+ task = 0;
+
+ if (task)
+ {
+ if (task->forw)
+ task->forw->back = task->back;
+ if (task->back)
+ task->back->forw = task->forw;
+ else
+ capture_tasks = task->forw;
+ }
+
+ rtems_interrupt_enable (level);
+
+ _Workspace_Free (task);
+ }
+}
+
+/*
+ * rtems_capture_record
+ *
+ * DESCRIPTION:
+ *
+ * This function records a capture record into the capture buffer.
+ *
+ */
+static inline void
+rtems_capture_record (rtems_capture_task_t* task,
+ uint32_t events)
+{
+ /*
+ * Check the watch state if we have a task control, and
+ * the task's real priority is lower or equal to the ceiling.
+ */
+ if (task &&
+ ((capture_flags &
+ (RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_ONLY_MONITOR)) ==
+ RTEMS_CAPTURE_TRIGGERED))
+ {
+ rtems_capture_control_t* control;
+
+ control = task->control;
+
+ /*
+ * Capure the record if we have an event that is always
+ * captured, or the task's real priority is greater than the
+ * watch ceiling, and the global watch or task watch is enabled.
+ */
+
+ if ((events & RTEMS_CAPTURE_RECORD_EVENTS) ||
+ ((task->tcb->real_priority >= capture_ceiling) &&
+ (task->tcb->real_priority <= capture_floor) &&
+ ((capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH) ||
+ (control && (control->flags & RTEMS_CAPTURE_WATCH)))))
+ {
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (capture_count < capture_size)
+ {
+ capture_count++;
+ capture_in->task = task;
+ capture_in->events = (events |
+ (task->tcb->real_priority) |
+ (task->tcb->current_priority << 8));
+
+ if ((events & RTEMS_CAPTURE_RECORD_EVENTS) == 0)
+ task->flags |= RTEMS_CAPTURE_TRACED;
+
+ rtems_capture_get_time (&capture_in->ticks, &capture_in->tick_offset);
+
+ if (capture_in == &capture_records[capture_size - 1])
+ capture_in = capture_records;
+ else
+ capture_in++;
+
+ rtems_capture_refcount_up (task);
+ }
+ else
+ capture_flags |= RTEMS_CAPTURE_OVERFLOW;
+ rtems_interrupt_enable (level);
+ }
+ }
+}
+
+/*
+ * rtems_capture_trigger
+ *
+ * DESCRIPTION:
+ *
+ * See if we have triggered and if not see if this event is a
+ * cause of a trigger.
+ */
+bool
+rtems_capture_trigger (rtems_capture_task_t* ft,
+ rtems_capture_task_t* tt,
+ uint32_t events)
+{
+ /*
+ * If we have not triggered then see if this is a trigger condition.
+ */
+ if (!(capture_flags & RTEMS_CAPTURE_TRIGGERED))
+ {
+ rtems_capture_control_t* fc = NULL;
+ rtems_capture_control_t* tc = NULL;
+ uint32_t from_events = 0;
+ uint32_t to_events = 0;
+ uint32_t from_to_events = 0;
+
+ if (ft)
+ {
+ fc = ft->control;
+ if (fc)
+ from_events = fc->from_triggers & events;
+ }
+
+ if (tt)
+ {
+ tc = tt->control;
+ if (tc)
+ {
+ to_events = tc->to_triggers & events;
+ if (ft && tc->by_valid)
+ from_to_events = tc->by_triggers & events;
+ }
+ }
+
+ /*
+ * Check if we have any from or to events. These are the
+ * from any or to any type triggers. All from/to triggers are
+ * listed in the to's control with the from in the from list.
+ *
+ * The masking above means any flag set is a trigger.
+ */
+ if (from_events || to_events)
+ {
+ capture_flags |= RTEMS_CAPTURE_TRIGGERED;
+ return 1;
+ }
+
+ /*
+ * Check the from->to events.
+ */
+ if (from_to_events)
+ {
+ if (rtems_capture_by_in_to (events, ft, tc))
+ {
+ capture_flags |= RTEMS_CAPTURE_TRIGGERED;
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * rtems_capture_create_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is created.
+ *
+ */
+static bool
+rtems_capture_create_task (rtems_tcb* current_task,
+ rtems_tcb* new_task)
+{
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* nt;
+
+ ct = current_task->extensions[capture_extension_index];
+
+ /*
+ * The task pointers may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ /*
+ * Create the new task's capture control block.
+ */
+ nt = rtems_capture_create_capture_task (new_task);
+
+ if (rtems_capture_trigger (ct, nt, RTEMS_CAPTURE_CREATE))
+ {
+ rtems_capture_record (ct, RTEMS_CAPTURE_CREATED_BY_EVENT);
+ rtems_capture_record (nt, RTEMS_CAPTURE_CREATED_EVENT);
+ }
+
+ return 1 == 1;
+}
+
+/*
+ * rtems_capture_start_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is started.
+ *
+ */
+static void
+rtems_capture_start_task (rtems_tcb* current_task,
+ rtems_tcb* started_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* st;
+
+ ct = current_task->extensions[capture_extension_index];
+ st = started_task->extensions[capture_extension_index];
+
+ /*
+ * The task pointers may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ if (st == NULL)
+ st = rtems_capture_create_capture_task (started_task);
+
+ if (rtems_capture_trigger (ct, st, RTEMS_CAPTURE_START))
+ {
+ rtems_capture_record (ct, RTEMS_CAPTURE_STARTED_BY_EVENT);
+ rtems_capture_record (st, RTEMS_CAPTURE_STARTED_EVENT);
+ }
+
+ rtems_capture_init_stack_usage (st);
+}
+
+/*
+ * rtems_capture_restart_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is restarted.
+ *
+ */
+static void
+rtems_capture_restart_task (rtems_tcb* current_task,
+ rtems_tcb* restarted_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* rt;
+
+ ct = current_task->extensions[capture_extension_index];
+ rt = restarted_task->extensions[capture_extension_index];
+
+ /*
+ * The task pointers may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ if (rt == NULL)
+ rt = rtems_capture_create_capture_task (restarted_task);
+
+ if (rtems_capture_trigger (ct, rt, RTEMS_CAPTURE_RESTART))
+ {
+ rtems_capture_record (ct, RTEMS_CAPTURE_RESTARTED_BY_EVENT);
+ rtems_capture_record (rt, RTEMS_CAPTURE_RESTARTED_EVENT);
+ }
+
+ rtems_capture_task_stack_usage (rt);
+ rtems_capture_init_stack_usage (rt);
+}
+
+/*
+ * rtems_capture_delete_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is deleted.
+ *
+ */
+static void
+rtems_capture_delete_task (rtems_tcb* current_task,
+ rtems_tcb* deleted_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* dt;
+
+ /*
+ * The task pointers may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ ct = current_task->extensions[capture_extension_index];
+ dt = deleted_task->extensions[capture_extension_index];
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ if (dt == NULL)
+ dt = rtems_capture_create_capture_task (deleted_task);
+
+ if (rtems_capture_trigger (ct, dt, RTEMS_CAPTURE_DELETE))
+ {
+ rtems_capture_record (ct, RTEMS_CAPTURE_DELETED_BY_EVENT);
+ rtems_capture_record (dt, RTEMS_CAPTURE_DELETED_EVENT);
+ }
+
+ rtems_capture_task_stack_usage (dt);
+
+ /*
+ * This task's tcb will be invalid. This signals the
+ * task has been deleted.
+ */
+ dt->tcb = 0;
+
+ rtems_capture_destroy_capture_task (dt);
+}
+
+/*
+ * rtems_capture_begin_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is begun.
+ *
+ */
+static void
+rtems_capture_begin_task (rtems_tcb* begin_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* bt;
+
+ bt = begin_task->extensions[capture_extension_index];
+
+ /*
+ * The task pointers may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (bt == NULL)
+ bt = rtems_capture_create_capture_task (begin_task);
+
+ if (rtems_capture_trigger (NULL, bt, RTEMS_CAPTURE_BEGIN))
+ rtems_capture_record (bt, RTEMS_CAPTURE_BEGIN_EVENT);
+}
+
+/*
+ * rtems_capture_exitted_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is exitted. That is
+ * returned rather than was deleted.
+ *
+ */
+static void
+rtems_capture_exitted_task (rtems_tcb* exitted_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* et;
+
+ et = exitted_task->extensions[capture_extension_index];
+
+ /*
+ * The task pointers may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (et == NULL)
+ et = rtems_capture_create_capture_task (exitted_task);
+
+ if (rtems_capture_trigger (NULL, et, RTEMS_CAPTURE_EXITTED))
+ rtems_capture_record (et, RTEMS_CAPTURE_EXITTED_EVENT);
+
+ rtems_capture_task_stack_usage (et);
+}
+
+/*
+ * rtems_capture_switch_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a context is switched.
+ *
+ */
+static void
+rtems_capture_switch_task (rtems_tcb* current_task,
+ rtems_tcb* heir_task)
+{
+ /*
+ * Only perform context switch trace processing if tracing is
+ * enabled.
+ */
+ if (capture_flags & RTEMS_CAPTURE_ON)
+ {
+ uint32_t ticks;
+ uint32_t tick_offset;
+
+ /*
+ * Get the cpature task control block so we can update the
+ * reference and perform any watch or trigger functions.
+ * The task pointers may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* ht;
+
+
+ if (_States_Is_transient (current_task->current_state)
+ || _States_Is_dormant (current_task->current_state))
+ {
+ rtems_id ct_id = current_task->Object.id;
+
+ for (ct = capture_tasks; ct; ct = ct->forw)
+ if (ct->id == ct_id)
+ break;
+ }
+ else
+ {
+ ct = current_task->extensions[capture_extension_index];
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+ }
+
+ ht = heir_task->extensions[capture_extension_index];
+
+ if (ht == NULL)
+ ht = rtems_capture_create_capture_task (heir_task);
+
+ /*
+ * Update the execution time. Assume the tick will not overflow
+ * for now. This may need to change.
+ */
+ rtems_capture_get_time (&ticks, &tick_offset);
+
+ /*
+ * We could end up with null pointers for both the current task
+ * and the heir task.
+ */
+
+ if (ht)
+ {
+ ht->in++;
+ ht->ticks_in = ticks;
+ ht->tick_offset_in = tick_offset;
+ }
+
+ if (ct)
+ {
+ ct->out++;
+ ct->ticks += ticks - ct->ticks_in;
+
+ if (capture_timestamp)
+ {
+ tick_offset += capture_tick_period - ct->tick_offset_in;
+
+ if (tick_offset < capture_tick_period)
+ ct->tick_offset = tick_offset;
+ else
+ {
+ ct->ticks++;
+ ct->tick_offset = tick_offset - capture_tick_period;
+ }
+ }
+ else
+ {
+ ct->tick_offset += 100;
+ }
+ }
+
+ if (rtems_capture_trigger (ct, ht, RTEMS_CAPTURE_SWITCH))
+ {
+ rtems_capture_record (ct, RTEMS_CAPTURE_SWITCHED_OUT_EVENT);
+ rtems_capture_record (ht, RTEMS_CAPTURE_SWITCHED_IN_EVENT);
+ }
+ }
+}
+
+/*
+ * rtems_capture_open
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the realtime capture engine allocating the trace
+ * buffer. It is assumed we have a working heap at stage of initialisation.
+ *
+ */
+rtems_status_code
+rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp __attribute__((unused)))
+{
+ rtems_extensions_table capture_extensions;
+ rtems_name name;
+ rtems_status_code sc;
+
+ /*
+ * See if the capture engine is already open.
+ */
+
+ if (capture_records)
+ return RTEMS_RESOURCE_IN_USE;
+
+ capture_records = malloc (size * sizeof (rtems_capture_record_t));
+
+ if (capture_records == NULL)
+ return RTEMS_NO_MEMORY;
+
+ capture_size = size;
+ capture_count = 0;
+ capture_in = capture_records;
+ capture_out = 0;
+ capture_flags = 0;
+ capture_tasks = NULL;
+ capture_ceiling = 0;
+ capture_floor = 255;
+
+ /*
+ * Create the extension table. This is copied so we
+ * can create it as a local.
+ */
+ capture_extensions.thread_create = rtems_capture_create_task;
+ capture_extensions.thread_start = rtems_capture_start_task;
+ capture_extensions.thread_restart = rtems_capture_restart_task;
+ capture_extensions.thread_delete = rtems_capture_delete_task;
+ capture_extensions.thread_switch = rtems_capture_switch_task;
+ capture_extensions.thread_begin = rtems_capture_begin_task;
+ capture_extensions.thread_exitted = rtems_capture_exitted_task;
+ capture_extensions.fatal = NULL;
+
+ /*
+ * Get the tick period from the BSP Configuration Table.
+ */
+ capture_tick_period = Configuration.microseconds_per_tick;
+
+ /*
+ * Register the user extension handlers for the CAPture Engine.
+ */
+ name = rtems_build_name ('C', 'A', 'P', 'E');
+ sc = rtems_extension_create (name, &capture_extensions, &capture_id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ capture_id = 0;
+ free (capture_records);
+ capture_records = NULL;
+ }
+ else
+ {
+ capture_extension_index = rtems_object_id_get_index (capture_id);;
+ }
+
+ /*
+ * Iterate over the list of existing tasks.
+ */
+
+ return sc;
+}
+
+/*
+ * rtems_capture_close
+ *
+ * DESCRIPTION:
+ *
+ * This function shutdowns the capture engine and release any claimed
+ * resources.
+ */
+rtems_status_code
+rtems_capture_close (void)
+{
+ rtems_interrupt_level level;
+ rtems_capture_task_t* task;
+ rtems_capture_control_t* control;
+ rtems_capture_record_t* records;
+ rtems_status_code sc;
+
+ rtems_interrupt_disable (level);
+
+ if (!capture_records)
+ {
+ rtems_interrupt_enable (level);
+ return RTEMS_SUCCESSFUL;
+ }
+
+ capture_flags &= ~(RTEMS_CAPTURE_ON | RTEMS_CAPTURE_ONLY_MONITOR);
+
+ records = capture_records;
+ capture_records = NULL;
+
+ rtems_interrupt_enable (level);
+
+ /*
+ * Delete the extension first. This means we are now able to
+ * release the resources we have without them being used.
+ */
+
+ sc = rtems_extension_delete (capture_id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+
+ task = capture_tasks;
+
+ while (task)
+ {
+ rtems_capture_task_t* delete = task;
+ task = task->forw;
+ _Workspace_Free (delete);
+ }
+
+ capture_tasks = NULL;
+
+ control = capture_controls;
+
+ while (control)
+ {
+ rtems_capture_control_t* delete = control;
+ control = control->next;
+ _Workspace_Free (delete);
+ }
+
+ capture_controls = NULL;
+
+ if (capture_records)
+ {
+ free (capture_records);
+ capture_records = NULL;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_control
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of tracing at a global level.
+ */
+rtems_status_code
+rtems_capture_control (bool enable)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (!capture_records)
+ {
+ rtems_interrupt_enable (level);
+ return RTEMS_UNSATISFIED;
+ }
+
+ if (enable)
+ capture_flags |= RTEMS_CAPTURE_ON;
+ else
+ capture_flags &= ~RTEMS_CAPTURE_ON;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_monitor
+ *
+ * DESCRIPTION:
+ *
+ * This function enable the monitor mode. When in the monitor mode
+ * the tasks are monitored but no data is saved. This can be used
+ * to profile the load on a system.
+ */
+rtems_status_code
+rtems_capture_monitor (bool enable)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (!capture_records)
+ {
+ rtems_interrupt_enable (level);
+ return RTEMS_UNSATISFIED;
+ }
+
+ if (enable)
+ capture_flags |= RTEMS_CAPTURE_ONLY_MONITOR;
+ else
+ capture_flags &= ~RTEMS_CAPTURE_ONLY_MONITOR;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_flush
+ *
+ * DESCRIPTION:
+ *
+ * This function flushes the capture buffer. The prime parameter allows the
+ * capture engine to also be primed again.
+ */
+rtems_status_code
+rtems_capture_flush (bool prime)
+{
+ rtems_interrupt_level level;
+ rtems_capture_task_t* task;
+
+ rtems_interrupt_disable (level);
+
+ for (task = capture_tasks; task != NULL; task = task->forw)
+ {
+ task->flags &= ~RTEMS_CAPTURE_TRACED;
+ task->refcount = 0;
+ }
+
+ if (prime)
+ capture_flags &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW);
+ else
+ capture_flags &= ~RTEMS_CAPTURE_OVERFLOW;
+
+ capture_count = 0;
+ capture_in = capture_records;
+ capture_out = 0;
+
+ rtems_interrupt_enable (level);
+
+ task = capture_tasks;
+
+ while (task)
+ {
+ rtems_capture_task_t* check = task;
+ task = task->forw;
+ rtems_capture_destroy_capture_task (check);
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_add
+ *
+ * DESCRIPTION:
+ *
+ * This function defines a watch for a specific task given a name. A watch
+ * causes it to be traced either in or out of context. The watch can be
+ * optionally enabled or disabled with the set routine. It is disabled by
+ * default.
+ */
+rtems_status_code
+rtems_capture_watch_add (rtems_name name, rtems_id id)
+{
+ rtems_capture_control_t* control;
+
+ if ((name == 0) && (id == 0))
+ return RTEMS_UNSATISFIED;
+
+ control = rtems_capture_find_control (name, id);
+
+ if (control && !id)
+ return RTEMS_TOO_MANY;
+
+ if (!control)
+ control = rtems_capture_create_control (name, id);
+
+ if (!control)
+ return RTEMS_NO_MEMORY;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_del
+ *
+ * DESCRIPTION:
+ *
+ * This function removes a watch for a specific task given a name. The task
+ * description will still exist if referenced by a trace record in the trace
+ * buffer or a global watch is defined.
+ */
+rtems_status_code
+rtems_capture_watch_del (rtems_name name, rtems_id id)
+{
+ rtems_interrupt_level level;
+ rtems_capture_control_t* control;
+ rtems_capture_control_t** prev_control;
+ rtems_capture_task_t* task;
+ bool found = false;
+
+ /*
+ * Should this test be for wildcards ?
+ */
+
+ for (prev_control = &capture_controls, control = capture_controls;
+ control != NULL; )
+ {
+ if (rtems_capture_match_name_id (control->name, control->id, name, id))
+ {
+ rtems_interrupt_disable (level);
+
+ for (task = capture_tasks; task != NULL; task = task->forw)
+ if (task->control == control)
+ task->control = 0;
+
+ *prev_control = control->next;
+
+ rtems_interrupt_enable (level);
+
+ _Workspace_Free (control);
+
+ control = *prev_control;
+
+ found = true;
+ }
+ else
+ {
+ prev_control = &control->next;
+ control = control->next;
+ }
+ }
+
+ if (found)
+ return RTEMS_SUCCESSFUL;
+
+ return RTEMS_INVALID_NAME;
+}
+
+/*
+ * rtems_capture_watch_set
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a watch. The watch can be enabled or
+ * disabled.
+ */
+rtems_status_code
+rtems_capture_watch_ctrl (rtems_name name, rtems_id id, bool enable)
+{
+ rtems_interrupt_level level;
+ rtems_capture_control_t* control;
+ bool found = false;
+
+ /*
+ * Find the control and then set the watch. It must exist before it can
+ * be controlled.
+ */
+ for (control = capture_controls; control != NULL; control = control->next)
+ {
+ if (rtems_capture_match_name_id (control->name, control->id, name, id))
+ {
+ rtems_interrupt_disable (level);
+
+ if (enable)
+ control->flags |= RTEMS_CAPTURE_WATCH;
+ else
+ control->flags &= ~RTEMS_CAPTURE_WATCH;
+
+ rtems_interrupt_enable (level);
+
+ found = true;
+ }
+ }
+
+ if (found)
+ return RTEMS_SUCCESSFUL;
+
+ return RTEMS_INVALID_NAME;
+}
+
+/*
+ * rtems_capture_watch_global
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a global watch. The watch can be enabled or
+ * disabled. A global watch configures all tasks below the ceiling and above
+ * the floor to be traced.
+ */
+rtems_status_code
+rtems_capture_watch_global (bool enable)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ /*
+ * We need to keep specific and global watches separate so
+ * a global enable/disable does not lose a specific watch.
+ */
+ if (enable)
+ capture_flags |= RTEMS_CAPTURE_GLOBAL_WATCH;
+ else
+ capture_flags &= ~RTEMS_CAPTURE_GLOBAL_WATCH;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_global_on
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the global watch state.
+ */
+bool
+rtems_capture_watch_global_on (void)
+{
+ return capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0;
+}
+
+/*
+ * rtems_capture_watch_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch ceiling. Tasks at or greating that the
+ * ceiling priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a higher
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_ceiling (rtems_task_priority ceiling)
+{
+ capture_ceiling = ceiling;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_get_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch ceiling.
+ */
+rtems_task_priority
+rtems_capture_watch_get_ceiling (void)
+{
+ return capture_ceiling;
+}
+
+/*
+ * rtems_capture_watch_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch floor. Tasks at or less that the
+ * floor priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a lower
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_floor (rtems_task_priority floor)
+{
+ capture_floor = floor;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_get_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch floor.
+ */
+rtems_task_priority
+rtems_capture_watch_get_floor (void)
+{
+ return capture_floor;
+}
+
+/*
+ * rtems_capture_map_trigger
+ *
+ * DESCRIPTION:
+ *
+ * Map the trigger to a bit mask.
+ *
+ */
+uint32_t
+rtems_capture_map_trigger (rtems_capture_trigger_t trigger)
+{
+ /*
+ * Transform the mode and trigger to a bit map.
+ */
+ switch (trigger)
+ {
+ case rtems_capture_switch:
+ return RTEMS_CAPTURE_SWITCH;
+ case rtems_capture_create:
+ return RTEMS_CAPTURE_CREATE;
+ case rtems_capture_start:
+ return RTEMS_CAPTURE_START;
+ case rtems_capture_restart:
+ return RTEMS_CAPTURE_RESTART;
+ case rtems_capture_delete:
+ return RTEMS_CAPTURE_DELETE;
+ case rtems_capture_begin:
+ return RTEMS_CAPTURE_BEGIN;
+ case rtems_capture_exitted:
+ return RTEMS_CAPTURE_EXITTED;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*
+ * rtems_capture_set_trigger
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a trigger.
+ *
+ * This set trigger routine will create a capture control for the
+ * target task. The task list is searched and any existing tasks
+ * are linked to the new control.
+ *
+ * We can have a number of tasks that have the same name so we
+ * search using names. This means a number of tasks can be
+ * linked to single control.
+ */
+rtems_status_code
+rtems_capture_set_trigger (rtems_name from_name,
+ rtems_id from_id,
+ rtems_name to_name,
+ rtems_id to_id,
+ rtems_capture_trigger_mode_t mode,
+ rtems_capture_trigger_t trigger)
+{
+ rtems_capture_control_t* control;
+ uint32_t flags;
+
+ flags = rtems_capture_map_trigger (trigger);
+
+ /*
+ * The mode sets the opposite type of trigger. For example
+ * FROM ANY means trigger when the event happens TO this
+ * task. TO ANY means FROM this task.
+ */
+
+ if (mode == rtems_capture_to_any)
+ {
+ control = rtems_capture_create_control (from_name, from_id);
+ if (control == NULL)
+ return RTEMS_NO_MEMORY;
+ control->from_triggers |= flags & RTEMS_CAPTURE_FROM_TRIGS;
+ }
+ else
+ {
+ control = rtems_capture_create_control (to_name, to_id);
+ if (control == NULL)
+ return RTEMS_NO_MEMORY;
+ if (mode == rtems_capture_from_any)
+ control->to_triggers |= flags;
+ else
+ {
+ bool done = false;
+ int i;
+
+ control->by_triggers |= flags;
+
+ for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
+ {
+ if (rtems_capture_control_by_valid (control, i) &&
+ ((control->by[i].name == from_name) ||
+ (from_id && (control->by[i].id == from_id))))
+ {
+ control->by[i].trigger |= flags;
+ done = true;
+ break;
+ }
+ }
+
+ if (!done)
+ {
+ for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
+ {
+ if (!rtems_capture_control_by_valid (control, i))
+ {
+ control->by_valid |= RTEMS_CAPTURE_CONTROL_FROM_MASK (i);
+ control->by[i].name = from_name;
+ control->by[i].id = from_id;
+ control->by[i].trigger = flags;
+ done = true;
+ break;
+ }
+ }
+ }
+
+ if (!done)
+ return RTEMS_TOO_MANY;
+ }
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_clear_trigger
+ *
+ * DESCRIPTION:
+ *
+ * This function clear a trigger.
+ */
+rtems_status_code
+rtems_capture_clear_trigger (rtems_name from_name,
+ rtems_id from_id,
+ rtems_name to_name,
+ rtems_id to_id,
+ rtems_capture_trigger_mode_t mode,
+ rtems_capture_trigger_t trigger)
+{
+ rtems_capture_control_t* control;
+ uint32_t flags;
+
+ flags = rtems_capture_map_trigger (trigger);
+
+ if (mode == rtems_capture_to_any)
+ {
+ control = rtems_capture_find_control (from_name, from_id);
+ if (control == NULL)
+ {
+ if (from_id)
+ return RTEMS_INVALID_ID;
+ return RTEMS_INVALID_NAME;
+ }
+ control->from_triggers &= ~flags;
+ }
+ else
+ {
+ control = rtems_capture_find_control (to_name, to_id);
+ if (control == NULL)
+ {
+ if (to_id)
+ return RTEMS_INVALID_ID;
+ return RTEMS_INVALID_NAME;
+ }
+ if (mode == rtems_capture_from_any)
+ control->to_triggers &= ~flags;
+ else
+ {
+ bool done = false;
+ int i;
+
+ control->by_triggers &= ~flags;
+
+ for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
+ {
+ if (rtems_capture_control_by_valid (control, i) &&
+ ((control->by[i].name == from_name) ||
+ (control->by[i].id == from_id)))
+ {
+ control->by[i].trigger &= ~trigger;
+ if (control->by[i].trigger == 0)
+ control->by_valid &= ~RTEMS_CAPTURE_CONTROL_FROM_MASK (i);
+ done = true;
+ break;
+ }
+ }
+
+ if (!done)
+ {
+ if (from_id)
+ return RTEMS_INVALID_ID;
+ return RTEMS_INVALID_NAME;
+ }
+ }
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_read
+ *
+ * DESCRIPTION:
+ *
+ * This function reads a number of records from the capture buffer.
+ * The user can optionally block and wait until the buffer as a
+ * specific number of records available or a specific time has
+ * elasped.
+ *
+ * The function returns the number of record that is has that are
+ * in a continous block of memory. If the number of available records
+ * wrap then only those records are provided. This removes the need for
+ * caller to be concerned about buffer wrappings. If the number of
+ * requested records cannot be met due to the wrapping of the records
+ * less than the specified number will be returned.
+ *
+ * The user must release the records. This is achieved with a call to
+ * rtems_capture_release. Calls this function without a release will
+ * result in at least the same number of records being released.
+ *
+ * The 'threshold' parameter is the number of records that must be
+ * captured before returning. If a timeout period is specified (non-0)
+ * any captured records will be returned. These parameters stop
+ * thrashing occuring for a small number of records, yet allows
+ * a user configured latiency to be applied for single events.
+ *
+ * The 'timeout' parameter is in micro-seconds. A value of 0 will disable
+ * the timeout.
+ *
+ */
+rtems_status_code
+rtems_capture_read (uint32_t threshold,
+ uint32_t timeout,
+ uint32_t* read,
+ rtems_capture_record_t** recs)
+{
+ rtems_interrupt_level level;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint32_t count;
+
+ *read = 0;
+ *recs = NULL;
+
+ rtems_interrupt_disable (level);
+
+ /*
+ * Only one reader is allowed.
+ */
+
+ if (capture_flags & RTEMS_CAPTURE_READER_ACTIVE)
+ {
+ rtems_interrupt_enable (level);
+ return RTEMS_RESOURCE_IN_USE;
+ }
+
+ capture_flags |= RTEMS_CAPTURE_READER_ACTIVE;
+ *read = count = capture_count;
+
+ rtems_interrupt_enable (level);
+
+ *recs = &capture_records[capture_out];
+
+ for (;;)
+ {
+ /*
+ * See if the count wraps the end of the record buffer.
+ */
+ if (count && ((capture_out + count) >= capture_size))
+ *read = capture_size - capture_out;
+
+ /*
+ * Do we have a threshold and the current count has not wrapped
+ * around the end of the capture record buffer ?
+ */
+ if ((*read == count) && threshold)
+ {
+ /*
+ * Do we have enough records ?
+ */
+ if (*read < threshold)
+ {
+ rtems_event_set event_out;
+
+ rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &capture_reader);
+
+ rtems_interrupt_disable (level);
+
+ capture_flags |= RTEMS_CAPTURE_READER_WAITING;
+
+ rtems_interrupt_enable (level);
+
+ sc = rtems_event_receive (RTEMS_EVENT_0,
+ RTEMS_WAIT | RTEMS_EVENT_ANY,
+ RTEMS_MICROSECONDS_TO_TICKS (timeout),
+ &event_out);
+
+ /*
+ * Let the user handle all other sorts of errors. This may
+ * not be the best solution, but oh well, it will do for
+ * now.
+ */
+ if ((sc != RTEMS_SUCCESSFUL) && (sc != RTEMS_TIMEOUT))
+ break;
+
+ rtems_interrupt_disable (level);
+
+ *read = count = capture_count;
+
+ rtems_interrupt_enable (level);
+
+ continue;
+ }
+ }
+
+ /*
+ * Always out if we reach here. To loop use continue.
+ */
+ break;
+ }
+
+ return sc;
+}
+
+/*
+ * rtems_capture_release
+ *
+ * DESCRIPTION:
+ *
+ * This function releases the requested number of record slots back
+ * to the capture engine. The count must match the number read.
+ */
+rtems_status_code
+rtems_capture_release (uint32_t count)
+{
+ rtems_capture_record_t* rec;
+ uint32_t counted;
+
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (count > capture_count)
+ count = capture_count;
+
+ rtems_interrupt_enable (level);
+
+ counted = count;
+
+ rec = &capture_records[capture_out];
+
+ while (counted--)
+ {
+ rtems_capture_refcount_down (rec->task);
+ rtems_capture_destroy_capture_task (rec->task);
+ rec++;
+ }
+
+ rtems_interrupt_disable (level);
+
+ capture_count -= count;
+
+ capture_out = (capture_out + count) % capture_size;
+
+ capture_flags &= ~RTEMS_CAPTURE_READER_ACTIVE;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_tick_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tick period in nano-seconds.
+ */
+uint32_t
+rtems_capture_tick_time (void)
+{
+ return capture_tick_period;
+}
+
+/*
+ * rtems_capture_event_text
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a string for an event based on the bit in the
+ * event. The functions takes the bit offset as a number not the bit
+ * set in a bit map.
+ */
+const char*
+rtems_capture_event_text (int event)
+{
+ if ((event < RTEMS_CAPTURE_EVENT_START) || (event > RTEMS_CAPTURE_EVENT_END))
+ return "invalid event id";
+ return capture_event_text[event - RTEMS_CAPTURE_EVENT_START];
+}
+
+/*
+ * rtems_capture_get_task_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of tasks that the
+ * capture engine has detected.
+ */
+rtems_capture_task_t*
+rtems_capture_get_task_list (void)
+{
+ return capture_tasks;
+}
+
+/*
+ * rtems_capture_task_stack_usage
+ *
+ * DESCRIPTION:
+ *
+ * This function updates the stack usage. The task control block
+ * is updated.
+ */
+uint32_t
+rtems_capture_task_stack_usage (rtems_capture_task_t* task)
+{
+ if (task->tcb)
+ {
+ uint32_t* st;
+ uint32_t* s;
+
+ /*
+ * @todo: Assumes all stacks move the same way.
+ */
+ st = task->tcb->Start.Initial_stack.area + task->stack_size;
+ s = task->tcb->Start.Initial_stack.area;
+
+ while (s < st)
+ {
+ if (*s != 0xdeaddead)
+ break;
+ s++;
+ }
+
+ task->stack_clean =
+ s - (uint32_t*) task->tcb->Start.Initial_stack.area;
+ }
+
+ return task->stack_clean;
+}
+
+/*
+ * rtems_capture_get_control_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of control in the
+ * capture engine.
+ */
+rtems_capture_control_t*
+rtems_capture_get_control_list (void)
+{
+ return capture_controls;
+}
diff --git a/cpukit/libmisc/capture/capture.h b/cpukit/libmisc/capture/capture.h
new file mode 100644
index 0000000000..48ba5ebec4
--- /dev/null
+++ b/cpukit/libmisc/capture/capture.h
@@ -0,0 +1,1042 @@
+/**
+ * @file rtems/capture.h
+ */
+
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+ This is the Capture Engine component.
+
+*/
+
+#ifndef __CAPTURE_H_
+#define __CAPTURE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+
+/**
+ * The number of tasks in a trigger group.
+ */
+#define RTEMS_CAPTURE_TRIGGER_TASKS (32)
+
+/**
+ * rtems_capture_from_t
+ *
+ * DESCRIPTION:
+ *
+ * A from capture is a task id and a mask for the type of
+ * from trigger we are interested in. The mask uses the same
+ * bit maps as the flags field in the control structure. There
+ * will only be a from type trigger if the flags in the control
+ * structure has the specific *_BY bit set.
+ */
+typedef struct rtems_capture_from_s
+{
+ rtems_name name;
+ rtems_id id;
+ uint32_t trigger;
+} rtems_capture_from_t;
+
+/**
+ * rtems_capture_control_t
+ *
+ * DESCRIPTION:
+ *
+ * RTEMS control holds the trigger and watch configuration for a group of
+ * tasks with the same name. The flags hold global control flags.
+ *
+ * The to_triggers fields holds triggers TO this task. The from_triggers holds
+ * triggers from this task. The by_triggers is an OR or triggers which are
+ * caused BY the task listed TO this task. The by_valid flag which entries
+ * in by are valid.
+ */
+typedef struct rtems_capture_control_s
+{
+ rtems_name name;
+ rtems_id id;
+ uint32_t flags;
+ uint32_t to_triggers;
+ uint32_t from_triggers;
+ uint32_t by_triggers;
+ uint32_t by_valid;
+ rtems_capture_from_t by[RTEMS_CAPTURE_TRIGGER_TASKS];
+ struct rtems_capture_control_s* next;
+} rtems_capture_control_t;
+
+/**
+ * The from_valid mask.
+ */
+#define RTEMS_CAPTURE_CONTROL_FROM_MASK(_s) \
+ (UINT32_C(1) << (RTEMS_CAPTURE_TRIGGER_TASKS - ((_s) + 1)))
+
+/**
+ * Control flags.
+ */
+#define RTEMS_CAPTURE_WATCH (1 << 0)
+
+/**
+ * Control triggers.
+ */
+#define RTEMS_CAPTURE_SWITCH (1 << 0)
+#define RTEMS_CAPTURE_CREATE (1 << 1)
+#define RTEMS_CAPTURE_START (1 << 2)
+#define RTEMS_CAPTURE_RESTART (1 << 3)
+#define RTEMS_CAPTURE_DELETE (1 << 4)
+#define RTEMS_CAPTURE_BEGIN (1 << 5)
+#define RTEMS_CAPTURE_EXITTED (1 << 6)
+
+#define RTEMS_CAPTURE_FROM_TRIGS (RTEMS_CAPTURE_SWITCH | \
+ RTEMS_CAPTURE_CREATE | \
+ RTEMS_CAPTURE_START | \
+ RTEMS_CAPTURE_RESTART | \
+ RTEMS_CAPTURE_DELETE)
+
+#define RTEMS_CAPTURE_TO_TRIGS (RTEMS_CAPTURE_SWITCH | \
+ RTEMS_CAPTURE_CREATE | \
+ RTEMS_CAPTURE_START | \
+ RTEMS_CAPTURE_RESTART | \
+ RTEMS_CAPTURE_DELETE | \
+ RTEMS_CAPTURE_BEGIN | \
+ RTEMS_CAPTURE_EXITTED)
+
+/**
+ * rtems_capture_task_t
+ *
+ * DESCRIPTION:
+ *
+ * RTEMS capture control provdes the information about a task, along
+ * with its trigger state. The control is referenced by each
+ * capture record. This is information neeed by the decoder. The
+ * capture record cannot assume the task will exist when the record is
+ * dumped via the target interface so task info needed for tracing is
+ * copied and held here. Once the references in the trace buffer
+ * have been removed and the task is deleted this structure is
+ * released back to the heap.
+ *
+ * The inline helper functions provide more details about the info
+ * contained in this structure.
+ *
+ * Note, the tracer code exploits the fact an rtems_name is a
+ * 32bit value.
+ */
+typedef struct rtems_capture_task_s
+{
+ rtems_name name;
+ rtems_id id;
+ uint32_t flags;
+ uint32_t refcount;
+ rtems_tcb* tcb;
+ uint32_t in;
+ uint32_t out;
+ rtems_task_priority start_priority;
+ uint32_t stack_size;
+ uint32_t stack_clean;
+ uint32_t ticks;
+ uint32_t tick_offset;
+ uint32_t ticks_in;
+ uint32_t tick_offset_in;
+ uint32_t last_ticks;
+ uint32_t last_tick_offset;
+ rtems_capture_control_t* control;
+ struct rtems_capture_task_s* forw;
+ struct rtems_capture_task_s* back;
+} rtems_capture_task_t;
+
+/**
+ * Task flags.
+ */
+#define RTEMS_CAPTURE_TRACED (1 << 0)
+
+/*
+ * rtems_capture_record_t
+ *
+ * DESCRIPTION:
+ *
+ * RTEMS capture record. This is a record that is written into
+ * the buffer. The events includes the priority of the task
+ * at the time of the context switch.
+ */
+typedef struct rtems_capture_record_s
+{
+ rtems_capture_task_t* task;
+ uint32_t events;
+ uint32_t ticks;
+ uint32_t tick_offset;
+} rtems_capture_record_t;
+
+/**
+ * The capture record event flags.
+ */
+#define RTEMS_CAPTURE_REAL_PRI_EVENT_MASK UINT32_C (0x000000ff)
+#define RTEMS_CAPTURE_CURR_PRI_EVENT_MASK UINT32_C (0x0000ff00)
+#define RTEMS_CAPTURE_REAL_PRIORITY_EVENT (0)
+#define RTEMS_CAPTURE_CURR_PRIORITY_EVENT (8)
+#define RTEMS_CAPTURE_EVENT_START (16)
+#define RTEMS_CAPTURE_CREATED_BY_EVENT UINT32_C (0x00010000)
+#define RTEMS_CAPTURE_CREATED_EVENT UINT32_C (0x00020000)
+#define RTEMS_CAPTURE_STARTED_BY_EVENT UINT32_C (0x00040000)
+#define RTEMS_CAPTURE_STARTED_EVENT UINT32_C (0x00080000)
+#define RTEMS_CAPTURE_RESTARTED_BY_EVENT UINT32_C (0x00100000)
+#define RTEMS_CAPTURE_RESTARTED_EVENT UINT32_C (0x00200000)
+#define RTEMS_CAPTURE_DELETED_BY_EVENT UINT32_C (0x00400000)
+#define RTEMS_CAPTURE_DELETED_EVENT UINT32_C (0x00800000)
+#define RTEMS_CAPTURE_BEGIN_EVENT UINT32_C (0x01000000)
+#define RTEMS_CAPTURE_EXITTED_EVENT UINT32_C (0x02000000)
+#define RTEMS_CAPTURE_SWITCHED_OUT_EVENT UINT32_C (0x04000000)
+#define RTEMS_CAPTURE_SWITCHED_IN_EVENT UINT32_C (0x08000000)
+#define RTEMS_CAPTURE_TIMESTAMP UINT32_C (0x10000000)
+#define RTEMS_CAPTURE_EVENT_END (28)
+
+/**
+ * rtems_capture_trigger_mode_t
+ *
+ * DESCRIPTION:
+ *
+ * The types of trigger modes that exist.
+ */
+typedef enum rtems_capture_trigger_mode_e
+{
+ rtems_capture_to_any,
+ rtems_capture_from_any,
+ rtems_capture_from_to
+} rtems_capture_trigger_mode_t;
+
+/**
+ * rtems_capture_trigger_t
+ *
+ * DESCRIPTION:
+ *
+ * The types of triggers that exist.
+ */
+typedef enum rtems_capture_trigger_e
+{
+ rtems_capture_switch,
+ rtems_capture_create,
+ rtems_capture_start,
+ rtems_capture_restart,
+ rtems_capture_delete,
+ rtems_capture_begin,
+ rtems_capture_exitted
+} rtems_capture_trigger_t;
+
+/**
+ * rtems_capture_timestamp
+ *
+ * DESCRIPTION:
+ *
+ * This defines the callout handler to obtain a time stamp. The
+ * value returned is time count since the last read.
+ *
+ */
+
+typedef void (*rtems_capture_timestamp)
+ (uint32_t* ticks, uint32_t* micro);
+
+/**
+ * rtems_capture_open
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the realtime trace manager allocating the
+ * capture buffer. It is assumed we have a working heap at stage of
+ * initialisation.
+ *
+ */
+rtems_status_code
+rtems_capture_open (uint32_t size,
+ rtems_capture_timestamp timestamp);
+
+/**
+ * rtems_capture_close
+ *
+ * DESCRIPTION:
+ *
+ * This function shutdowns the tracer and release any claimed
+ * resources.
+ */
+rtems_status_code
+rtems_capture_close (void);
+
+/**
+ * rtems_capture_control
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of tracing at a global level.
+ */
+rtems_status_code
+rtems_capture_control (bool enable);
+
+/**
+ * rtems_capture_monitor
+ *
+ * DESCRIPTION:
+ *
+ * This function enable the monitor mode. When in the monitor mode
+ * the tasks are monitored but no data is saved. This can be used
+ * to profile the load on a system.
+ */
+rtems_status_code
+rtems_capture_monitor (bool enable);
+
+/*
+ * rtems_capture_flush
+ *
+ * DESCRIPTION:
+ *
+ * This function flushes the trace buffer. The prime parameter allows the
+ * capture engine to also be primed again.
+ */
+rtems_status_code
+rtems_capture_flush (bool prime);
+
+/**
+ * rtems_capture_watch_add
+ *
+ * DESCRIPTION:
+ *
+ * This function defines a watch for a specific task given a name. A watch
+ * causes it to be traced either in or out of context. The watch can be
+ * optionally enabled or disabled with the set routine. It is disabled by
+ * default.
+ */
+rtems_status_code
+rtems_capture_watch_add (rtems_name name, rtems_id id);
+
+/**
+ * rtems_capture_watch_del
+ *
+ * DESCRIPTION:
+ *
+ * This function removes a watch for a specific task given a name. The task
+ * description will still exist if referenced by a trace record in the trace
+ * buffer or a global watch is defined.
+ */
+rtems_status_code
+rtems_capture_watch_del (rtems_name name, rtems_id id);
+
+/**
+ * rtems_capture_watch_set
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a watch. The watch can be enabled or
+ * disabled.
+ */
+rtems_status_code
+rtems_capture_watch_ctrl (rtems_name name,
+ rtems_id id,
+ bool enable);
+
+/**
+ * rtems_capture_watch_global
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a global watch. The watch can
+ * be enabled or disabled. A global watch configures all tasks below
+ * the ceiling and above the floor to be traced.
+ */
+rtems_status_code
+rtems_capture_watch_global (bool enable);
+
+/**
+ * rtems_capture_watch_global_on
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the global watch state.
+ */
+bool
+rtems_capture_watch_global_on (void);
+
+/**
+ * rtems_capture_watch_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch ceiling. Tasks at or greating that the
+ * ceiling priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a higher
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_ceiling (rtems_task_priority ceiling);
+
+/**
+ * rtems_capture_watch_get_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch ceiling.
+ */
+rtems_task_priority
+rtems_capture_watch_get_ceiling (void);
+
+/**
+ * rtems_capture_watch_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch floor. Tasks at or less that the
+ * floor priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a lower
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_floor (rtems_task_priority floor);
+
+/**
+ * rtems_capture_watch_get_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch floor.
+ */
+rtems_task_priority
+rtems_capture_watch_get_floor (void);
+
+/**
+ * rtems_capture_set_trigger
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a trigger.
+ *
+ * This set trigger routine will create a trace control for the
+ * target task. The task list is searched and any existing tasks
+ * are linked to the new control.
+ *
+ * We can have a number of tasks that have the same name so we
+ * search using names. This means a number of tasks can be
+ * linked to single control.
+ */
+rtems_status_code
+rtems_capture_set_trigger (rtems_name from_name,
+ rtems_id from_id,
+ rtems_name to_name,
+ rtems_id to_id,
+ rtems_capture_trigger_mode_t mode,
+ rtems_capture_trigger_t trigger);
+
+/**
+ * rtems_capture_clear_trigger
+ *
+ * DESCRIPTION:
+ *
+ * This function clears a trigger.
+ *
+ * This clear trigger routine will not clear a watch.
+ */
+rtems_status_code
+rtems_capture_clear_trigger (rtems_name from_name,
+ rtems_id from_id,
+ rtems_name to_name,
+ rtems_id to_id,
+ rtems_capture_trigger_mode_t mode,
+ rtems_capture_trigger_t trigger);
+
+/**
+ * rtems_capture_read
+ *
+ * DESCRIPTION:
+ *
+ * This function reads a number of records from the capture buffer.
+ * The user can optionally block and wait until the buffer as a
+ * specific number of records available or a specific time has
+ * elasped.
+ *
+ * The function returns the number of record that is has that are
+ * in a continous block of memory. If the number of available records
+ * wrap then only those records are provided. This removes the need for
+ * caller to be concerned about buffer wrappings. If the number of
+ * requested records cannot be met due to the wrapping of the records
+ * less than the specified number will be returned.
+ *
+ * The user must release the records. This is achieved with a call to
+ * rtems_capture_release. Calls this function without a release will
+ * result in at least the same number of records being released.
+ *
+ * The 'threshold' parameter is the number of records that must be
+ * captured before returning. If a timeout period is specified (non-0)
+ * any captured records will be returned. These parameters stop
+ * thrashing occuring for a small number of records, yet allows
+ * a user configured latiency to be applied for single events.
+ *
+ * The 'timeout' parameter is in micro-seconds. A value of 0 will
+ * disable the timeout.
+ *
+ */
+rtems_status_code
+rtems_capture_read (uint32_t threshold,
+ uint32_t timeout,
+ uint32_t* read,
+ rtems_capture_record_t** recs);
+
+/**
+ * rtems_capture_release
+ *
+ * DESCRIPTION:
+ *
+ * This function releases the requested number of record slots back
+ * to the capture engine. The count must match the number read.
+ */
+rtems_status_code
+rtems_capture_release (uint32_t count);
+
+/**
+ * rtems_capture_tick_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tick period in micro-seconds.
+ */
+uint32_t
+rtems_capture_tick_time (void);
+
+/*
+ * rtems_capture_tick_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tick period in micro-seconds.
+ */
+uint32_t
+rtems_capture_tick_time (void);
+
+/**
+ * rtems_capture_event_text
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a string for an event based on the bit in the
+ * event. The functions takes the bit offset as a number not the bit
+ * set in a bit map.
+ */
+const char*
+rtems_capture_event_text (int event);
+
+/**
+ * rtems_capture_get_task_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of tasks that the
+ * capture engine has detected.
+ */
+rtems_capture_task_t*
+rtems_capture_get_task_list (void);
+
+/**
+ * rtems_capture_next_task
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the pointer to the next task in the list. The
+ * pointer NULL terminates the list.
+ */
+static inline rtems_capture_task_t*
+rtems_capture_next_task (rtems_capture_task_t* task)
+{
+ return task->forw;
+}
+
+/**
+ * rtems_capture_task_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function returns true if the task control block points to
+ * a valid task.
+ */
+static inline bool
+rtems_capture_task_valid (rtems_capture_task_t* task)
+{
+ return task->tcb != NULL;
+}
+
+/**
+ * rtems_capture_task_id
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task id.
+ */
+static inline rtems_id
+rtems_capture_task_id (rtems_capture_task_t* task)
+{
+ return task->id;
+}
+
+/**
+ * rtems_capture_task_state
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task state.
+ */
+static inline States_Control
+rtems_capture_task_state (rtems_capture_task_t* task)
+{
+ if (rtems_capture_task_valid (task))
+ return task->tcb->current_state;
+ return 0;
+}
+
+/**
+ * rtems_capture_task_name
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task name.
+ */
+static inline rtems_name
+rtems_capture_task_name (rtems_capture_task_t* task)
+{
+ return task->name;
+}
+
+/**
+ * rtems_capture_task_flags
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task flags.
+ */
+static inline uint32_t
+rtems_capture_task_flags (rtems_capture_task_t* task)
+{
+ return task->flags;
+}
+
+/**
+ * rtems_capture_task_control
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task control if present.
+ */
+static inline rtems_capture_control_t*
+rtems_capture_task_control (rtems_capture_task_t* task)
+{
+ return task->control;
+}
+
+/**
+ * rtems_capture_task_control_flags
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task control flags if a control is present.
+ */
+static inline uint32_t
+rtems_capture_task_control_flags (rtems_capture_task_t* task)
+{
+ if (!task->control)
+ return 0;
+ return task->control->flags;
+}
+
+/**
+ * rtems_capture_task_switched_in
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of times the task has
+ * been switched into context.
+ */
+static inline uint32_t
+rtems_capture_task_switched_in (rtems_capture_task_t* task)
+{
+ return task->in;
+}
+
+/**
+ * rtems_capture_task_switched_out
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of times the task has
+ * been switched out of context.
+ */
+static inline uint32_t
+rtems_capture_task_switched_out (rtems_capture_task_t* task)
+{
+ return task->out;
+}
+
+/**
+ * rtems_capture_task_curr_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tasks start priority. The tracer needs this
+ * to track where the task's priority goes.
+ */
+static inline rtems_task_priority
+rtems_capture_task_start_priority (rtems_capture_task_t* task)
+{
+ return task->start_priority;
+}
+
+/**
+ * rtems_capture_task_real_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tasks real priority.
+ */
+static inline rtems_task_priority
+rtems_capture_task_real_priority (rtems_capture_task_t* task)
+{
+ if (rtems_capture_task_valid (task))
+ return task->tcb->real_priority;
+ return 0;
+}
+
+/**
+ * rtems_capture_task_curr_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tasks current priority.
+ */
+static inline rtems_task_priority
+rtems_capture_task_curr_priority (rtems_capture_task_t* task)
+{
+ if (rtems_capture_task_valid (task))
+ return task->tcb->current_priority;
+ return 0;
+}
+
+/**
+ * rtems_capture_task_stack_usage
+ *
+ * DESCRIPTION:
+ *
+ * This function updates the stack usage. The task control block
+ * is updated.
+ */
+uint32_t
+rtems_capture_task_stack_usage (rtems_capture_task_t* task);
+
+/**
+ * rtems_capture_task_stack_size
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task's stack size.
+ */
+static inline uint32_t
+rtems_capture_task_stack_size (rtems_capture_task_t* task)
+{
+ return task->stack_size;
+}
+
+/**
+ * rtems_capture_task_stack_used
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the amount of stack used.
+ */
+static inline uint32_t
+rtems_capture_task_stack_used (rtems_capture_task_t* task)
+{
+ return task->stack_size - task->stack_clean;
+}
+
+/**
+ * rtems_capture_task_ticks
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current execution time as ticks.
+ */
+static inline uint32_t
+rtems_capture_task_ticks (rtems_capture_task_t* task)
+{
+ return task->ticks;
+}
+
+/**
+ * rtems_capture_task_tick_offset
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current execution time tick offset.
+ */
+static inline uint32_t
+rtems_capture_task_tick_offset (rtems_capture_task_t* task)
+{
+ return task->tick_offset;
+}
+
+/**
+ * rtems_capture_task_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current execution time.
+ */
+static inline unsigned long long
+rtems_capture_task_time (rtems_capture_task_t* task)
+{
+ unsigned long long t = task->ticks;
+ return (t * rtems_capture_tick_time ()) + task->tick_offset;;
+}
+
+/**
+ * rtems_capture_task_delta_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the execution time as a different between the
+ * last time the detla time was and now.
+ */
+static inline unsigned long long
+rtems_capture_task_delta_time (rtems_capture_task_t* task)
+{
+ unsigned long long t = task->ticks - task->last_ticks;
+ uint32_t o = task->tick_offset - task->last_tick_offset;
+
+ task->last_ticks = task->ticks;
+ task->last_tick_offset = task->tick_offset;
+
+ return (t * rtems_capture_tick_time ()) + o;
+}
+
+/**
+ * rtems_capture_task_count
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of tasks the capture
+ * engine knows about.
+ */
+static inline uint32_t
+rtems_capture_task_count (void)
+{
+ rtems_capture_task_t* task = rtems_capture_get_task_list ();
+ uint32_t count = 0;
+
+ while (task)
+ {
+ count++;
+ task = rtems_capture_next_task (task);
+ }
+
+ return count;
+}
+
+/**
+ * rtems_capture_get_control_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of controls in the
+ * capture engine.
+ */
+rtems_capture_control_t*
+rtems_capture_get_control_list (void);
+
+/**
+ * rtems_capture_next_control
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the pointer to the next control in the list. The
+ * pointer NULL terminates the list.
+ */
+static inline rtems_capture_control_t*
+rtems_capture_next_control (rtems_capture_control_t* control)
+{
+ return control->next;
+}
+
+/**
+ * rtems_capture_control_id
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control id.
+ */
+static inline rtems_id
+rtems_capture_control_id (rtems_capture_control_t* control)
+{
+ return control->id;
+}
+
+/**
+ * rtems_capture_control_name
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control name.
+ */
+static inline rtems_name
+rtems_capture_control_name (rtems_capture_control_t* control)
+{
+ return control->name;
+}
+
+/**
+ * rtems_capture_control_flags
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control flags.
+ */
+static inline uint32_t
+rtems_capture_control_flags (rtems_capture_control_t* control)
+{
+ return control->flags;
+}
+
+/**
+ * rtems_capture_control_to_triggers
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task control to triggers.
+ */
+static inline uint32_t
+rtems_capture_control_to_triggers (rtems_capture_control_t* control)
+{
+ return control->to_triggers;
+}
+
+/**
+ * rtems_capture_control_from_triggers
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task control from triggers.
+ */
+static inline uint32_t
+rtems_capture_control_from_triggers (rtems_capture_control_t* control)
+{
+ return control->from_triggers;
+}
+
+/**
+ * rtems_capture_control_all_by_triggers
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task control by triggers.
+ */
+static inline uint32_t
+rtems_capture_control_all_by_triggers (rtems_capture_control_t* control)
+{
+ return control->by_triggers;
+}
+
+/**
+ * rtems_capture_control_by_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control valid BY flags.
+ */
+static inline int
+rtems_capture_control_by_valid (rtems_capture_control_t* control, int slot)
+{
+ return control->by_valid & RTEMS_CAPTURE_CONTROL_FROM_MASK (slot);
+}
+
+/**
+ * rtems_capture_control_by_name
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control BY task name.
+ */
+static inline rtems_name
+rtems_capture_control_by_name (rtems_capture_control_t* control, int by)
+{
+ if (by < RTEMS_CAPTURE_TRIGGER_TASKS)
+ return control->by[by].name;
+ return control->by[0].name;
+}
+
+/**
+ * rtems_capture_control_by_id
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control BY task id.
+ */
+static inline rtems_id
+rtems_capture_control_by_id (rtems_capture_control_t* control, int by)
+{
+ if (by < RTEMS_CAPTURE_TRIGGER_TASKS)
+ return control->by[by].id;
+ return control->by[0].id;
+}
+
+/**
+ * rtems_capture_control_by_triggers
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control BY task triggers.
+ */
+static inline uint32_t
+rtems_capture_control_by_triggers (rtems_capture_control_t* control,
+ int by)
+{
+ if (by < RTEMS_CAPTURE_TRIGGER_TASKS)
+ return control->by[by].trigger;
+ return control->by[0].trigger;
+}
+
+/**
+ * rtems_capture_control_count
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of controls the capture
+ * engine has.
+ */
+static inline uint32_t
+rtems_capture_control_count (void)
+{
+ rtems_capture_control_t* control = rtems_capture_get_control_list ();
+ uint32_t count = 0;
+
+ while (control)
+ {
+ count++;
+ control = rtems_capture_next_control (control);
+ }
+
+ return count;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/cpuuse/README b/cpukit/libmisc/cpuuse/README
new file mode 100644
index 0000000000..ac674bb0b6
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/README
@@ -0,0 +1,21 @@
+#
+# $Id$
+#
+
+This directory contains code to report and reset per-task CPU usage.
+If the BSP supports nanosecond timestamp granularity, this this information
+is very accurate. Otherwise, it is dependendent on the tick granularity.
+
+It provides two primary features:
+
+ + Generate a CPU Usage Report
+ + Reset CPU Usage Information
+
+NOTES:
+
+1. If configured for tick granularity, CPU usage is "docked" by a
+ clock tick at each context switch.
+2. If configured for nanosecond granularity, no work is done at each
+ clock tick. All bookkeeping is done as part of a context switch.
+
+
diff --git a/cpukit/libmisc/cpuuse/cpuusagedata.c b/cpukit/libmisc/cpuuse/cpuusagedata.c
new file mode 100644
index 0000000000..2d74b7eadf
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/cpuusagedata.c
@@ -0,0 +1,28 @@
+/*
+ * CPU Usage Reporter - Shared Data
+ *
+ * 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 <rtems.h>
+#include <rtems/cpuuse.h>
+#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ #include <rtems/score/timespec.h>
+#endif
+
+#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ struct timespec CPU_usage_Uptime_at_last_reset;
+#else
+ uint32_t CPU_usage_Ticks_at_last_reset;
+#endif
diff --git a/cpukit/libmisc/cpuuse/cpuusagereport.c b/cpukit/libmisc/cpuuse/cpuusagereport.c
new file mode 100644
index 0000000000..92445520b7
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/cpuusagereport.c
@@ -0,0 +1,205 @@
+/*
+ * CPU Usage Reporter
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * 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 <rtems.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include <rtems/cpuuse.h>
+#include <rtems/bspIo.h>
+
+#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ #include <rtems/score/timestamp.h>
+#endif
+
+#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ extern Timestamp_Control CPU_usage_Uptime_at_last_reset;
+#else
+ extern uint32_t CPU_usage_Ticks_at_last_reset;
+#endif
+
+/*PAGE
+ *
+ * rtems_cpu_usage_report
+ */
+
+void rtems_cpu_usage_report_with_plugin(
+ void *context,
+ rtems_printk_plugin_t print
+)
+{
+ uint32_t i;
+ uint32_t api_index;
+ Thread_Control *the_thread;
+ Objects_Information *information;
+ char name[13];
+ uint32_t ival, fval;
+ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ Timestamp_Control uptime, total, ran, uptime_at_last_reset;
+ #else
+ uint32_t total_units = 0;
+ #endif
+
+ if ( !print )
+ return;
+
+ /*
+ * When not using nanosecond CPU usage resolution, we have to count
+ * the number of "ticks" we gave credit for to give the user a rough
+ * guideline as to what each number means proportionally.
+ */
+ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ _Timestamp_Set_to_zero( &total );
+ uptime_at_last_reset = CPU_usage_Uptime_at_last_reset;
+ #else
+ for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) {
+ #if !defined(RTEMS_POSIX_API) || defined(RTEMS_DEBUG)
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ #endif
+
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+
+ if ( the_thread )
+ total_units += the_thread->cpu_time_used;
+ }
+ }
+ }
+ #endif
+
+ (*print)(
+ context,
+ "-------------------------------------------------------------------------------\n"
+ " CPU USAGE BY THREAD\n"
+ "------------+----------------------------------------+---------------+---------\n"
+ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ " ID | NAME | SECONDS | PERCENT\n"
+ #else
+ " ID | NAME | TICKS | PERCENT\n"
+ #endif
+ "------------+----------------------------------------+---------------+---------\n"
+ );
+
+ for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) {
+ #if !defined(RTEMS_POSIX_API) || defined(RTEMS_DEBUG)
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ #endif
+
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+
+ if ( !the_thread )
+ continue;
+
+ rtems_object_get_name( the_thread->Object.id, sizeof(name), name );
+
+ (*print)(
+ context,
+ " 0x%08" PRIx32 " | %-38s |",
+ the_thread->Object.id,
+ name
+ );
+
+ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ /*
+ * If this is the currently executing thread, account for time
+ * since the last context switch.
+ */
+ ran = the_thread->cpu_time_used;
+ if ( _Thread_Executing->Object.id == the_thread->Object.id ) {
+ Timestamp_Control used;
+ Timestamp_Control last = _Thread_Time_of_last_context_switch;
+ _TOD_Get_uptime( &uptime );
+ _Timestamp_Subtract( &last, &uptime, &used );
+ _Timestamp_Add_to( &ran, &used );
+ } else {
+ _TOD_Get_uptime( &uptime );
+ }
+ _Timestamp_Subtract( &uptime_at_last_reset, &uptime, &total );
+ _Timestamp_Divide( &ran, &total, &ival, &fval );
+
+ /*
+ * Print the information
+ */
+
+ (*print)( context,
+ "%7" PRIu32 ".%06" PRIu32 " |%4" PRIu32 ".%03" PRIu32 "\n",
+ _Timestamp_Get_seconds( &ran ),
+ _Timestamp_Get_nanoseconds( &ran ) /
+ TOD_NANOSECONDS_PER_MICROSECOND,
+ ival, fval
+ );
+ #else
+ if (total_units) {
+ uint64_t ival_64;
+
+ ival_64 = the_thread->cpu_time_used;
+ ival_64 *= 100000;
+ ival = ival_64 / total_units;
+ } else {
+ ival = 0;
+ }
+
+ fval = ival % 1000;
+ ival /= 1000;
+ (*print)( context,
+ "%14" PRIu32 " |%4" PRIu32 ".%03" PRIu32 "\n",
+ the_thread->cpu_time_used,
+ ival,
+ fval
+ );
+ #endif
+ }
+ }
+ }
+
+ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ (*print)(
+ context,
+ "------------+----------------------------------------+---------------+---------\n"
+ " TIME SINCE LAST CPU USAGE RESET IN SECONDS: %7" PRIu32 ".%06" PRIu32 "\n"
+ "-------------------------------------------------------------------------------\n",
+ _Timestamp_Get_seconds( &total ),
+ _Timestamp_Get_nanoseconds( &total ) / TOD_NANOSECONDS_PER_MICROSECOND
+ );
+ #else
+ (*print)(
+ context,
+ "------------+----------------------------------------+---------------+---------\n"
+ " TICKS SINCE LAST SYSTEM RESET: %14" PRIu32 "\n"
+ " TOTAL UNITS: %14" PRIu32 "\n"
+ "-------------------------------------------------------------------------------\n",
+ _Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset,
+ total_units
+ );
+ #endif
+}
+
+void rtems_cpu_usage_report( void )
+{
+ rtems_cpu_usage_report_with_plugin( NULL, printk_plugin );
+}
diff --git a/cpukit/libmisc/cpuuse/cpuusagereset.c b/cpukit/libmisc/cpuuse/cpuusagereset.c
new file mode 100644
index 0000000000..0bf46903f1
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/cpuusagereset.c
@@ -0,0 +1,60 @@
+/*
+ * CPU Usage Reporter
+ *
+ * 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 <rtems.h>
+#include <rtems/score/timestamp.h>
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include <rtems/cpuuse.h>
+
+static void CPU_usage_Per_thread_handler(
+ Thread_Control *the_thread
+)
+{
+ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ _Timestamp_Set_to_zero( &the_thread->cpu_time_used );
+ #else
+ the_thread->cpu_time_used = 0;
+ #endif
+}
+
+/*
+ * External data that is shared by cpu usage code but not declared in .h files.
+ */
+#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ extern Timestamp_Control CPU_usage_Uptime_at_last_reset;
+#else
+ extern uint32_t CPU_usage_Ticks_at_last_reset;
+#endif
+
+/*
+ * rtems_cpu_usage_reset
+ */
+void rtems_cpu_usage_reset( void )
+{
+ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ _TOD_Get_uptime( &CPU_usage_Uptime_at_last_reset );
+ _Thread_Time_of_last_context_switch = CPU_usage_Uptime_at_last_reset;
+ #else
+ CPU_usage_Ticks_at_last_reset = _Watchdog_Ticks_since_boot;
+ #endif
+
+ rtems_iterate_over_all_threads(CPU_usage_Per_thread_handler);
+}
diff --git a/cpukit/libmisc/cpuuse/cpuuse.h b/cpukit/libmisc/cpuuse/cpuuse.h
new file mode 100644
index 0000000000..b38927e7c6
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/cpuuse.h
@@ -0,0 +1,51 @@
+/* cpuuse.h
+ *
+ * This include file contains information necessary to utilize
+ * and install the cpu usage reporting mechanism.
+ *
+ * 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_CPUUSE_h
+#define __RTEMS_CPUUSE_h
+
+#include <rtems/bspIo.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * rtems_cpu_usage_report_with_handler
+ */
+
+void rtems_cpu_usage_report_with_plugin(
+ void *context,
+ rtems_printk_plugin_t handler
+);
+
+/*
+ * rtems_cpu_usage_report
+ */
+
+void rtems_cpu_usage_report( void );
+
+/*
+ * rtems_cpu_usage_reset
+ */
+
+void rtems_cpu_usage_reset( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/devnull/devnull.c b/cpukit/libmisc/devnull/devnull.c
new file mode 100644
index 0000000000..4b22199814
--- /dev/null
+++ b/cpukit/libmisc/devnull/devnull.c
@@ -0,0 +1,184 @@
+/* /dev/null
+ *
+ * Derived from rtems' stub driver.
+ *
+ * Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * 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 <rtems.h>
+#include <rtems/devnull.h>
+#include <rtems/libio.h>
+
+/* null_initialize
+ *
+ * This routine is the null device driver init routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+uint32_t NULL_major;
+static char initialized;
+
+rtems_device_driver null_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor __attribute__((unused)),
+ void *pargp __attribute__((unused))
+)
+{
+ rtems_device_driver status;
+
+ if ( !initialized ) {
+ initialized = 1;
+
+ status = rtems_io_register_name(
+ "/dev/null",
+ major,
+ (rtems_device_minor_number) 0
+ );
+
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+
+ NULL_major = major;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* null_open
+ *
+ * This routine is the null device driver open routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargb - pointer to open parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_open(
+ rtems_device_major_number major __attribute__((unused)),
+ rtems_device_minor_number minor __attribute__((unused)),
+ void *pargp __attribute__((unused))
+)
+{
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_close
+ *
+ * This routine is the null device driver close routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargb - pointer to close parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_close(
+ rtems_device_major_number major __attribute__((unused)),
+ rtems_device_minor_number minor __attribute__((unused)),
+ void *pargp __attribute__((unused))
+)
+{
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_read
+ *
+ * This routine is the null device driver read routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to read parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_read(
+ rtems_device_major_number major __attribute__((unused)),
+ rtems_device_minor_number minor __attribute__((unused)),
+ void *pargp __attribute__((unused))
+)
+{
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_write
+ *
+ * This routine is the null device driver write routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to write parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_write(
+ rtems_device_major_number major __attribute__((unused)),
+ rtems_device_minor_number minor __attribute__((unused)),
+ void *pargp
+)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) pargp;
+
+ if ( rw_args )
+ rw_args->bytes_moved = rw_args->count;
+
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_control
+ *
+ * This routine is the null device driver control routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to cntrl parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_control(
+ rtems_device_major_number major __attribute__((unused)),
+ rtems_device_minor_number minor __attribute__((unused)),
+ void *pargp __attribute__((unused))
+)
+{
+ return NULL_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/devnull/devnull.h b/cpukit/libmisc/devnull/devnull.h
new file mode 100644
index 0000000000..4fe90cde6c
--- /dev/null
+++ b/cpukit/libmisc/devnull/devnull.h
@@ -0,0 +1,73 @@
+/* devnull.h
+ *
+ * Null device driver, derived from rtems' stub driver.
+ *
+ * Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * 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_DEVNULL_H
+#define _RTEMS_DEVNULL_H
+
+#include <rtems/io.h> /* rtems_device_driver */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEVNULL_DRIVER_TABLE_ENTRY \
+ { null_initialize, null_open, null_close, null_read, \
+ null_write, null_control }
+
+#define NULL_SUCCESSFUL RTEMS_SUCCESSFUL
+
+rtems_device_driver null_initialize(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_open(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_close(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_read(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_write(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_control(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/dummy/README b/cpukit/libmisc/dummy/README
new file mode 100644
index 0000000000..03bb30834d
--- /dev/null
+++ b/cpukit/libmisc/dummy/README
@@ -0,0 +1,23 @@
+dummy.rel
+=========
+
+A relocatible objects which contains a dummy configuration for RTEMS.
+
+Helps linking standard c-program code with RTEMS, which shall *not* be run
+on a target, such as configure script code fragments generated by autoconf's
+AC_TRY_LINK.
+
+Example:
+
+tar xzvf somepkg.tar.gz
+cd somepkg
+
+LDFLAGS=/usr/local/rtems/<cpu>-rtems/<bsp>/lib/dummy.rel \
+CC="<cpu>-rtems-gcc \
+-B/usr/local/rtems/<cpu>-rtems/<bsp>/lib/ -specs bsp_specs -qrtems" \
+CC_FOR_BUILD="gcc" \
+configure --host=<cpu>-rtems --build=i686-pc-linux-gnu
+make
+
+History:
+Starting dummy.c with a copy of rtems-19990528/c/src/tests/samples/minimum/init.c
diff --git a/cpukit/libmisc/dummy/dummy-networking.c b/cpukit/libmisc/dummy/dummy-networking.c
new file mode 100644
index 0000000000..77d708d516
--- /dev/null
+++ b/cpukit/libmisc/dummy/dummy-networking.c
@@ -0,0 +1,44 @@
+/*
+ * Dummy configuration file
+ *
+ * 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 <rtems.h>
+
+/* Loopback Network Configuration */
+#if defined(RTEMS_NETWORKING)
+ #include <rtems/rtems_bsdnet.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+
+ struct rtems_bsdnet_config rtems_bsdnet_config = {
+ NULL, /* Network interface */
+ NULL, /* Use fixed network configuration */
+ 0, /* Default network task priority */
+ 0, /* Default mbuf capacity */
+ 0, /* Default mbuf cluster capacity */
+ "testSystem", /* Host name */
+ "nowhere.com", /* Domain name */
+ "127.0.0.1", /* Gateway */
+ "127.0.0.1", /* Log host */
+ {"127.0.0.1" }, /* Name server(s) */
+ {"127.0.0.1" }, /* NTP server(s) */
+ 1, /* sb_efficiency */
+ 0, /* udp_tx_buf_size */
+ 0, /* udp_rx_buf_size */
+ 0, /* tcp_tx_buf_size */
+ 0 /* tcp_rx_buf_size */
+ };
+#endif
diff --git a/cpukit/libmisc/dummy/dummy.c b/cpukit/libmisc/dummy/dummy.c
new file mode 100644
index 0000000000..b062c06091
--- /dev/null
+++ b/cpukit/libmisc/dummy/dummy.c
@@ -0,0 +1,38 @@
+/*
+ * Dummy configuration file
+ *
+ * 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 <rtems.h>
+
+int main( int, char **, char **);
+
+/* configuration information */
+
+/* This is enough to get a basic main() up. */
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_MAXIMUM_TASKS 10
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 20
+#define CONFIGURE_INIT_TASK_ENTRY_POINT (void *)main
+
+/* Include basic device drivers needed to call delays */
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
+
diff --git a/cpukit/libmisc/dumpbuf/dumpbuf.c b/cpukit/libmisc/dumpbuf/dumpbuf.c
new file mode 100644
index 0000000000..97274ecbaa
--- /dev/null
+++ b/cpukit/libmisc/dumpbuf/dumpbuf.c
@@ -0,0 +1,80 @@
+/*
+ * COPYRIGHT (c) 1997-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may 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 <rtems/dumpbuf.h>
+#include <rtems/bspIo.h>
+
+/*
+ * Put the body below rtems_print_buffer so it won't get inlined.
+ */
+
+static inline void Dump_Line(
+ const unsigned char *buffer,
+ int length
+);
+
+void rtems_print_buffer(
+ const unsigned char *buffer,
+ int length
+)
+{
+
+ int i, mod, max;
+
+ if ( !length ) return;
+
+ mod = length % 16;
+
+ max = length - mod;
+
+ for ( i=0 ; i<max ; i+=16 )
+ Dump_Line( &buffer[ i ], 16 );
+
+ if ( mod )
+ Dump_Line( &buffer[ max ], mod );
+}
+
+static inline void Dump_Line(
+ const unsigned char *buffer,
+ int length
+)
+{
+
+ int i;
+ char line_buffer[120];
+
+ line_buffer[0] = '\0';
+
+ for( i=0 ; i<length ; i++ )
+ sprintf( line_buffer, "%s%02x ", line_buffer, buffer[ i ] );
+
+ for( ; i<16 ; i++ )
+ strcat( line_buffer, " " );
+
+ strcat( line_buffer, "|" );
+ for( i=0 ; i<length ; i++ )
+ sprintf( line_buffer, "%s%c", line_buffer,
+ isprint( buffer[ i ] ) ? buffer[ i ] : '.' );
+
+ for( ; i<16 ; i++ )
+ strcat( line_buffer, " " );
+
+ strcat( line_buffer, "|\n" );
+
+ printk( line_buffer );
+}
diff --git a/cpukit/libmisc/dumpbuf/dumpbuf.h b/cpukit/libmisc/dumpbuf/dumpbuf.h
new file mode 100644
index 0000000000..3502ace70a
--- /dev/null
+++ b/cpukit/libmisc/dumpbuf/dumpbuf.h
@@ -0,0 +1,39 @@
+/*
+ * COPYRIGHT (c) 1997-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __DUMP_BUFFER_h
+#define __DUMP_BUFFER_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Print Memory Buffer
+ *
+ * This method prints @a length bytes beginning at @a buffer in
+ * a nice format similar to what one would expect from a debugger
+ * or ROM monitor.
+ *
+ * @param[in] buffer is the address of the buffer
+ * @param[in] length is the length of the buffer
+ */
+void rtems_print_buffer(
+ const unsigned char *buffer,
+ int length
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/fb/fb.h b/cpukit/libmisc/fb/fb.h
new file mode 100644
index 0000000000..cf49d7bd91
--- /dev/null
+++ b/cpukit/libmisc/fb/fb.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2000 - Rosimildo da Silva
+ *
+ * MODULE DESCRIPTION:
+ * Micro FrameBuffer interface for Embedded Systems.
+ *
+ * $Id$
+ */
+
+#ifndef _MW_FB_H
+#define _MW_FB_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ioctls
+ 0x46 is 'F' */
+#define FBIOGET_VSCREENINFO 0x4600
+#define FBIOPUT_VSCREENINFO 0x4601
+#define FBIOGET_FSCREENINFO 0x4602
+#define FBIOGETCMAP 0x4604
+#define FBIOPUTCMAP 0x4605
+#define FB_EXEC_FUNCTION 0x4606
+#define FBIOSWAPBUFFERS 0x4607
+#define FBIOSETBUFFERMODE 0x4608
+
+#define FB_SINGLE_BUFFERED 0
+#define FB_TRIPLE_BUFFERED 1
+
+#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
+#define FB_TYPE_PLANES 1 /* Non interleaved planes */
+#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */
+#define FB_TYPE_TEXT 3 /* Text/attributes */
+#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */
+#define FB_TYPE_VIRTUAL_BUFFER 5 /* Virtual Buffer */
+
+
+#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */
+#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */
+#define FB_VISUAL_TRUECOLOR 2 /* True color */
+#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */
+#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */
+#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */
+
+#define FB_ACCEL_NONE 0 /* no hardware accelerator */
+
+struct fb_bitfield {
+ uint32_t offset; /* beginning of bitfield */
+ uint32_t length; /* length of bitfield */
+ uint32_t msb_right; /* != 0 : Most significant bit is */
+ /* right */
+};
+
+struct fb_var_screeninfo {
+ uint32_t xres; /* visible resolution */
+ uint32_t yres;
+ uint32_t bits_per_pixel; /* guess what */
+ struct fb_bitfield red; /* bitfield in fb mem if true color, */
+ struct fb_bitfield green; /* else only length is significant */
+ struct fb_bitfield blue;
+ struct fb_bitfield transp; /* transparency */
+};
+
+struct fb_fix_screeninfo {
+ volatile char *smem_start; /* Start of frame buffer mem */
+ /* (physical address) */
+ uint32_t smem_len; /* Length of frame buffer mem */
+ uint32_t type; /* see FB_TYPE_* */
+ uint32_t visual; /* see FB_VISUAL_* */
+ uint32_t line_length; /* number of chars per line */
+};
+
+struct fb_cmap {
+ uint32_t start; /* First entry */
+ uint32_t len; /* Number of entries */
+ uint16_t *red; /* Red values */
+ uint16_t *green;
+ uint16_t *blue;
+ uint16_t *transp; /* transparency, can be NULL */
+};
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MW_FB_H */
diff --git a/cpukit/libmisc/fb/mw_print.c b/cpukit/libmisc/fb/mw_print.c
new file mode 100644
index 0000000000..4e8abf2bd8
--- /dev/null
+++ b/cpukit/libmisc/fb/mw_print.c
@@ -0,0 +1,92 @@
+/*
+ * COPYRIGHT (c) 1989-2011.
+ * 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 <rtems/mw_uid.h>
+#include <stdio.h>
+
+const char *uid_buttons(
+ unsigned short btns,
+ char *buffer,
+ size_t max
+)
+{
+ snprintf(
+ buffer,
+ max,
+ "LEFT=%s CENTER=%s RIGHT=%s",
+ ((btns & MV_BUTTON_LEFT) ? "down" : "up"),
+ ((btns & MV_BUTTON_CENTER) ? "down" : "up"),
+ ((btns & MV_BUTTON_RIGHT) ? "down" : "up")
+ );
+ return buffer;
+}
+
+void uid_print_message(
+ struct MW_UID_MESSAGE *uid
+)
+{
+ uid_print_message_with_plugin( NULL, printk_plugin, uid );
+}
+
+void uid_print_message_with_plugin(
+ void *context,
+ rtems_printk_plugin_t handler,
+ struct MW_UID_MESSAGE *uid
+)
+{
+ char buttons[80];
+
+ switch (uid->type) {
+ case MV_UID_INVALID:
+ (*handler)( context, "MV_UID_INVALID\n" );
+ break;
+ case MV_UID_REL_POS:
+ (*handler)(
+ context,
+ "MV_UID_REL_POS - %s x=%d y=%d z=%d\n",
+ uid_buttons( uid->m.pos.btns, buttons, sizeof(buttons)),
+ uid->m.pos.x, /* x location */
+ uid->m.pos.y, /* y location */
+ uid->m.pos.z /* z location, 0 for 2D */
+ );
+ break;
+ case MV_UID_ABS_POS:
+ (*handler)(
+ context,
+ "MV_UID_ABS_POS - %s x=%d y=%d z=%d\n",
+ uid_buttons( uid->m.pos.btns, buttons, sizeof(buttons)),
+ uid->m.pos.x, /* x location */
+ uid->m.pos.y, /* y location */
+ uid->m.pos.z /* z location, 0 for 2D */
+ );
+ break;
+ case MV_UID_KBD:
+ (*handler)( context,
+ "MV_UID_KBD - code=0x%04x modifiers=0x%02x mode=0x%02x\n",
+ uid->m.kbd.code, /* keycode or scancode */
+ uid->m.kbd.modifiers, /* key modifiers */
+ uid->m.kbd.mode /* current Kbd mode */
+ );
+ break;
+ case MV_UID_TIMER:
+ (*handler)( context, "MV_UID_TIMER\n" );
+ break;
+ default:
+ (*handler)( context, "Invalid device type\n" );
+ break;
+ }
+
+}
+
diff --git a/cpukit/libmisc/fb/mw_uid.c b/cpukit/libmisc/fb/mw_uid.c
new file mode 100644
index 0000000000..e3cf34f276
--- /dev/null
+++ b/cpukit/libmisc/fb/mw_uid.c
@@ -0,0 +1,150 @@
+/*
+ *
+ * Copyright (c) 2000 - Rosimildo da Silva
+ *
+ * MODULE DESCRIPTION:
+ * This module implements the input devices interface used by MicroWindows
+ * in an embedded system environment. It uses the RTEMS message queue as
+ * the repository for the messages posted by the devices registered.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <rtems.h>
+
+#include <rtems/mw_uid.h>
+#include <rtems/seterr.h>
+
+static rtems_id queue_id = 0;
+static int open_count = 0;
+
+/*
+#define MW_DEBUG_ON 1
+*/
+
+/* open a message queue with the kernel */
+int uid_open_queue(
+ const char *q_name,
+ int flags __attribute__((unused)),
+ size_t max_msgs
+)
+{
+ rtems_status_code status;
+
+ /*
+ * For the first device calling this function we would create the queue.
+ * It is assumed that this call is done at initialization, and no concerns
+ * regarding multi-threading is taken in consideration here.
+ */
+ if ( open_count ) {
+ open_count++;
+ return 0;
+ }
+
+ status = rtems_message_queue_create(
+ rtems_build_name( q_name[0], q_name[1], q_name[2], q_name[3] ),
+ max_msgs,
+ sizeof( struct MW_UID_MESSAGE ),
+ RTEMS_FIFO | RTEMS_LOCAL,
+ &queue_id
+ );
+ if ( status != RTEMS_SUCCESSFUL ) {
+ #ifdef MW_DEBUG_ON
+ printk( "UID_Queue: error creating queue: %d\n", status );
+ #endif
+ return -1;
+ }
+ #ifdef MW_DEBUG_ON
+ printk( "UID_Queue: id=%X\n", queue_id );
+ #endif
+ open_count++;
+ return 0;
+}
+
+
+/* close message queue */
+int uid_close_queue( void )
+{
+ if ( open_count == 1 ) {
+ rtems_message_queue_delete( queue_id );
+ queue_id = 0;
+ }
+ open_count--;
+ return 0;
+}
+
+/* reads for a message from the device */
+int uid_read_message( struct MW_UID_MESSAGE *m, unsigned long timeout )
+{
+ rtems_status_code status;
+ size_t size = 0;
+ unsigned long micro_secs = timeout*1000;
+ int wait = (timeout != 0);
+
+ status = rtems_message_queue_receive(
+ queue_id,
+ (void*)m,
+ &size,
+ wait ? RTEMS_WAIT : RTEMS_NO_WAIT,
+ RTEMS_MICROSECONDS_TO_TICKS(micro_secs)
+ );
+
+ if( status == RTEMS_SUCCESSFUL ) {
+ return size;
+ } else if( ( status == RTEMS_UNSATISFIED ) || ( status == RTEMS_TIMEOUT ) ) {
+ rtems_set_errno_and_return_minus_one( ETIMEDOUT );
+ }
+ /* Here we have one error condition */
+ #ifdef MW_DEBUG_ON
+ printk( "UID_Queue: error reading queue: %d\n", status );
+ #endif
+ return -1;
+}
+
+/*
+ * add a message to the queue of events. This method can be used to
+ * simulate hardware events, and it can be very handy during development
+ * a new interface.
+ */
+int uid_send_message( struct MW_UID_MESSAGE *m )
+{
+ rtems_status_code status;
+ status = rtems_message_queue_send(
+ queue_id, ( void * )m, sizeof( struct MW_UID_MESSAGE ) );
+ return (status == RTEMS_SUCCESSFUL) ? 0 : -1;
+}
+
+/*
+ * register the device to insert events to the message
+ * queue named as the value passed in q_name
+ */
+int uid_register_device( int fd, const char *q_name )
+{
+ return ioctl( fd, MW_UID_REGISTER_DEVICE, q_name );
+}
+
+/* tell this device to stop adding events to the queue */
+int uid_unregister_device( int fd )
+{
+ return ioctl( fd, MW_UID_UNREGISTER_DEVICE, NULL );
+}
+
+/* set the keyboard */
+int uid_set_kbd_mode( int fd, int mode, int *old_mode )
+{
+ if (ioctl( fd, MV_KDGKBMODE, old_mode) < 0) {
+ return -1;
+ }
+ if (ioctl(fd, MV_KDSKBMODE, mode ) < 0 ) {
+ return -1;
+ }
+ return 0;
+}
diff --git a/cpukit/libmisc/fb/mw_uid.h b/cpukit/libmisc/fb/mw_uid.h
new file mode 100644
index 0000000000..89f440acf4
--- /dev/null
+++ b/cpukit/libmisc/fb/mw_uid.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2000 - Rosimildo da Silva
+ *
+ * MODULE DESCRIPTION:
+ * This module defines the interface for input devices used by MicroWindows
+ * in an embedded system environment.
+ *
+ * $Id$
+ */
+
+#ifndef _MW_UID_H
+#define _MW_UID_H
+
+#include <sys/types.h>
+#include <rtems/bspIo.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 0x41XX -- IOCTL functions for the Micro Input Devices commands */
+#define MW_UID_REGISTER_DEVICE 0x4100
+#define MW_UID_UNREGISTER_DEVICE 0x4101
+
+/* devices supported by MicroWindows */
+enum MW_INPUT_DEVICE_TYPE {
+ MV_UID_INVALID = 0,
+ MV_UID_REL_POS = 1, /* mouse */
+ MV_UID_ABS_POS = 2, /* touch-screen */
+ MV_UID_KBD = 3, /* keyboard */
+ MV_UID_TIMER = 4 /* timer -- not used */
+};
+
+/* matching MicroWindows */
+#define MV_BUTTON_RIGHT 0x01
+#define MV_BUTTON_CENTER 0x02
+#define MV_BUTTON_LEFT 0x04
+
+/* modifiers of the keyboard type devices */
+#define MV_KEY_MODIFIER_SHIFT_DOWN 0x10
+#define MV_KEY_MODIFIER_ALT_DOWN 0x20
+
+/* indication of the LEDS */
+#define MV_KEY_MODIFIER_CAPS_ON 0x04
+#define MV_KEY_MODIFIER_NUN_LOCK_ON 0x02
+#define MV_KEY_SCROLL_LOCK_ON 0x01
+
+/* keyboard modes -- default ASCII */
+#define MV_KEY_MODE_ASCII 0x01
+/*
+ * This mode one event is sent when a key is pressed,
+ * and another one is send when a key is released.
+ */
+#define MV_KEY_MODE_SCANCODE 0x00
+
+/* these defines match with the linux keyboard range
+ * for ioctls functions for the keyboard interface.
+ * 0x4BXX --- keyboard related functions
+ */
+#define MV_KDGKBMODE 0x4B44 /* gets current keyboard mode */
+#define MV_KDSKBMODE 0x4B45 /* sets current keyboard mode */
+
+/*
+ * Message generated by input devices controlled by MicroWindows.
+ */
+struct MW_UID_MESSAGE {
+ enum MW_INPUT_DEVICE_TYPE type; /* device type */
+ union {
+ /* fired when keyboard events are raised */
+ struct kbd_t {
+ unsigned short code; /* keycode or scancode */
+ unsigned char modifiers; /* key modifiers */
+ unsigned char mode; /* current Kbd mode */
+ } kbd;
+
+ /* fired when position events are raised, mouse, touch screen, etc */
+ struct pos_t {
+ unsigned short btns; /* indicates which buttons are pressed */
+ short x; /* x location */
+ short y; /* y location */
+ short z; /* z location, 0 for 2D */
+ } pos;
+
+ /* fired by a timer device periodically */
+ struct timer_t {
+ unsigned long frt; /* free running timer */
+ unsigned long seq; /* sequence number */
+ } tmr;
+ } m;
+};
+
+
+/*
+ * API for creating/closing/accessing the message queue used by the micro
+ * input device interface. All functions in this interface returns a
+ * zero ( 0 ) on success. One exception for that is the "read" routine
+ * that returns the number of bytes read. Negaive numbers indicate errors
+ *
+ * The implementation of the message queue for RTEMS uses a POSIX message
+ * queue interface. It should be very portable among systems with a POSIX
+ * support.
+ */
+
+/**
+ * This method creates the message queue that holds events from the
+ * input devices.
+ *
+ * @param[in] q_name is the name of the message queue
+ * @param[in] flags controls the behaviour of the queue
+ * @param[in] max_msgs specifies the maximum number of pending messages
+ *
+ * @note The message queue is from the Classic API.
+ *
+ * @return This method returns 0 on success and -1 on error.
+ */
+extern int uid_open_queue( const char *q_name, int flags, size_t max_msgs );
+
+/**
+ * This method closes the message queue and deletes it.
+ *
+ * @return This method returns 0 on success and -1 on error.
+ */
+extern int uid_close_queue( void );
+
+/**
+ * This method reads a message from the queue. It waits up to the specified
+ * timeout in miliseconds. A @a timeout of 0 is a poll.
+ *
+ * @param[in] m will be filled in with the received message
+ * @param[in] timeout is the maximum number of mulliseconds to wait
+ *
+ * @return This method returns 0 on success and -1 on error.
+ */
+extern int uid_read_message( struct MW_UID_MESSAGE *m, unsigned long timeout );
+
+/**
+ * This methods writes a message to the queue.
+ *
+ * @param[in] m is the message to send
+ *
+ * @return This method returns 0 on success and -1 on error.
+ */
+extern int uid_send_message( struct MW_UID_MESSAGE *m );
+
+/**
+ * This method registers the device associated with @a fd to
+ * to insert data to the queue
+ */
+extern int uid_register_device( int fd, const char *q_name );
+
+/* unregister device to stop adding messages to the queue */
+extern int uid_unregister_device( int fd );
+
+/* set the keyboard */
+extern int uid_set_kbd_mode( int fd, int mode, int *old_mode );
+
+/**
+ * This methods prints the specified UID message using printk
+ *
+ * @param[in] uid points to the message to print
+ */
+void uid_print_message(
+ struct MW_UID_MESSAGE *uid
+);
+
+/**
+ * This methods prints the specified UID message using your fprintf
+ * style method of choice.
+ *
+ * @param[in] context is a pointer to a data area which may be
+ * used by some print handlers
+ * @param[in] handler is the fprintf style method to invoke
+ * @param[in] uid points to the message to print
+ */
+void uid_print_message_with_plugin(
+ void *context,
+ rtems_printk_plugin_t handler,
+ struct MW_UID_MESSAGE *uid
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MW_UID_H */
diff --git a/cpukit/libmisc/fsmount/README b/cpukit/libmisc/fsmount/README
new file mode 100644
index 0000000000..88bfda62e7
--- /dev/null
+++ b/cpukit/libmisc/fsmount/README
@@ -0,0 +1,24 @@
+#
+#
+# fsmount information
+#
+# Author: Thomas Doerfler 02/07/2003
+#
+# README,v 1.1 1999/07/09 17:23:15 joel Exp
+#
+
+fsmount.c contains the function fsmount. It processes the
+fs table given as an parameter to create the listed mount points
+and mount the corresponding file systems to their mount points.
+See "c/src/tests/samples/fileio" for a sample on how to use this
+function.
+
+The field "report_reasons" specifies, what results of the mount point
+creation/mount operations should print to the console.
+
+The field "abort_reasons" specifies, what results of the mount point
+creation/mount operations should abort the function. Do not set the
+"abort_reasons" bit, unless you want to stop the processing of the
+fsmount table after the first successful mount.
+
+
diff --git a/cpukit/libmisc/fsmount/fsmount.c b/cpukit/libmisc/fsmount/fsmount.c
new file mode 100644
index 0000000000..1d82b94391
--- /dev/null
+++ b/cpukit/libmisc/fsmount/fsmount.c
@@ -0,0 +1,138 @@
+/**
+ * @file
+ *
+ * File system mount functions.
+ */
+
+/*===============================================================*\
+| Project: RTEMS fsmount |
++-----------------------------------------------------------------+
+| File: fsmount.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2003 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file contains the fsmount functions. These functions |
+| are used to mount a list of filesystems (and create their mount |
+| points before) |
+| |
+| 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. |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 02.07.03 creation doe |
+\*===============================================================*/
+
+#ifndef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/fsmount.h>
+#include <rtems/libio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int rtems_fsmount
+(
+/*-------------------------------------------------------------------------*\
+ | Purpose: |
+ | This function will create the mount points listed and mount the file |
+ | systems listed in the calling parameters |
+ +---------------------------------------------------------------------------+
+ | Input Parameters: |
+ \*-------------------------------------------------------------------------*/
+ const rtems_fstab_entry *fstab_ptr,
+ size_t fstab_count,
+ size_t *fail_idx
+ )
+/*-------------------------------------------------------------------------*\
+ | Return Value: |
+ | 0, if success, -1 and errno if failed |
+ \*=========================================================================*/
+{
+ int rc = 0;
+ int tmp_rc;
+ size_t fstab_idx = 0;
+ bool terminate = false;
+
+ /*
+ * scan through all fstab entries;
+ */
+ while (!terminate &&
+ (fstab_idx < fstab_count)) {
+ tmp_rc = 0;
+ /*
+ * create mount point
+ */
+ if (tmp_rc == 0) {
+ tmp_rc = rtems_mkdir(fstab_ptr->target, S_IRWXU | S_IRWXG | S_IRWXO);
+ if (tmp_rc != 0) {
+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNTPNT_CRTERR)) {
+ fprintf(stdout,"fsmount: creation of mount point \"%s\" failed: %s\n",
+ fstab_ptr->target,
+ strerror(errno));
+ }
+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNTPNT_CRTERR)) {
+ terminate = true;
+ rc = tmp_rc;
+ }
+ }
+ }
+ /*
+ * mount device to given mount point
+ */
+ if (tmp_rc == 0) {
+ tmp_rc = mount(fstab_ptr->source,
+ fstab_ptr->target,
+ fstab_ptr->type,
+ fstab_ptr->options,
+ NULL);
+ if (tmp_rc != 0) {
+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNT_FAILED)) {
+ fprintf(stdout,"fsmount: mounting of \"%s\" to"
+ " \"%s\" failed: %s\n",
+ fstab_ptr->source,
+ fstab_ptr->target,
+ strerror(errno));
+ }
+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNT_FAILED)) {
+ terminate = true;
+ rc = tmp_rc;
+ }
+ }
+ else {
+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNT_OK)) {
+ fprintf(stdout,"fsmount: mounting of \"%s\" to"
+ " \"%s\" succeeded\n",
+ fstab_ptr->source,
+ fstab_ptr->target);
+ }
+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNT_OK)) {
+ terminate = true;
+ }
+ }
+ }
+ /*
+ * proceed to next entry
+ */
+ if (!terminate) {
+ fstab_ptr++;
+ fstab_idx++;
+ }
+ }
+ if (fail_idx != NULL) {
+ *fail_idx = fstab_idx;
+ }
+ return rc;
+}
diff --git a/cpukit/libmisc/fsmount/fsmount.h b/cpukit/libmisc/fsmount/fsmount.h
new file mode 100644
index 0000000000..94c8508358
--- /dev/null
+++ b/cpukit/libmisc/fsmount/fsmount.h
@@ -0,0 +1,209 @@
+/**
+ * @file
+ *
+ * File system mount functions.
+ */
+
+/*===============================================================*\
+| Project: RTEMS fsmount |
++-----------------------------------------------------------------+
+| File: fsmount.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2003 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file contains the fsmount functions. These functions |
+| are used to mount a list of filesystems (and create their mount |
+| points before) |
+| |
+| 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. |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 02.07.03 creation doe |
+\*===============================================================*/
+
+#ifndef _FSMOUNT_H
+#define _FSMOUNT_H
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libcsupport.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup rtems_fstab File System Mount Support
+ *
+ * @{
+ */
+
+/**
+ * File system mount report and abort condition flags.
+ *
+ * The flags define, which conditions will cause a report during the mount
+ * process (via printf()) or abort the mount process.
+ *
+ * @see rtems_fstab_entry and rtems_fsmount().
+ */
+typedef enum {
+ /**
+ * No conditions.
+ */
+ RTEMS_FSTAB_NONE = 0U,
+
+ /**
+ * Complete mount process was successful.
+ */
+ RTEMS_FSTAB_OK = 0x1U,
+
+ /**
+ * Mount point creation failed.
+ */
+ RTEMS_FSTAB_ERROR_MOUNT_POINT = 0x2U,
+
+ /**
+ * File system mount failed.
+ */
+ RTEMS_FSTAB_ERROR_MOUNT = 0x4U,
+
+ /**
+ * Something failed.
+ */
+ RTEMS_FSTAB_ERROR = RTEMS_FSTAB_ERROR_MOUNT_POINT | RTEMS_FSTAB_ERROR_MOUNT,
+
+ /**
+ * Any condition.
+ */
+ RTEMS_FSTAB_ANY = RTEMS_FSTAB_OK | RTEMS_FSTAB_ERROR
+} rtems_fstab_conditions;
+
+/**
+ * File system table entry.
+ */
+typedef struct {
+ /**
+ * Source for the mount.
+ */
+ const char *source;
+
+ /**
+ * Target for the mount.
+ */
+ const char *target;
+
+ /**
+ * File system operations.
+ */
+ const char *type;
+
+ /**
+ * File system mount options.
+ */
+ rtems_filesystem_options_t options;
+
+ /**
+ * Report @ref rtems_fstab_conditions "condition flags".
+ */
+ uint16_t report_reasons;
+
+ /**
+ * Abort @ref rtems_fstab_conditions "condition flags".
+ */
+ uint16_t abort_reasons;
+} rtems_fstab_entry;
+
+/**
+ * Mounts the file systems listed in the file system mount table @a fstab of
+ * size @a size.
+ *
+ * Each file system will be mounted according to its table entry parameters.
+ * In case of an abort condition the corresponding table index will be reported
+ * in @a abort_index. The pointer @a abort_index may be @c NULL. The mount
+ * point paths will be created with rtems_mkdir() and need not exist
+ * beforehand.
+ *
+ * On success, zero is returned. On error, -1 is returned, and @c errno is set
+ * appropriately.
+ *
+ * @see rtems_bdpart_register_from_disk().
+ *
+ * The following example code tries to mount a FAT file system within a SD
+ * Card. Some cards do not have a partition table so at first it tries to find
+ * a file system inside the hole disk. If this is successful the mount process
+ * will be aborted because the @ref RTEMS_FSTAB_OK condition is true. If this
+ * did not work it tries to mount the file system inside the first partition.
+ * If this fails the mount process will not be aborted (this is already the
+ * last entry), but the last error status will be returned.
+ *
+ * @code
+ * #include <stdio.h>
+ * #include <string.h>
+ * #include <errno.h>
+ *
+ * #include <rtems.h>
+ * #include <rtems/bdpart.h>
+ * #include <rtems/error.h>
+ * #include <rtems/fsmount.h>
+ *
+ * static const rtems_fstab_entry fstab [] = {
+ * {
+ * .source = "/dev/sd-card-a",
+ * .target = "/mnt",
+ * .type = "dosfs",
+ * .options = RTEMS_FILESYSTEM_READ_WRITE,
+ * .report_reasons = RTEMS_FSTAB_ANY,
+ * .abort_reasons = RTEMS_FSTAB_OK
+ * }, {
+ * .source = "/dev/sd-card-a1",
+ * .target = "/mnt",
+ * .type = "dosfs",
+ * .options = RTEMS_FILESYSTEM_READ_WRITE,
+ * .report_reasons = RTEMS_FSTAB_ANY,
+ * .abort_reasons = RTEMS_FSTAB_NONE
+ * }
+ * };
+ *
+ * static void my_mount(void)
+ * {
+ * rtems_status_code sc = RTEMS_SUCCESSFUL;
+ * int rv = 0;
+ * size_t abort_index = 0;
+ *
+ * sc = rtems_bdpart_register_from_disk("/dev/sd-card-a");
+ * if (sc != RTEMS_SUCCESSFUL) {
+ * printf("read partition table failed: %s\n", rtems_status_text(sc));
+ * }
+ *
+ * rv = rtems_fsmount(fstab, sizeof(fstab) / sizeof(fstab [0]), &abort_index);
+ * if (rv != 0) {
+ * printf("mount failed: %s\n", strerror(errno));
+ * }
+ * printf("mount aborted at %zu\n", abort_index);
+ * }
+ * @endcode
+ */
+int rtems_fsmount( const rtems_fstab_entry *fstab, size_t size, size_t *abort_index);
+
+/** @} */
+
+typedef rtems_fstab_entry fstab_t;
+
+#define FSMOUNT_MNT_OK RTEMS_FSTAB_OK
+
+#define FSMOUNT_MNTPNT_CRTERR RTEMS_FSTAB_ERROR_MOUNT_POINT
+
+#define FSMOUNT_MNT_FAILED RTEMS_FSTAB_ERROR_MOUNT
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FSMOUNT_H */
diff --git a/cpukit/libmisc/monitor/README b/cpukit/libmisc/monitor/README
new file mode 100644
index 0000000000..d5a73da140
--- /dev/null
+++ b/cpukit/libmisc/monitor/README
@@ -0,0 +1,97 @@
+#
+# $Id$
+#
+
+monitor task
+
+The monitor task is an optional task that knows about RTEMS
+data structures and can print out information about them.
+It is a work-in-progress and needs many more commands, but
+is useful now.
+
+The monitor works best when it is the highest priority task,
+so all your other tasks should ideally be at some priority
+greater than 1.
+
+To use the monitor:
+-------------------
+
+ #include <rtems/monitor.h>
+
+ ...
+
+ rtems_monitor_init(0);
+
+ The parameter to rtems_monitor_init() tells the monitor whether
+ to suspend itself on startup. A value of 0 causes the monitor
+ to immediately enter command mode; a non-zero value causes the
+ monitor to suspend itself after creation and wait for explicit
+ wakeup.
+
+
+ rtems_monitor_wakeup();
+
+ wakes up a suspended monitor and causes it to reenter command mode.
+
+Monitor commands
+----------------
+
+ The monitor prompt is 'rtems> '.
+ Can abbreviate commands to "uniquity"
+ There is a 'help' command. Here is the output from various
+ help commands:
+
+ Commands (may be abbreviated)
+
+ help -- get this message or command specific help
+ task -- show task information
+ queue -- show message queue information
+ symbol -- show entries from symbol table
+ pause -- pause monitor for a specified number of ticks
+ fatal -- invoke a fatal RTEMS error
+
+ task [id [id ...] ]
+ display information about the specified tasks.
+ Default is to display information about all tasks on this node
+
+ queue [id [id ... ] ]
+ display information about the specified message queues
+ Default is to display information about all queues on this node
+
+ symbol [ symbolname [symbolname ... ] ]
+ display value associated with specified symbol.
+ Defaults to displaying all known symbols.
+
+ pause [ticks]
+ monitor goes to "sleep" for specified ticks (default is 1)
+ monitor will resume at end of period or if explicitly awakened
+
+ fatal [status]
+ Invoke 'rtems_fatal_error_occurred' with 'status'
+ (default is RTEMS_INTERNAL_ERROR)
+
+ continue
+ put the monitor to sleep waiting for an explicit wakeup from the
+ program running.
+
+
+Sample output from 'task' command
+---------------------------------
+
+ rtems> task
+ ID NAME PRIO STAT MODES EVENTS WAITID WAITARG NOTES
+ ------------------------------------------------------------------------
+ 00010001 UI1 2 READY P:T:nA NONE15: 0x40606348
+ 00010002 RMON 1 READY nP NONE15: 0x40604110
+
+ 'RMON' is the monitor itself, so we have 1 "user" task.
+ Its modes are P:T:nA which translate to:
+
+ preemptable
+ timesliced
+ no ASRS
+
+ It has no events.
+ It has a notepad value for notepad 15 which is 0x40606348
+ (this is the libc thread state)
+
diff --git a/cpukit/libmisc/monitor/mon-command.c b/cpukit/libmisc/monitor/mon-command.c
new file mode 100644
index 0000000000..b16c8f06c0
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-command.c
@@ -0,0 +1,244 @@
+/**
+ * @file
+ *
+ * @brief Command support routines for RTEMS monitor.
+ */
+
+/*
+ * $Id$
+ *
+ * 2001-01-30 KJO (vac4050@cae597.rsc.raytheon.com):
+ * Fixed rtems_monitor_command_lookup() to accept partial
+ * commands to uniqeness. Added support for setting
+ * the monitor prompt via an environment variable:
+ * RTEMS_MONITOR_PROMPT
+ *
+ * CCJ: 26-3-2000, adding command history and command line
+ * editing. This code is donated from My Right Boot and not
+ * covered by GPL, only the RTEMS license.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+static void
+rtems_monitor_show_help (
+ const rtems_monitor_command_entry_t *help_cmd,
+ int max_cmd_len
+)
+{
+#define MAX_HELP_LINE_LENGTH (75 - max_cmd_len - 2)
+
+ if (help_cmd && help_cmd->command)
+ {
+ const char *help = help_cmd->usage;
+ int help_len = strlen (help);
+ int spaces = max_cmd_len - strlen (help_cmd->command);
+ int show_this_line = 0;
+ int line_one = 1;
+ int c;
+
+ fprintf(stdout,"%s", help_cmd->command);
+
+ if (help_len == 0)
+ {
+ fprintf(stdout," - No help associated.\n");
+ return;
+ }
+
+ while (help_len)
+ {
+ fprintf(stdout,"%*c", spaces, ' ');
+
+ if (line_one)
+ fprintf(stdout," - ");
+
+ spaces = max_cmd_len + 2;
+ line_one = 0;
+
+ /*
+ * See if greater then the line length if so, work back
+ * from the end for a space, tab or lf or cr.
+ */
+
+ if (help_len > MAX_HELP_LINE_LENGTH)
+ {
+ for (show_this_line = MAX_HELP_LINE_LENGTH - 1;
+ show_this_line;
+ show_this_line--)
+ if ((help[show_this_line] == ' ') ||
+ (help[show_this_line] == '\n') ||
+ (help[show_this_line] == '\r'))
+ break;
+
+ /*
+ * If show_this_line is 0, it is a very long word !!
+ */
+
+ if (show_this_line == 0)
+ show_this_line = MAX_HELP_LINE_LENGTH - 1;
+ }
+ else
+ show_this_line = help_len;
+
+ for (c = 0; c < show_this_line; c++)
+ if ((help[c] == '\r') || (help[c] == '\n'))
+ show_this_line = c;
+ else
+ putchar (help[c]);
+
+ fprintf(stdout,"\n");
+
+ help += show_this_line;
+ help_len -= show_this_line;
+
+ /*
+ * Move past the line feeds or what ever else is being skipped.
+ */
+
+ while (help_len)
+ {
+ if ((*help != '\r') && (*help != '\n'))
+ break;
+
+ if (*help != ' ')
+ {
+ help++;
+ help_len--;
+ break;
+ }
+ help++;
+ help_len--;
+ }
+ }
+ }
+}
+
+void
+rtems_monitor_command_usage(
+ const rtems_monitor_command_entry_t *table,
+ const char *command_name
+)
+{
+ const rtems_monitor_command_entry_t *command = table;
+ int max_cmd_len = 0;
+
+ /* if first entry in table is a usage, then print it out */
+
+ if (command_name && (*command_name != '\0'))
+ {
+ command = rtems_monitor_command_lookup (command_name);
+
+ if (command)
+ rtems_monitor_show_help (command, strlen (command_name));
+ else
+ fprintf(stdout,"Unrecognised command; try just 'help'\n");
+ return;
+ }
+
+ /*
+ * Find the largest command size.
+ */
+
+ while (command)
+ {
+ int len = command->command ? strlen (command->command) : 0 ;
+
+ if (len > max_cmd_len)
+ max_cmd_len = len;
+
+ command = command->next;
+ }
+
+ max_cmd_len++;
+
+ command = table;
+
+ /*
+ * Now some nice formatting for the help.
+ */
+
+ while (command)
+ {
+ rtems_monitor_show_help (command, max_cmd_len);
+ command = command->next;
+ }
+}
+
+
+void rtems_monitor_help_cmd(
+ int argc,
+ char **argv,
+ const rtems_monitor_command_arg_t *command_arg,
+ bool verbose __attribute__((unused))
+)
+{
+ int arg;
+ const rtems_monitor_command_entry_t *command =
+ command_arg->monitor_command_entry;
+
+ if (argc == 1)
+ rtems_monitor_command_usage(command, 0);
+ else
+ {
+ for (arg = 1; argv[arg]; arg++)
+ rtems_monitor_command_usage(command, argv[arg]);
+ }
+}
+
+typedef struct {
+ const char *name;
+ size_t length;
+ const rtems_monitor_command_entry_t *match;
+} rtems_monitor_command_lookup_entry;
+
+static bool rtems_monitor_command_lookup_routine(
+ const rtems_monitor_command_entry_t *e,
+ void *arg
+)
+{
+ rtems_monitor_command_lookup_entry *le =
+ (rtems_monitor_command_lookup_entry *) arg;
+
+ /* Check name */
+ if (strncmp(e->command, le->name, le->length) == 0) {
+ /* Check for ambiguity */
+ if (le->match == NULL) {
+ le->match = e;
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * @brief Looks for a command with the name @a name in the list of registered
+ * commands.
+ *
+ * The parameter @a name must not be NULL.
+ *
+ * Returns the corresponding command entry or NULL if no command is found.
+ */
+const rtems_monitor_command_entry_t *rtems_monitor_command_lookup(
+ const char *name
+)
+{
+ rtems_monitor_command_lookup_entry e = {
+ .name = name,
+ .length = strlen( name),
+ .match = NULL
+ };
+
+ rtems_monitor_command_iterate(rtems_monitor_command_lookup_routine, &e);
+
+ return e.match;
+}
diff --git a/cpukit/libmisc/monitor/mon-config.c b/cpukit/libmisc/monitor/mon-config.c
new file mode 100644
index 0000000000..b067db7e2f
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-config.c
@@ -0,0 +1,136 @@
+/*
+ * RTEMS Config display support
+ *
+ * TODO
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+
+#define DATACOL 15
+#define CONTCOL DATACOL /* continued col */
+
+/*
+ * Fill in entire monitor config table
+ * for sending to a remote monitor or printing on the local system
+ */
+
+void
+rtems_monitor_config_canonical(
+ rtems_monitor_config_t *canonical_config,
+ void *config_void
+)
+{
+ rtems_configuration_table *c = (rtems_configuration_table *) config_void;
+ rtems_api_configuration_table *r = &Configuration_RTEMS_API;
+
+ canonical_config->work_space_start = c->work_space_start;
+ canonical_config->work_space_size = c->work_space_size;
+ canonical_config->maximum_tasks = r->maximum_tasks;
+ canonical_config->maximum_timers = r->maximum_timers;
+ canonical_config->maximum_semaphores = r->maximum_semaphores;
+ canonical_config->maximum_message_queues = r->maximum_message_queues;
+ canonical_config->maximum_partitions = r->maximum_partitions;
+ canonical_config->maximum_regions = r->maximum_regions;
+ canonical_config->maximum_ports = r->maximum_ports;
+ canonical_config->maximum_periods = r->maximum_periods;
+ canonical_config->maximum_extensions = c->maximum_extensions;
+ canonical_config->microseconds_per_tick = c->microseconds_per_tick;
+ canonical_config->ticks_per_timeslice = c->ticks_per_timeslice;
+ canonical_config->number_of_initialization_tasks = r->number_of_initialization_tasks;
+}
+
+/*
+ * This is easy, since there is only 1 (altho we could get them from
+ * other nodes...)
+ */
+
+void *
+rtems_monitor_config_next(
+ void *object_info __attribute__((unused)),
+ rtems_monitor_config_t *canonical_config __attribute__((unused)),
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = &Configuration;
+ int n = rtems_object_id_get_index(*next_id);
+
+ if (n >= 1)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ *next_id += 1;
+ return (void *) c;
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_config_dump_header(
+ bool verbose __attribute__((unused))
+)
+{
+ fprintf(stdout,"\
+INITIAL (startup) Configuration Info\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+
+int
+rtems_monitor_config_dump(
+ rtems_monitor_config_t *monitor_config,
+ bool verbose __attribute__((unused))
+)
+{
+ int length = 0;
+
+ length = 0;
+ length += fprintf(stdout,"WORKSPACE");
+ length += rtems_monitor_pad(DATACOL, length);
+ length += fprintf(stdout,"start: %p; size: 0x%" PRIx32 "\n",
+ monitor_config->work_space_start,
+ monitor_config->work_space_size);
+
+ length = 0;
+ length += fprintf(stdout,"TIME");
+ length += rtems_monitor_pad(DATACOL, length);
+ length += fprintf(stdout,"usec/tick: %" PRId32 "; tick/timeslice: %" PRId32 "; tick/sec: %" PRId32 "\n",
+ monitor_config->microseconds_per_tick,
+ monitor_config->ticks_per_timeslice,
+ 1000000 / monitor_config->microseconds_per_tick);
+
+ length = 0;
+ length += fprintf(stdout,"MAXIMUMS");
+ length += rtems_monitor_pad(DATACOL, length);
+ length += fprintf(stdout,"tasks: %" PRId32 "; timers: %" PRId32 "; sems: %" PRId32 "; que's: %" PRId32 "; ext's: %" PRId32 "\n",
+ monitor_config->maximum_tasks,
+ monitor_config->maximum_timers,
+ monitor_config->maximum_semaphores,
+ monitor_config->maximum_message_queues,
+ monitor_config->maximum_extensions);
+ length = 0;
+ length += rtems_monitor_pad(CONTCOL, length);
+ length += fprintf(stdout,"partitions: %" PRId32 "; regions: %" PRId32 "; ports: %" PRId32 "; periods: %" PRId32 "\n",
+ monitor_config->maximum_partitions,
+ monitor_config->maximum_regions,
+ monitor_config->maximum_ports,
+ monitor_config->maximum_periods);
+ return length;
+}
diff --git a/cpukit/libmisc/monitor/mon-driver.c b/cpukit/libmisc/monitor/mon-driver.c
new file mode 100644
index 0000000000..c5c2c468b9
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-driver.c
@@ -0,0 +1,144 @@
+/*
+ * RTEMS monitor IO (device drivers) support
+ *
+ * There are 2 "driver" things the monitor knows about.
+ *
+ * 1. Regular RTEMS drivers.
+ * This is a table indexed by major device number and
+ * containing driver entry points only.
+ *
+ * 2. Driver name table.
+ * A separate table of names for drivers.
+ * The table converts driver names to a major number
+ * as index into the driver table and a minor number
+ * for an argument to driver.
+ *
+ * Drivers are displayed with 'driver' command.
+ * Names are displayed with 'name' command.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+#include <inttypes.h>
+
+#define DATACOL 15
+#define CONTCOL DATACOL /* continued col */
+
+
+void
+rtems_monitor_driver_canonical(
+ rtems_monitor_driver_t *canonical_driver,
+ void *driver_void
+)
+{
+ rtems_driver_address_table *d = (rtems_driver_address_table *) driver_void;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->initialization,
+ (void *) d->initialization_entry);
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->open,
+ (void *) d->open_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->close,
+ (void *) d->close_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->read,
+ (void *) d->read_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->write,
+ (void *) d->write_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->control,
+ (void *) d->control_entry);
+}
+
+
+void *
+rtems_monitor_driver_next(
+ void *object_info __attribute__((unused)),
+ rtems_monitor_driver_t *canonical_driver,
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = &Configuration;
+ uint32_t n = rtems_object_id_get_index(*next_id);
+
+ if (n >= c->number_of_device_drivers)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * dummy up a fake id and name for this item
+ */
+
+ canonical_driver->id = n;
+ canonical_driver->name = rtems_build_name('-', '-', '-', '-');
+
+ *next_id += 1;
+ return (void *) (c->Device_driver_table + n);
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_driver_dump_header(
+ bool verbose __attribute__((unused))
+)
+{
+ fprintf(stdout,"\
+ Major Entry points\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+void
+rtems_monitor_driver_dump(
+ rtems_monitor_driver_t *monitor_driver,
+ bool verbose
+)
+{
+ uint32_t length = 0;
+
+#if defined(RTEMS_USE_16_BIT_OBJECT)
+ length += fprintf(stdout," %" PRId16 "", monitor_driver->id);
+#else
+ length += fprintf(stdout," %" PRId32 "", monitor_driver->id);
+#endif
+ length += rtems_monitor_pad(13, length);
+ length += fprintf(stdout,"init: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->initialization, verbose);
+ length += fprintf(stdout,"; control: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->control, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(13, length);
+
+ length += fprintf(stdout,"open: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->open, verbose);
+ length += fprintf(stdout,"; close: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->close, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(13, length);
+
+ length += fprintf(stdout,"read: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->read, verbose);
+ length += fprintf(stdout,"; write: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->write, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+}
diff --git a/cpukit/libmisc/monitor/mon-editor.c b/cpukit/libmisc/monitor/mon-editor.c
new file mode 100644
index 0000000000..1104b50185
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-editor.c
@@ -0,0 +1,643 @@
+/**
+ * @file
+ *
+ * @brief Command line editor for RTEMS monitor.
+ */
+
+/*
+ * $Id$
+ *
+ * 2001-01-30 KJO (vac4050@cae597.rsc.raytheon.com):
+ * Fixed rtems_monitor_command_lookup() to accept partial
+ * commands to uniqeness. Added support for setting
+ * the monitor prompt via an environment variable:
+ * RTEMS_MONITOR_PROMPT
+ *
+ * CCJ: 26-3-2000, adding command history and command line
+ * editing. This code is donated from My Right Boot and not
+ * covered by GPL, only the RTEMS license.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <termios.h>
+#include <unistd.h>
+
+#ifndef MONITOR_PROMPT
+#define MONITOR_PROMPT "rtems" /* will have '> ' appended */
+#endif
+
+/*
+ * Some key labels to define special keys.
+ */
+
+#define KEYS_EXTENDED (0x8000)
+#define KEYS_NORMAL_MASK (0x00ff)
+#define KEYS_INS (0)
+#define KEYS_DEL (1)
+#define KEYS_UARROW (2)
+#define KEYS_DARROW (3)
+#define KEYS_LARROW (4)
+#define KEYS_RARROW (5)
+#define KEYS_HOME (6)
+#define KEYS_END (7)
+#define KEYS_F1 (8)
+#define KEYS_F2 (9)
+#define KEYS_F3 (10)
+#define KEYS_F4 (11)
+#define KEYS_F5 (12)
+#define KEYS_F6 (13)
+#define KEYS_F7 (14)
+#define KEYS_F8 (15)
+#define KEYS_F9 (16)
+#define KEYS_F10 (17)
+
+#define RTEMS_COMMAND_BUFFER_SIZE (75)
+
+static char monitor_prompt[32];
+static char buffer[RTEMS_COMMAND_BUFFER_SIZE];
+static int pos;
+static int logged_in;
+
+/*
+ * History data.
+ */
+
+#define RTEMS_COMMAND_HISTORIES (20)
+
+static char history_buffer[RTEMS_COMMAND_HISTORIES][RTEMS_COMMAND_BUFFER_SIZE];
+static int history_pos[RTEMS_COMMAND_HISTORIES];
+static int history;
+static int history_next;
+
+/*
+ * 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_two[] =
+{
+ { '~', 0, KEYS_INS },
+ { 0, 0, 0 }
+};
+
+static const struct translation_table trans_three[] =
+{
+ { '~', 0, KEYS_DEL },
+ { 0, 0, 0 }
+};
+
+static const struct translation_table trans_tab_csi[] =
+{
+ { '2', trans_two, 0 },
+ { '3', trans_three, 0 },
+ { 'A', 0, KEYS_UARROW },
+ { 'B', 0, KEYS_DARROW },
+ { 'D', 0, KEYS_LARROW },
+ { 'C', 0, KEYS_RARROW },
+ { 'F', 0, KEYS_END },
+ { 'H', 0, KEYS_HOME },
+ { 0, 0, 0 }
+};
+
+static const struct translation_table trans_tab_O[] =
+{
+ { '1', 0, KEYS_F1 },
+ { '2', 0, KEYS_F2 },
+ { '3', 0, KEYS_F3 },
+ { '4', 0, KEYS_F4 },
+ { '5', 0, KEYS_F5 },
+ { '6', 0, KEYS_F6 },
+ { '7', 0, KEYS_F7 },
+ { '8', 0, KEYS_F8 },
+ { '9', 0, KEYS_F9 },
+ { ':', 0, KEYS_F10 },
+ { 'P', 0, KEYS_F1 },
+ { 'Q', 0, KEYS_F2 },
+ { 'R', 0, KEYS_F3 },
+ { 'S', 0, KEYS_F4 },
+ { 'T', 0, KEYS_F5 },
+ { 'U', 0, KEYS_F6 },
+ { 'V', 0, KEYS_F7 },
+ { 'W', 0, KEYS_F8 },
+ { 'X', 0, KEYS_F9 },
+ { 'Y', 0, 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 translation 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.
+ */
+
+static unsigned int
+rtems_monitor_getchar (void)
+{
+ const struct translation_table *translation = 0;
+ for (;;)
+ {
+ char c = getchar ();
+ 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 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;
+ }
+ }
+}
+
+/*
+ * The line editor with history.
+ */
+
+static int
+rtems_monitor_line_editor (
+ char *command
+)
+{
+ int repeating = 0;
+
+ memset (buffer, 0, RTEMS_COMMAND_BUFFER_SIZE);
+ history = history_next;
+ pos = 0;
+
+ if (!logged_in)
+ fprintf(stdout,"\nMonitor ready, press enter to login.\n\n");
+ else
+ fprintf(stdout,"%s $ ", monitor_prompt);
+
+ while (1)
+ {
+ unsigned int extended_key;
+ char c;
+
+ fflush (stdout);
+
+ extended_key = rtems_monitor_getchar ();
+ c = extended_key & KEYS_NORMAL_MASK;
+
+ /*
+ * Make the extended_key usable as a boolean.
+ */
+ extended_key &= ~KEYS_NORMAL_MASK;
+
+ if (!extended_key && !logged_in)
+ {
+ if (c == '\n')
+ {
+ logged_in = 1;
+ /*
+ * The prompt has changed from `>' to `$' to help know
+ * which version of the monitor code people are using.
+ */
+ fprintf(stdout,"%s $ ", monitor_prompt);
+ }
+ }
+ else
+ {
+ if (extended_key)
+ {
+ switch (c)
+ {
+ case KEYS_END:
+ fprintf(stdout,buffer + pos);
+ pos = (int) strlen (buffer);
+ break;
+
+ case KEYS_HOME:
+ fprintf(stdout,"\r%s $ ", monitor_prompt);
+ pos = 0;
+ break;
+
+ case KEYS_LARROW:
+ if (pos > 0)
+ {
+ pos--;
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_RARROW:
+ if ((pos < RTEMS_COMMAND_BUFFER_SIZE) && (buffer[pos] != '\0'))
+ {
+ putchar (buffer[pos]);
+ pos++;
+ }
+ break;
+
+ case KEYS_UARROW:
+ /*
+ * If we are moving up the histories then we need to save the working
+ * buffer.
+ */
+ if (history)
+ {
+ int end;
+ int bs;
+ if (history == history_next)
+ {
+ memcpy (history_buffer[history_next], buffer,
+ RTEMS_COMMAND_BUFFER_SIZE);
+ history_pos[history_next] = pos;
+ }
+ history--;
+ memcpy (buffer, history_buffer[history],
+ RTEMS_COMMAND_BUFFER_SIZE);
+ pos = history_pos[history];
+ fprintf(stdout,"\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
+ fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_DARROW:
+ if (history < history_next)
+ {
+ int end;
+ int bs;
+ history++;
+ memcpy (buffer, history_buffer[history],
+ RTEMS_COMMAND_BUFFER_SIZE);
+ pos = history_pos[history];
+ fprintf(stdout,"\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
+ fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_DEL:
+ if (buffer[pos] != '\0')
+ {
+ int end;
+ int bs;
+ strcpy (&buffer[pos], &buffer[pos + 1]);
+ fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (c)
+ {
+ case '\b':
+ case '\x7e':
+ case '\x7f':
+ if (pos > 0)
+ {
+ int bs;
+ pos--;
+ strcpy (buffer + pos, buffer + pos + 1);
+ fprintf(stdout,"\b%s \b", buffer + pos);
+ for (bs = 0; bs < ((int) strlen (buffer) - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case '\n':
+ /*
+ * Process the command.
+ */
+ fprintf(stdout,"\n");
+ repeating = 1;
+ /*
+ * Only process the history if we have a command and
+ *a history.
+ */
+ if (strlen (buffer))
+ {
+ if (history_next && (history == history_next))
+ {
+ /*
+ * Do not place the last command into the history
+ *if the same.
+ */
+ if (strcmp (history_buffer[history_next - 1], buffer))
+ repeating = 0;
+ }
+ else
+ repeating = 0;
+ }
+ if (!repeating)
+ {
+ memcpy (history_buffer[history_next], buffer,
+ RTEMS_COMMAND_BUFFER_SIZE);
+ history_pos[history_next] = pos;
+ if (history_next < (RTEMS_COMMAND_HISTORIES - 1))
+ history_next++;
+ else
+ {
+ memmove (history_buffer[0], history_buffer[1],
+ RTEMS_COMMAND_BUFFER_SIZE * (RTEMS_COMMAND_HISTORIES - 1));
+ memmove (&history_pos[0], &history_pos[1],
+ sizeof (history_pos[0]) * (RTEMS_COMMAND_HISTORIES - 1));
+ }
+ }
+ else
+ {
+#ifdef ENABLE_ENTER_REPEATS
+ if (history_next)
+ memcpy (buffer, history_buffer[history_next - 1],
+ RTEMS_COMMAND_BUFFER_SIZE);
+#endif
+ }
+ memmove (command, buffer, RTEMS_COMMAND_BUFFER_SIZE);
+ return repeating;
+ break;
+
+ default:
+ if ((pos < (RTEMS_COMMAND_BUFFER_SIZE - 1)) &&
+ (c >= ' ') && (c <= 'z'))
+ {
+ int end;
+ end = strlen (buffer);
+ if ((pos < end) && (end < RTEMS_COMMAND_BUFFER_SIZE))
+ {
+ int ch, bs;
+ for (ch = end; ch > pos; ch--)
+ buffer[ch] = buffer[ch - 1];
+ fprintf(stdout,buffer + pos);
+ for (bs = 0; bs < (end - pos + 1); bs++)
+ putchar ('\b');
+ }
+ buffer[pos++] = c;
+ if (pos > end)
+ buffer[pos] = '\0';
+ putchar (c);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * make_argv(cp): token-count
+ * Break up the command line in 'cp' into global argv[] and argc (return
+ * value).
+ */
+
+int
+rtems_monitor_make_argv(
+ char *cp,
+ int *argc_p,
+ char **argv)
+{
+ int argc = 0;
+
+ while ((cp = strtok(cp, " \t\n\r")))
+ {
+ argv[argc++] = cp;
+ cp = (char *) NULL;
+ }
+ argv[argc] = (char *) NULL; /* end of argv */
+
+ return *argc_p = argc;
+}
+
+
+/*
+ * Read and break up a monitor command
+ *
+ * We have to loop on the gets call, since it will return NULL under UNIX
+ * RTEMS when we get a signal (eg: SIGALRM).
+ */
+
+int
+rtems_monitor_command_read(char *command,
+ int *argc,
+ char **argv)
+{
+ char *env_prompt;
+
+ env_prompt = getenv("RTEMS_MONITOR_PROMPT");
+
+ /*
+ * put node number in the prompt if we are multiprocessing
+ */
+#if defined(RTEMS_MULTIPROCESSING)
+ if (!rtems_configuration_get_user_multiprocessing_table ())
+ sprintf (monitor_prompt, "%s",
+ (env_prompt == NULL) ? MONITOR_PROMPT: env_prompt);
+ else /* .... */
+#endif
+ if (rtems_monitor_default_node != rtems_monitor_node)
+ sprintf (monitor_prompt, "%" PRId32 "-%s-%" PRId32 "", rtems_monitor_node,
+ (env_prompt == NULL) ? MONITOR_PROMPT : env_prompt,
+ rtems_monitor_default_node);
+ else
+ sprintf (monitor_prompt, "%" PRId32 "-%s", rtems_monitor_node,
+ (env_prompt == NULL) ? MONITOR_PROMPT : env_prompt);
+
+ rtems_monitor_line_editor (command);
+
+ return rtems_monitor_make_argv (command, argc, argv);
+}
+
+/*
+ * Main monitor command loop
+ */
+
+void
+rtems_monitor_task(
+ rtems_task_argument monitor_flags
+)
+{
+ rtems_tcb *debugee = 0;
+ rtems_context *rp;
+#if (CPU_HARDWARE_FP == TRUE) || (CPU_SOFTWARE_FP == TRUE)
+ rtems_context_fp *fp;
+#endif
+ char command_buffer[513];
+ int argc;
+ char *argv[64];
+ bool verbose = false;
+ struct termios term;
+
+ /*
+ * Make the stdin stream characte not line based.
+ */
+
+ if (tcgetattr (STDIN_FILENO, &term) < 0)
+ {
+ fprintf(stdout,"rtems-monitor: cannot get terminal attributes.\n");
+ }
+ else
+ {
+ /*
+ * No echo, no canonical processing.
+ */
+
+ term.c_lflag &= ~(ECHO | ICANON | IEXTEN);
+
+ /*
+ * No sigint on BREAK, CR-to-NL off, input parity off,
+ * don't strip 8th bit on input, output flow control off
+ */
+
+ term.c_lflag &= ~(INPCK | ISTRIP | IXON);
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+
+ if (tcsetattr (STDIN_FILENO, TCSANOW, &term) < 0)
+ {
+ fprintf(stdout,"cannot set terminal attributes\n");
+ }
+ }
+
+ if (!(monitor_flags & RTEMS_MONITOR_NOSYMLOAD)) {
+ rtems_monitor_symbols_loadup();
+ }
+
+ if (monitor_flags & RTEMS_MONITOR_SUSPEND)
+ (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
+
+ for (;;)
+ {
+ const rtems_monitor_command_entry_t *command;
+
+ debugee = _Thread_Executing;
+ rp = &debugee->Registers;
+#if (CPU_HARDWARE_FP == TRUE) || (CPU_SOFTWARE_FP == TRUE)
+ fp = debugee->fp_context; /* possibly 0 */
+#endif
+
+ if (0 == rtems_monitor_command_read(command_buffer, &argc, argv))
+ continue;
+ if (argc < 1
+ || (command = rtems_monitor_command_lookup(argv [0])) == 0) {
+ /* no command */
+ fprintf(stdout,"Unrecognised command; try 'help'\n");
+ continue;
+ }
+
+ command->command_function(argc, argv, &command->command_arg, verbose);
+
+ fflush(stdout);
+ }
+}
+
+
+void
+rtems_monitor_kill(void)
+{
+ if (rtems_monitor_task_id)
+ rtems_task_delete(rtems_monitor_task_id);
+ rtems_monitor_task_id = 0;
+
+ rtems_monitor_server_kill();
+}
+
+void
+rtems_monitor_init(
+ uint32_t monitor_flags
+)
+{
+ rtems_status_code status;
+
+ rtems_monitor_kill();
+
+ status = rtems_task_create(RTEMS_MONITOR_NAME,
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE * 2,
+ RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &rtems_monitor_task_id);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor task");
+ return;
+ }
+
+ rtems_monitor_node = rtems_object_id_get_node(rtems_monitor_task_id);
+ rtems_monitor_default_node = rtems_monitor_node;
+
+ rtems_monitor_server_init(monitor_flags);
+
+ if (!(monitor_flags & RTEMS_MONITOR_NOTASK)) {
+ /*
+ * Start the monitor task itself
+ */
+ status = rtems_task_start(
+ rtems_monitor_task_id, rtems_monitor_task, monitor_flags);
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_error(status, "could not start monitor");
+ return;
+ }
+ }
+}
diff --git a/cpukit/libmisc/monitor/mon-extension.c b/cpukit/libmisc/monitor/mon-extension.c
new file mode 100644
index 0000000000..c6a9f72040
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-extension.c
@@ -0,0 +1,102 @@
+/*
+ * RTEMS Monitor extension support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+void
+rtems_monitor_extension_canonical(
+ rtems_monitor_extension_t *canonical_extension,
+ void *extension_void
+)
+{
+ Extension_Control *rtems_extension = (Extension_Control *) extension_void;
+ rtems_extensions_table *e = &rtems_extension->Extension.Callouts;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_create,
+ (void *) e->thread_create);
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_start,
+ (void *) e->thread_start);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_restart,
+ (void *) e->thread_restart);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_delete,
+ (void *) e->thread_delete);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_tswitch,
+ (void *) e->thread_switch);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_begin,
+ (void *) e->thread_begin);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_exitted,
+ (void *) e->thread_exitted);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_fatal,
+ (void *) e->fatal);
+}
+
+void
+rtems_monitor_extension_dump_header(
+ bool verbose __attribute__((unused))
+)
+{
+ fprintf(stdout,"\
+ ID NAME\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+
+/*
+ * Dump out the canonical form
+ */
+
+void
+rtems_monitor_extension_dump(
+ rtems_monitor_extension_t *monitor_extension,
+ bool verbose
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_dump_id(monitor_extension->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_extension->id);
+
+ length += rtems_monitor_pad(18, length);
+ length += fprintf(stdout,"create: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_create, verbose);
+ length += fprintf(stdout,"; start: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_start, verbose);
+ length += fprintf(stdout,"; restart: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_restart, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(18, length);
+ length += fprintf(stdout,"delete: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_delete, verbose);
+ length += fprintf(stdout,"; switch: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_tswitch, verbose);
+ length += fprintf(stdout,"; begin: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_begin, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(18, length);
+ length += fprintf(stdout,"exitted: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_exitted, verbose);
+ length += fprintf(stdout,"; fatal: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_fatal, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/mon-itask.c b/cpukit/libmisc/monitor/mon-itask.c
new file mode 100644
index 0000000000..6dab51a768
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-itask.c
@@ -0,0 +1,121 @@
+/*
+ * RTEMS Monitor init task support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+
+/*
+ * As above, but just for init tasks
+ */
+void
+rtems_monitor_init_task_canonical(
+ rtems_monitor_init_task_t *canonical_itask,
+ void *itask_void
+)
+{
+ rtems_initialization_tasks_table *rtems_itask = itask_void;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_itask->entry,
+ (void *) rtems_itask->entry_point);
+
+ canonical_itask->argument = rtems_itask->argument;
+ canonical_itask->stack_size = rtems_itask->stack_size;
+ canonical_itask->priority = rtems_itask->initial_priority;
+ canonical_itask->modes = rtems_itask->mode_set;
+ canonical_itask->attributes = rtems_itask->attribute_set;
+}
+
+void *
+rtems_monitor_init_task_next(
+ void *object_info __attribute__((unused)),
+ rtems_monitor_init_task_t *canonical_init_task,
+ rtems_id *next_id
+)
+{
+ rtems_initialization_tasks_table *itask;
+ uint32_t n = rtems_object_id_get_index(*next_id);
+
+ if (n >= Configuration_RTEMS_API.number_of_initialization_tasks)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ itask = Configuration_RTEMS_API.User_initialization_tasks_table + n;
+
+ /*
+ * dummy up a fake id and name for this item
+ */
+
+ canonical_init_task->id = n;
+ canonical_init_task->name = itask->name;
+
+ *next_id += 1;
+ return (void *) itask;
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_init_task_dump_header(
+ bool verbose __attribute__((unused))
+)
+{
+ fprintf(stdout,"\
+ # NAME ENTRY ARGUMENT PRIO MODES ATTRIBUTES STACK SIZE\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+/*
+ */
+
+void
+rtems_monitor_init_task_dump(
+ rtems_monitor_init_task_t *monitor_itask,
+ bool verbose
+)
+{
+ int length = 0;
+
+ length += rtems_monitor_dump_decimal(monitor_itask->id);
+
+ length += rtems_monitor_pad(7, length);
+ length += rtems_monitor_dump_name(monitor_itask->id);
+
+ length += rtems_monitor_pad(14, length);
+ length += rtems_monitor_symbol_dump(&monitor_itask->entry, verbose);
+
+ length += rtems_monitor_pad(25, length);
+ length += fprintf(stdout,"%" PRId32 " [0x%" PRIx32 "]",
+ monitor_itask->argument, monitor_itask->argument);
+
+ length += rtems_monitor_pad(39, length);
+ length += rtems_monitor_dump_priority(monitor_itask->priority);
+
+ length += rtems_monitor_pad(46, length);
+ length += rtems_monitor_dump_modes(monitor_itask->modes);
+
+ length += rtems_monitor_pad(54, length);
+ length += rtems_monitor_dump_attributes(monitor_itask->attributes);
+
+ length += rtems_monitor_pad(66, length);
+ length += fprintf(stdout,"%" PRId32 " [0x%" PRIx32 "]",
+ monitor_itask->stack_size, monitor_itask->stack_size);
+
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/mon-manager.c b/cpukit/libmisc/monitor/mon-manager.c
new file mode 100644
index 0000000000..9e71addfae
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-manager.c
@@ -0,0 +1,55 @@
+/*
+ * RTEMS Monitor "manager" support.
+ * Used to traverse object (chain) lists and print them out.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+/*
+ * "next" routine for all objects that are RTEMS manager objects
+ */
+
+void *
+rtems_monitor_manager_next(
+ void *table_void,
+ void *canonical,
+ rtems_id *next_id
+)
+{
+ Objects_Information *table = table_void;
+ rtems_monitor_generic_t *copy;
+ Objects_Control *object = 0;
+ Objects_Locations location;
+
+ /*
+ * When we are called, it must be local
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( ! _Objects_Is_local_id(*next_id) )
+ goto done;
+#endif
+
+ object = _Objects_Get_next(table, *next_id, &location, next_id);
+
+ if (object)
+ {
+ copy = (rtems_monitor_generic_t *) canonical;
+ copy->id = object->id;
+ copy->name = object->name.name_u32;
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+done:
+#endif
+ return object;
+}
diff --git a/cpukit/libmisc/monitor/mon-monitor.c b/cpukit/libmisc/monitor/mon-monitor.c
new file mode 100644
index 0000000000..88f3d49eb3
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-monitor.c
@@ -0,0 +1,529 @@
+/*
+ * RTEMS monitor main body
+ *
+ * TODO:
+ * add stuff to RTEMS api
+ * rtems_get_name(id)
+ * rtems_get_type(id)
+ * rtems_build_id(node, type, num)
+ * Add a command to dump out info about an arbitrary id when
+ * types are added to id's
+ * rtems> id idnum
+ * idnum: node n, object: whatever, id: whatever
+ * allow id's to be specified as n:t:id, where 'n:t' is optional
+ * should have a separate monitor FILE stream (ala the debugger)
+ * remote request/response stuff should be cleaned up
+ * maybe we can use real rpc??
+ * 'info' command to print out:
+ * interrupt stack location, direction and size
+ * floating point config stuff
+ * interrupt config stuff
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <rtems/monitor.h>
+
+/* set by trap handler */
+extern rtems_tcb *debugger_interrupted_task;
+extern rtems_context *debugger_interrupted_task_context;
+extern uint32_t debugger_trap;
+
+/*
+ * Various id's for the monitor
+ * They need to be public variables for access by other agencies
+ * such as debugger and remote servers'
+ */
+
+rtems_id rtems_monitor_task_id;
+
+uint32_t rtems_monitor_node; /* our node number */
+uint32_t rtems_monitor_default_node; /* current default for commands */
+
+/*
+ * The rtems symbol table
+ */
+
+rtems_symbol_table_t *rtems_monitor_symbols;
+
+/*
+ * The top-level commands
+ */
+
+static const rtems_monitor_command_entry_t rtems_monitor_commands[] = {
+ { "config",
+ "Show the system configuration.",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_CONFIG },
+ &rtems_monitor_commands[1],
+ },
+ { "itask",
+ "List init tasks for the system",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_INIT_TASK },
+ &rtems_monitor_commands[2],
+ },
+ { "mpci",
+ "Show the MPCI system configuration, if configured.",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_MPCI },
+ &rtems_monitor_commands[3],
+ },
+ { "pause",
+ "Monitor goes to \"sleep\" for specified ticks (default is 1). "
+ "Monitor will resume at end of period or if explicitly awakened\n"
+ " pause [ticks]",
+ 0,
+ rtems_monitor_pause_cmd,
+ { 0 },
+ &rtems_monitor_commands[4],
+ },
+ { "continue",
+ "Put the monitor to sleep waiting for an explicit wakeup from the "
+ "program running.\n",
+ 0,
+ rtems_monitor_continue_cmd,
+ { 0 },
+ &rtems_monitor_commands[5],
+ },
+ { "go",
+ "Alias for 'continue'",
+ 0,
+ rtems_monitor_continue_cmd,
+ { 0 },
+ &rtems_monitor_commands[6],
+ },
+ { "symbol",
+ "Display value associated with specified symbol. "
+ "Defaults to displaying all known symbols.\n"
+ " symbol [ symbolname [symbolname ... ] ]",
+ 0,
+ rtems_monitor_symbol_cmd,
+ { .symbol_table = &rtems_monitor_symbols },
+ &rtems_monitor_commands[7],
+ },
+ { "extension",
+ "Display information about specified extensions. "
+ "Default is to display information about all extensions on this node.\n"
+ " extension [id [id ...] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_EXTENSION },
+ &rtems_monitor_commands[8],
+ },
+ { "task",
+ "Display information about the specified tasks. "
+ "Default is to display information about all tasks on this node.\n"
+ " task [id [id ...] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_TASK },
+ &rtems_monitor_commands[9],
+ },
+ { "queue",
+ "Display information about the specified message queues. "
+ "Default is to display information about all queues on this node.\n"
+ " queue [id [id ... ] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_QUEUE },
+ &rtems_monitor_commands[10],
+ },
+ { "sema",
+ "sema [id [id ... ] ]\n"
+ " display information about the specified semaphores\n"
+ " Default is to display information about all semaphores on this node\n"
+ ,
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_SEMAPHORE },
+ &rtems_monitor_commands[11],
+ },
+ { "region",
+ "region [id [id ... ] ]\n"
+ " display information about the specified regions\n"
+ " Default is to display information about all regions on this node\n"
+ ,
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_REGION },
+ &rtems_monitor_commands[12],
+ },
+ { "part",
+ "part [id [id ... ] ]\n"
+ " display information about the specified partitions\n"
+ " Default is to display information about all partitions on this node\n"
+ ,
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_PARTITION },
+ &rtems_monitor_commands[13],
+ },
+ { "object",
+ "Display information about specified RTEMS objects. "
+ "Object id's must include 'type' information. "
+ "(which may normally be defaulted)\n"
+ " object [id [id ...] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_INVALID },
+ &rtems_monitor_commands[14],
+ },
+ { "driver",
+ "Display the RTEMS device driver table.\n"
+ " driver [ major [ major ... ] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_DRIVER },
+ &rtems_monitor_commands[15],
+ },
+ { "dname",
+ "Displays information about named drivers.\n",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_DNAME },
+ &rtems_monitor_commands[16],
+ },
+ { "exit",
+ "Invoke 'rtems_fatal_error_occurred' with 'status' "
+ "(default is RTEMS_SUCCESSFUL)\n"
+ " exit [status]",
+ 0,
+ rtems_monitor_fatal_cmd,
+ { .status_code = RTEMS_SUCCESSFUL },
+ &rtems_monitor_commands[17],
+ },
+ { "fatal",
+ "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
+ " fatal [status]",
+ 0,
+ rtems_monitor_fatal_cmd,
+ { .status_code = RTEMS_TASK_EXITTED }, /* exit value */
+ &rtems_monitor_commands[18],
+ },
+ { "quit",
+ "Alias for 'exit'\n",
+ 0,
+ rtems_monitor_fatal_cmd,
+ { .status_code = RTEMS_SUCCESSFUL }, /* exit value */
+ &rtems_monitor_commands[19],
+ },
+ { "reset",
+ "(SW)Resets the System.",
+ 0,
+ rtems_monitor_reset_cmd,
+ { 0 },
+ &rtems_monitor_commands[20],
+ },
+#if defined(RTEMS_MULTIPROCESSING)
+ { "node",
+ "Specify default node number for commands that take id's.\n"
+ " node [ node number ]",
+ 0,
+ rtems_monitor_node_cmd,
+ { 0 },
+ &rtems_monitor_commands[21],
+ },
+ #define RTEMS_MONITOR_POSIX_NEXT 22
+#else
+ #define RTEMS_MONITOR_POSIX_NEXT 21
+#endif
+#ifdef RTEMS_POSIX_API
+ { "pthread",
+ "Display information about the specified pthreads. "
+ "Default is to display information about all pthreads on this node.\n"
+ " pthread [id [id ...] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_PTHREAD },
+ &rtems_monitor_commands[RTEMS_MONITOR_POSIX_NEXT],
+ },
+ #define RTEMS_MONITOR_DEBUGGER_NEXT (RTEMS_MONITOR_POSIX_NEXT + 1)
+#else
+ #define RTEMS_MONITOR_DEBUGGER_NEXT RTEMS_MONITOR_POSIX_NEXT
+#endif
+#ifdef CPU_INVOKE_DEBUGGER
+ { "debugger",
+ "Enter the debugger, if possible. "
+ "A continue from the debugger will return to the monitor.\n",
+ 0,
+ rtems_monitor_debugger_cmd,
+ { 0 },
+ &rtems_monitor_commands[RTEMS_MONITOR_DEBUGGER_NEXT],
+ },
+#endif
+ { "help",
+ "Provide information about commands. "
+ "Default is show basic command summary.\n"
+ "help [ command [ command ] ]",
+ 0,
+ rtems_monitor_help_cmd,
+ { .monitor_command_entry = rtems_monitor_commands },
+ NULL
+ }
+};
+
+/*
+ * All registered commands.
+ */
+
+static const rtems_monitor_command_entry_t *rtems_monitor_registered_commands =
+ &rtems_monitor_commands [0];
+
+
+rtems_status_code
+rtems_monitor_suspend(rtems_interval timeout)
+{
+ rtems_event_set event_set;
+ rtems_status_code status;
+
+ status = rtems_event_receive(MONITOR_WAKEUP_EVENT,
+ RTEMS_DEFAULT_OPTIONS,
+ timeout,
+ &event_set);
+ return status;
+}
+
+void __attribute__((weak))
+rtems_monitor_reset_cmd(
+ int argc,
+ char **argv,
+ const rtems_monitor_command_arg_t* command_arg,
+ bool verbose
+)
+{
+
+}
+
+void
+rtems_monitor_wakeup(void)
+{
+ rtems_status_code status;
+
+ status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
+}
+
+void rtems_monitor_debugger_cmd(
+ int argc __attribute__((unused)),
+ char **argv __attribute__((unused)),
+ const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused))
+)
+{
+#ifdef CPU_INVOKE_DEBUGGER
+ CPU_INVOKE_DEBUGGER;
+#endif
+}
+
+void rtems_monitor_pause_cmd(
+ int argc,
+ char **argv,
+ const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused))
+)
+{
+ if (argc == 1)
+ rtems_monitor_suspend(1);
+ else
+ rtems_monitor_suspend(strtoul(argv[1], 0, 0));
+}
+
+void rtems_monitor_fatal_cmd(
+ int argc,
+ char **argv,
+ const rtems_monitor_command_arg_t *command_arg,
+ bool verbose __attribute__((unused))
+)
+{
+ if (argc == 1)
+ rtems_fatal_error_occurred(command_arg->status_code);
+ else
+ rtems_fatal_error_occurred(strtoul(argv[1], 0, 0));
+}
+
+void rtems_monitor_continue_cmd(
+ int argc __attribute__((unused)),
+ char **argv __attribute__((unused)),
+ const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused))
+)
+{
+ rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
+}
+
+#if defined(RTEMS_MULTIPROCESSING)
+void rtems_monitor_node_cmd(
+ int argc,
+ char **argv,
+ const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused))
+)
+{
+ uint32_t new_node = rtems_monitor_default_node;
+
+ switch (argc) {
+ case 1: /* no node, just set back to ours */
+ new_node = rtems_monitor_node;
+ break;
+
+ case 2:
+ new_node = strtoul(argv[1], 0, 0);
+ break;
+
+ default:
+ fprintf(stdout,"invalid syntax, try 'help node'\n");
+ break;
+ }
+
+ if ((new_node >= 1) &&
+ _Configuration_MP_table &&
+ (new_node <= _Configuration_MP_table->maximum_nodes))
+ rtems_monitor_default_node = new_node;
+}
+#endif
+
+
+/*
+ * Function: rtems_monitor_symbols_loadup
+ *
+ * Description:
+ * Create and load the monitor's symbol table.
+ * We are reading the output format of 'gnm' which looks like this:
+ *
+ * 400a7068 ? _Rate_monotonic_Information
+ * 400a708c ? _Thread_Dispatch_disable_level
+ * 400a7090 ? _Configuration_Table
+ *
+ * We ignore the type field.
+ *
+ * Side Effects:
+ * Creates and fills in 'rtems_monitor_symbols' table
+ *
+ * TODO
+ * there should be a BSP #define or something like that
+ * to do this; Assuming stdio is crazy.
+ * Someday this should know BFD
+ * Maybe we could get objcopy to just copy the symbol areas
+ * and copy that down.
+ *
+ */
+
+void
+rtems_monitor_symbols_loadup(void)
+{
+ FILE *fp;
+ char buffer[128];
+
+ if (rtems_monitor_symbols)
+ rtems_symbol_table_destroy(rtems_monitor_symbols);
+
+ rtems_monitor_symbols = rtems_symbol_table_create();
+ if (rtems_monitor_symbols == 0)
+ return;
+
+ fp = fopen("symbols", "r");
+
+ if (fp == 0)
+ return;
+
+ while (fgets(buffer, sizeof(buffer) - 1, fp))
+ {
+ char *symbol;
+ char *value;
+ char *ignored_type;
+
+ value = strtok(buffer, " \t\n");
+ ignored_type = strtok(0, " \t\n");
+ symbol = strtok(0, " \t\n");
+
+ if (symbol && ignored_type && value)
+ {
+ rtems_symbol_t *sp;
+ sp = rtems_symbol_create(rtems_monitor_symbols,
+ symbol,
+ (uint32_t) strtoul(value, 0, 16));
+ if (sp == 0)
+ {
+ fprintf(stdout,"could not define symbol '%s'\n", symbol);
+ goto done;
+ }
+ }
+ else
+ {
+ fprintf(stdout,"parsing error on '%s'\n", buffer);
+ goto done;
+ }
+ }
+
+done:
+ fclose(fp);
+ return;
+}
+
+/*
+ * User registered commands.
+ */
+
+int
+rtems_monitor_insert_cmd (
+ rtems_monitor_command_entry_t *command
+)
+{
+ const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;
+
+ /* Reject empty commands */
+ if (command->command == NULL) {
+ return 0;
+ }
+
+ /* Reject command if already present */
+ while (e->next != NULL) {
+ if (e->command != NULL && strcmp(command->command, e->command) == 0) {
+ return 0;
+ }
+ e = e->next;
+ }
+
+ /* Prepend new command */
+ command->next = rtems_monitor_registered_commands;
+ rtems_monitor_registered_commands = command;
+
+ return 1;
+}
+
+/**
+ * @brief Iterates through all registerd commands.
+ *
+ * For each command the interation routine @a routine is called with the
+ * command entry and the user provided argument @a arg. It is guaranteed that
+ * the command name and function are not NULL.
+ */
+void rtems_monitor_command_iterate(
+ rtems_monitor_per_command_routine routine,
+ void *arg
+)
+{
+ const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;
+
+ while (e != NULL) {
+ if (e->command != NULL && e->command_function != NULL) {
+ if (!routine(e, arg)) {
+ break;
+ }
+ }
+ e = e->next;
+ }
+}
diff --git a/cpukit/libmisc/monitor/mon-mpci.c b/cpukit/libmisc/monitor/mon-mpci.c
new file mode 100644
index 0000000000..ab77431241
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-mpci.c
@@ -0,0 +1,163 @@
+/*
+ * RTEMS MPCI Config display support
+ *
+ * TODO
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+#include <inttypes.h>
+
+#define DATACOL 15
+
+/*
+ * Fill in entire monitor config table
+ * for sending to a remote monitor or printing on the local system
+ */
+
+void
+rtems_monitor_mpci_canonical(
+ rtems_monitor_mpci_t *canonical_mpci,
+ void *config_void
+)
+{
+ rtems_configuration_table *c = &Configuration;
+ rtems_multiprocessing_table *m;
+ rtems_mpci_table *mt;
+
+ m = c->User_multiprocessing_table;
+ if (m == 0)
+ return;
+ mt = m->User_mpci_table;
+
+ canonical_mpci->node = m->node;
+ canonical_mpci->maximum_nodes = m->maximum_nodes;
+ canonical_mpci->maximum_global_objects = m->maximum_global_objects;
+ canonical_mpci->maximum_proxies = m->maximum_proxies;
+
+ canonical_mpci->default_timeout = mt->default_timeout;
+ canonical_mpci->maximum_packet_size = mt->maximum_packet_size;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->initialization,
+ (void *) mt->initialization);
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->get_packet,
+ (void *) mt->get_packet);
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->return_packet,
+ (void *) mt->return_packet);
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->send_packet,
+ (void *) mt->send_packet);
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->receive_packet,
+ (void *) mt->receive_packet);
+}
+
+/*
+ * This is easy, since there is only 1 (altho we could get them from
+ * other nodes...)
+ */
+
+void *
+rtems_monitor_mpci_next(
+ void *object_info,
+ rtems_monitor_mpci_t *canonical_mpci,
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = &Configuration;
+ int n = rtems_object_id_get_index(*next_id);
+
+ if (n >= 1)
+ goto failed;
+
+ if ( ! c->User_multiprocessing_table)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ *next_id += 1;
+ return (void *) c;
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_mpci_dump_header(
+ bool verbose
+)
+{
+ fprintf(stdout,"\
+ max max max default max\n\
+ node nodes globals proxies timeout pktsize\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+
+void
+rtems_monitor_mpci_dump(
+ rtems_monitor_mpci_t *monitor_mpci,
+ bool verbose
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_pad(2, length);
+ length += fprintf(stdout," %" PRId32 , monitor_mpci->node);
+ length += rtems_monitor_pad(11, length);
+ length += fprintf(stdout,"%" PRId32, monitor_mpci->maximum_nodes);
+
+ length += rtems_monitor_pad(18, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->maximum_global_objects);
+
+ length += rtems_monitor_pad(28, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->maximum_proxies);
+
+ length += rtems_monitor_pad(37, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->default_timeout);
+
+ length += rtems_monitor_pad(46, length);
+ length += rtems_monitor_dump_decimal((uint32_t) monitor_mpci->maximum_packet_size);
+
+ fprintf(stdout,"\n");
+ length = 0;
+ length += rtems_monitor_pad(DATACOL, length);
+
+ length += fprintf(stdout,"init: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->initialization, verbose);
+
+ fprintf(stdout,"\n");
+ length = 0;
+ length += rtems_monitor_pad(DATACOL, length);
+
+ length += fprintf(stdout,"get: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->get_packet, verbose);
+ length += fprintf(stdout,"; return: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->return_packet, verbose);
+
+ fprintf(stdout,"\n");
+ length = 0;
+ length += rtems_monitor_pad(DATACOL, length);
+
+ length += fprintf(stdout,"send: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->send_packet, verbose);
+ length += fprintf(stdout,"; receive: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->receive_packet, verbose);
+
+ fprintf(stdout,"\n");
+ length = 0;
+}
diff --git a/cpukit/libmisc/monitor/mon-network.c b/cpukit/libmisc/monitor/mon-network.c
new file mode 100644
index 0000000000..52c0cd9852
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-network.c
@@ -0,0 +1,342 @@
+/*
+ * 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$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <rtems/rtems_bsdnet.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/sockio.h>
+#include <net/route.h>
+
+
+void mon_ifconfig(int argc, char *argv[],
+ uint32_t command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ 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;
+ }
+ 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;
+ }
+ if (inet_pton(AF_INET, argv[cur_idx+1], &netmask.sin_addr) < 0) {
+ printf("bad netmask: %s\n", argv[cur_idx]);
+ return;
+ }
+ 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;
+ }
+ if (inet_pton(AF_INET, argv[cur_idx+1], &broadcast.sin_addr) < 0) {
+ printf("bad broadcast: %s\n", argv[cur_idx]);
+ return;
+ }
+ 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;
+ }
+ if (inet_pton(AF_INET, argv[cur_idx+1], &dstaddr.sin_addr) < 0) {
+ printf("bad pointopoint: %s\n", argv[cur_idx]);
+ return;
+ }
+
+ f_ptp = 1;
+ cur_idx += 1;
+ } else {
+ printf("Bad parameter: %s\n", argv[cur_idx]);
+ return;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+ }
+
+ if (f_bcast) {
+ rc = rtems_bsdnet_ifconfig(iface, SIOCSIFBRDADDR, &broadcast);
+ if (rc < 0) {
+ printf("Could not set broadcast: %s\n", strerror(errno));
+ return;
+ }
+ }
+
+ if (f_ptp) {
+ rc = rtems_bsdnet_ifconfig(iface, SIOCSIFDSTADDR, &dstaddr);
+ if (rc < 0) {
+ printf("Could not set destination address: %s\n", strerror(errno));
+ return;
+ }
+ 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;
+ }
+ }
+
+ 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;
+ }
+}
+
+
+
+void mon_route(int argc, char *argv[],
+ uint32_t command_arg __attribute__((unused)),
+ bool verbose __attribute__((unused)))
+{
+ 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;
+ }
+
+ 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;
+ }
+
+ if (argc < 3) {
+ printf("not enough arguments\n");
+ return;
+ }
+
+ 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;
+ }
+
+ if (argc < 4) {
+ printf("not enough arguments\n");
+ return;
+ }
+
+ 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;
+ }
+ 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;
+ }
+ f_gw = 1;
+ inet_pton(AF_INET, argv[cur_idx + 1], &netmask.sin_addr);
+ cur_idx += 1;
+ } else {
+ printf("Unknown argument: %s\n", argv[cur_idx]);
+ return;
+ }
+ 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");
+ }
+}
diff --git a/cpukit/libmisc/monitor/mon-object.c b/cpukit/libmisc/monitor/mon-object.c
new file mode 100644
index 0000000000..96b2a85f8d
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-object.c
@@ -0,0 +1,423 @@
+/*
+ * RTEMS Monitor "object" support.
+ *
+ * Used to traverse object lists and print them out.
+ * An object can be an RTEMS object (chain based stuff) or
+ * a "misc" object such as a device driver.
+ *
+ * Each object has its own file in this directory (eg: extension.c)
+ * That file provides routines to convert a "native" structure
+ * to its canonical form, print a canonical structure, etc.
+ *
+ * TODO:
+ * should allow for non-numeric id's???
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+#if defined(RTEMS_POSIX_API)
+ #include <rtems/posix/pthread.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+#include <string.h> /* memcpy() */
+
+#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
+
+/*
+ * add:
+ * next
+ */
+
+static const rtems_monitor_object_info_t rtems_monitor_object_info[] =
+{
+ { RTEMS_MONITOR_OBJECT_CONFIG,
+ (void *) 0,
+ sizeof(rtems_monitor_config_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_config_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_config_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_config_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_config_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_MPCI,
+ (void *) 0,
+#if defined(RTEMS_MULTIPROCESSING)
+ sizeof(rtems_monitor_mpci_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_mpci_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_mpci_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_mpci_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_mpci_dump,
+#else
+ 0,
+ (rtems_monitor_object_next_fn) 0,
+ (rtems_monitor_object_canonical_fn) 0,
+ (rtems_monitor_object_dump_header_fn) 0,
+ (rtems_monitor_object_dump_fn) 0,
+#endif
+ },
+ { RTEMS_MONITOR_OBJECT_INIT_TASK,
+ (void *) 0,
+ sizeof(rtems_monitor_init_task_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_init_task_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_init_task_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_init_task_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_init_task_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_TASK,
+ (void *) &_RTEMS_tasks_Information,
+ sizeof(rtems_monitor_task_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_task_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_task_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_task_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_QUEUE,
+ (void *) &_Message_queue_Information,
+ sizeof(rtems_monitor_queue_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_queue_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_queue_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_queue_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_SEMAPHORE,
+ (void *) &_Semaphore_Information,
+ sizeof(rtems_monitor_sema_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_sema_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_sema_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_sema_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_REGION,
+ (void *) &_Region_Information,
+ sizeof(rtems_monitor_region_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_region_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_region_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_region_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_PARTITION,
+ (void *) &_Partition_Information,
+ sizeof(rtems_monitor_part_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_part_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_part_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_part_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_EXTENSION,
+ (void *) &_Extension_Information,
+ sizeof(rtems_monitor_extension_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_extension_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_extension_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_extension_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_DRIVER,
+ (void *) 0,
+ sizeof(rtems_monitor_driver_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_driver_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_driver_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_driver_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_driver_dump,
+ },
+#if defined(RTEMS_POSIX_API)
+ { RTEMS_MONITOR_OBJECT_PTHREAD,
+ (void *) &_POSIX_Threads_Information,
+ sizeof(rtems_monitor_task_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_task_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_task_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_task_dump,
+ },
+#endif
+};
+
+/*
+ * Allow id's to be specified without the node number or
+ * type for convenience.
+ */
+
+rtems_id
+rtems_monitor_id_fixup(
+ rtems_id id,
+ uint32_t default_node,
+ rtems_monitor_object_type_t type
+)
+{
+ uint32_t node;
+
+ node = rtems_object_id_get_node(id);
+ if (node == 0)
+ {
+ if (rtems_object_id_get_class(id) != OBJECTS_CLASSIC_NO_CLASS)
+ type = rtems_object_id_get_class(id);
+
+ id = rtems_build_id(
+ OBJECTS_CLASSIC_API,
+ type,
+ default_node,
+ rtems_object_id_get_index(id)
+ );
+ }
+ return id;
+}
+
+
+const rtems_monitor_object_info_t *
+rtems_monitor_object_lookup(
+ rtems_monitor_object_type_t type
+)
+{
+ const rtems_monitor_object_info_t *p;
+ for (p = &rtems_monitor_object_info[0];
+ p < &rtems_monitor_object_info[NUMELEMS(rtems_monitor_object_info)];
+ p++)
+ {
+ if (p->type == type)
+ return p;
+ }
+ return 0;
+}
+
+rtems_id
+rtems_monitor_object_canonical_next_remote(
+ rtems_monitor_object_type_t type,
+ rtems_id id,
+ void *canonical
+)
+{
+ rtems_id next_id;
+ rtems_status_code status;
+ rtems_monitor_server_request_t request;
+ rtems_monitor_server_response_t response;
+
+ /*
+ * Send request
+ */
+
+ request.command = RTEMS_MONITOR_SERVER_CANONICAL;
+ request.argument0 = (uint32_t) type;
+ request.argument1 = (uint32_t) id;
+
+ status = rtems_monitor_server_request(
+ rtems_object_id_get_node(id), &request, &response);
+ if (status != RTEMS_SUCCESSFUL)
+ goto failed;
+
+ /*
+ * process response
+ */
+
+ next_id = (rtems_id) response.result0;
+ if (next_id != RTEMS_OBJECT_ID_FINAL)
+ (void) memcpy(canonical, &response.payload, response.result1);
+
+ return next_id;
+
+failed:
+ return RTEMS_OBJECT_ID_FINAL;
+
+}
+
+
+rtems_id
+rtems_monitor_object_canonical_next(
+ const rtems_monitor_object_info_t *info,
+ rtems_id id,
+ void *canonical
+)
+{
+ rtems_id next_id;
+ void *raw_item;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( ! _Objects_Is_local_id(id) ) {
+ next_id = rtems_monitor_object_canonical_next_remote(
+ info->type,
+ id,
+ canonical
+ );
+ } else
+#endif
+ {
+ next_id = id;
+
+ raw_item = (void *) info->next(
+ info->object_information,
+ canonical,
+ &next_id
+ );
+
+ if (raw_item) {
+ info->canonical(canonical, raw_item);
+ _Thread_Enable_dispatch();
+ }
+ }
+ return next_id;
+}
+
+
+/*
+ * this is routine server invokes locally to get the type
+ */
+
+rtems_id
+rtems_monitor_object_canonical_get(
+ rtems_monitor_object_type_t type,
+ rtems_id id,
+ void *canonical,
+ size_t *size_p
+)
+{
+ const rtems_monitor_object_info_t *info;
+ rtems_id next_id;
+
+ *size_p = 0;
+
+ info = rtems_monitor_object_lookup(type);
+
+ if (info == 0)
+ return RTEMS_OBJECT_ID_FINAL;
+
+ next_id = rtems_monitor_object_canonical_next(info, id, canonical);
+ *size_p = info->size;
+
+ return next_id;
+}
+
+
+void
+rtems_monitor_object_dump_1(
+ const rtems_monitor_object_info_t *info,
+ rtems_id id,
+ bool verbose
+)
+{
+ rtems_id next_id;
+ rtems_monitor_union_t canonical;
+
+ if ((next_id = rtems_monitor_object_canonical_next(
+ info,
+ id,
+ &canonical)) != RTEMS_OBJECT_ID_FINAL)
+ {
+ /*
+ * If the one we actually got is the one we wanted, then
+ * print it out.
+ * For ones that have an id field, this works fine,
+ * for all others, always dump it out.
+ *
+ * HACK: the way we determine whether there is an id is a hack.
+ *
+ * by the way: the reason we try to not have an id, is that some
+ * of the canonical structures are almost too big for shared
+ * memory driver (eg: mpci)
+ */
+
+ if ((info->next != rtems_monitor_manager_next) ||
+ (id == canonical.generic.id))
+ info->dump(&canonical, verbose);
+ }
+}
+
+void
+rtems_monitor_object_dump_all(
+ const rtems_monitor_object_info_t *info,
+ bool verbose
+)
+{
+ rtems_id next_id;
+ rtems_monitor_union_t canonical;
+
+ next_id = RTEMS_OBJECT_ID_INITIAL(OBJECTS_CLASSIC_API, info->type, rtems_monitor_default_node);
+
+ while ((next_id = rtems_monitor_object_canonical_next(
+ info,
+ next_id,
+ &canonical)) != RTEMS_OBJECT_ID_FINAL)
+ {
+ info->dump(&canonical, verbose);
+ }
+}
+
+void
+rtems_monitor_object_cmd(
+ int argc,
+ char **argv,
+ const rtems_monitor_command_arg_t *command_arg,
+ bool verbose
+)
+{
+ int arg;
+ const rtems_monitor_object_info_t *info = 0;
+ rtems_monitor_object_type_t type;
+
+ /* what is the default type? */
+ type = command_arg->monitor_object;
+
+ if (argc == 1)
+ {
+ if (type == RTEMS_MONITOR_OBJECT_INVALID)
+ {
+ fprintf(stdout,"A type must be specified to \"dump all\"\n");
+ goto done;
+ }
+
+ info = rtems_monitor_object_lookup(type);
+ if (info == 0)
+ goto not_found;
+
+ if (info->dump_header)
+ info->dump_header(verbose);
+ rtems_monitor_object_dump_all(info, verbose);
+ }
+ else
+ {
+ uint32_t default_node = rtems_monitor_default_node;
+ rtems_monitor_object_type_t last_type = RTEMS_MONITOR_OBJECT_INVALID;
+ rtems_id id;
+
+ for (arg=1; argv[arg]; arg++)
+ {
+ id = (rtems_id) strtoul(argv[arg], 0, 16);
+ id = rtems_monitor_id_fixup(id, default_node, type);
+ type = (rtems_monitor_object_type_t) rtems_object_id_get_class(id);
+
+ /*
+ * Allow the item type to change in the middle
+ * of the command. If the type changes, then
+ * just dump out a new header and keep on going.
+ */
+ if (type != last_type)
+ {
+ info = rtems_monitor_object_lookup(type);
+ if (info == 0)
+ goto not_found;
+
+ if (info->dump_header)
+ info->dump_header(verbose);
+ }
+
+ if (info == 0)
+ {
+not_found: fprintf(stdout,"Invalid or unsupported type %d\n", type);
+ goto done;
+ }
+
+ rtems_monitor_object_dump_1(info, id, verbose);
+
+ default_node = rtems_object_id_get_node(id);
+
+ last_type = type;
+ }
+ }
+done:
+ return;
+}
diff --git a/cpukit/libmisc/monitor/mon-part.c b/cpukit/libmisc/monitor/mon-part.c
new file mode 100644
index 0000000000..72aff6921f
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-part.c
@@ -0,0 +1,72 @@
+/*
+ * RTEMS Monitor partition support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include "monitor.h"
+#include <rtems/rtems/attr.inl>
+#include <stdio.h>
+#include <string.h> /* memcpy() */
+
+void
+rtems_monitor_part_canonical(
+ rtems_monitor_part_t *canonical_part,
+ void *part_void
+)
+{
+ Partition_Control *rtems_part = (Partition_Control *) part_void;
+
+ canonical_part->attribute = rtems_part->attribute_set;
+ canonical_part->start_addr = rtems_part->starting_address;
+ canonical_part->length = rtems_part->length;
+ canonical_part->buf_size = rtems_part->buffer_size;
+ canonical_part->used_blocks = rtems_part->number_of_used_blocks;
+}
+
+
+void
+rtems_monitor_part_dump_header(
+ bool verbose __attribute__((unused))
+)
+{
+ printf("\
+ ID NAME ATTR STARTADDR LENGTH BUF_SIZE USED_BLOCKS\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 1234
+ 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+/*
+ */
+
+void
+rtems_monitor_part_dump(
+ rtems_monitor_part_t *monitor_part,
+ bool verbose __attribute__((unused))
+)
+{
+ int length = 0;
+
+ length += rtems_monitor_dump_id(monitor_part->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_part->id);
+ length += rtems_monitor_pad(18, length);
+ length += rtems_monitor_dump_attributes(monitor_part->attribute);
+ length += rtems_monitor_pad(30, length);
+ length += rtems_monitor_dump_addr(monitor_part->start_addr);
+ length += rtems_monitor_pad(40, length);
+ length += rtems_monitor_dump_hex(monitor_part->length);
+ length += rtems_monitor_pad(50, length);
+ length += rtems_monitor_dump_hex(monitor_part->buf_size);
+ length += rtems_monitor_pad(60, length);
+ length += rtems_monitor_dump_hex(monitor_part->used_blocks);
+ printf("\n");
+}
+
diff --git a/cpukit/libmisc/monitor/mon-prmisc.c b/cpukit/libmisc/monitor/mon-prmisc.c
new file mode 100644
index 0000000000..32ee6711b4
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-prmisc.c
@@ -0,0 +1,259 @@
+/*
+ * Print misc stuff for the monitor dump routines
+ * Each routine returns the number of characters it output.
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <rtems/assoc.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+void
+rtems_monitor_separator(void)
+{
+ fprintf(stdout,"------------------------------------------------------------------------------\n");
+}
+
+uint32_t
+rtems_monitor_pad(
+ uint32_t destination_column,
+ uint32_t current_column
+)
+{
+ int pad_length;
+
+ if (destination_column <= current_column)
+ pad_length = 1;
+ else
+ pad_length = destination_column - current_column;
+
+ return fprintf(stdout,"%*s", pad_length, "");
+}
+
+int
+rtems_monitor_dump_decimal(uint32_t num)
+{
+ return fprintf(stdout,"%4" PRId32, num);
+}
+
+int
+rtems_monitor_dump_addr(void *addr)
+{
+ return fprintf(stdout,"0x%p", addr);
+}
+
+int
+rtems_monitor_dump_hex(uint32_t num)
+{
+ return fprintf(stdout,"0x%" PRIx32, num);
+}
+
+int
+rtems_monitor_dump_assoc_bitfield(
+ const rtems_assoc_t *ap,
+ const char *separator,
+ uint32_t value
+ )
+{
+ uint32_t b;
+ uint32_t length = 0;
+ const char *name;
+
+ for (b = 1; b; b <<= 1)
+ if (b & value)
+ {
+ if (length)
+ length += fprintf(stdout,"%s", separator);
+
+ name = rtems_assoc_name_by_local(ap, b);
+
+ if (name)
+ length += fprintf(stdout,"%s", name);
+ else
+ length += fprintf(stdout,"0x%" PRIx32, b);
+ }
+
+ return length;
+}
+
+int
+rtems_monitor_dump_id(rtems_id id)
+{
+#if defined(RTEMS_USE_16_BIT_OBJECT)
+ return fprintf(stdout,"%08" PRIx16, id);
+#else
+ return fprintf(stdout,"%08" PRIx32, id);
+#endif
+}
+
+int
+rtems_monitor_dump_name(rtems_id id)
+{
+ char name_buffer[18] = "????";
+
+ rtems_object_get_name( id, sizeof(name_buffer), name_buffer );
+
+ return fprintf( stdout, name_buffer );
+}
+
+int
+rtems_monitor_dump_priority(rtems_task_priority priority)
+{
+ return fprintf(stdout,"%3" PRId32, priority);
+}
+
+
+static const rtems_assoc_t rtems_monitor_state_assoc[] = {
+ { "DORM", STATES_DORMANT, 0 },
+ { "SUSP", STATES_SUSPENDED, 0 },
+ { "TRANS", STATES_TRANSIENT, 0 },
+ { "DELAY", STATES_DELAYING, 0 },
+ { "Wtime", STATES_WAITING_FOR_TIME, 0 },
+ { "Wbuf", STATES_WAITING_FOR_BUFFER, 0 },
+ { "Wseg", STATES_WAITING_FOR_SEGMENT, 0 },
+ { "Wmsg" , STATES_WAITING_FOR_MESSAGE, 0 },
+ { "Wevnt", STATES_WAITING_FOR_EVENT, 0 },
+ { "Wsem", STATES_WAITING_FOR_SEMAPHORE, 0 },
+ { "Wmutex", STATES_WAITING_FOR_MUTEX, 0 },
+ { "Wcvar", STATES_WAITING_FOR_CONDITION_VARIABLE, 0 },
+ { "Wjatx", STATES_WAITING_FOR_JOIN_AT_EXIT, 0 },
+ { "Wrpc", STATES_WAITING_FOR_RPC_REPLY, 0 },
+ { "WRATE", STATES_WAITING_FOR_PERIOD, 0 },
+ { "Wsig", STATES_WAITING_FOR_SIGNAL, 0 },
+ { "Wbar", STATES_WAITING_FOR_BARRIER, 0 },
+ { "Wrwlk", STATES_WAITING_FOR_RWLOCK, 0 },
+ { "Wisig", STATES_INTERRUPTIBLE_BY_SIGNAL, 0 },
+ { 0, 0, 0 },
+};
+
+int
+rtems_monitor_dump_state(States_Control state)
+{
+ int length = 0;
+
+ if (state == STATES_READY) /* assoc doesn't deal with this as it is 0 */
+ length += fprintf(stdout,"READY");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_state_assoc,
+ ":",
+ state);
+ return length;
+}
+
+static const rtems_assoc_t rtems_monitor_attribute_assoc[] = {
+ { "GL", RTEMS_GLOBAL, 0 },
+ { "PR", RTEMS_PRIORITY, 0 },
+ { "FL", RTEMS_FLOATING_POINT, 0 },
+ { "BI", RTEMS_BINARY_SEMAPHORE, 0 },
+ { "SB", RTEMS_SIMPLE_BINARY_SEMAPHORE, 0 },
+ { "IN", RTEMS_INHERIT_PRIORITY, 0 },
+ { "CE", RTEMS_PRIORITY_CEILING, 0 },
+ { "AR", RTEMS_BARRIER_AUTOMATIC_RELEASE, 0 },
+ { "ST", RTEMS_SYSTEM_TASK, 0 },
+ { 0, 0, 0 },
+};
+
+int
+rtems_monitor_dump_attributes(rtems_attribute attributes)
+{
+ int length = 0;
+
+ if (attributes == RTEMS_DEFAULT_ATTRIBUTES) /* value is 0 */
+ length += fprintf(stdout,"DEFAULT");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_attribute_assoc,
+ ":",
+ attributes);
+ return length;
+}
+
+static const rtems_assoc_t rtems_monitor_modes_assoc[] = {
+ { "nP", RTEMS_NO_PREEMPT, 0 },
+ { "T", RTEMS_TIMESLICE, 0 },
+ { "nA", RTEMS_NO_ASR, 0 },
+ { 0, 0, 0 },
+};
+
+int
+rtems_monitor_dump_modes(rtems_mode modes)
+{
+ uint32_t length = 0;
+
+ if (modes == RTEMS_DEFAULT_MODES) /* value is 0 */
+ length += fprintf(stdout,"P:T:nA");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_modes_assoc,
+ ":",
+ modes);
+ return length;
+}
+
+static const rtems_assoc_t rtems_monitor_events_assoc[] = {
+ { "0", RTEMS_EVENT_0, 0 },
+ { "1", RTEMS_EVENT_1, 0 },
+ { "2", RTEMS_EVENT_2, 0 },
+ { "3", RTEMS_EVENT_3, 0 },
+ { "4", RTEMS_EVENT_4, 0 },
+ { "5", RTEMS_EVENT_5, 0 },
+ { "6", RTEMS_EVENT_6, 0 },
+ { "7", RTEMS_EVENT_7, 0 },
+ { "8", RTEMS_EVENT_8, 0 },
+ { "9", RTEMS_EVENT_9, 0 },
+ { "10", RTEMS_EVENT_10, 0 },
+ { "11", RTEMS_EVENT_11, 0 },
+ { "12", RTEMS_EVENT_12, 0 },
+ { "13", RTEMS_EVENT_13, 0 },
+ { "14", RTEMS_EVENT_14, 0 },
+ { "15", RTEMS_EVENT_15, 0 },
+ { "16", RTEMS_EVENT_16, 0 },
+ { "17", RTEMS_EVENT_17, 0 },
+ { "18", RTEMS_EVENT_18, 0 },
+ { "19", RTEMS_EVENT_19, 0 },
+ { "20", RTEMS_EVENT_20, 0 },
+ { "21", RTEMS_EVENT_21, 0 },
+ { "22", RTEMS_EVENT_22, 0 },
+ { "23", RTEMS_EVENT_23, 0 },
+ { "24", RTEMS_EVENT_24, 0 },
+ { "25", RTEMS_EVENT_25, 0 },
+ { "26", RTEMS_EVENT_26, 0 },
+ { "27", RTEMS_EVENT_27, 0 },
+ { "28", RTEMS_EVENT_28, 0 },
+ { "29", RTEMS_EVENT_29, 0 },
+ { "30", RTEMS_EVENT_30, 0 },
+ { "31", RTEMS_EVENT_31, 0 },
+ { 0, 0, 0 },
+};
+
+int
+rtems_monitor_dump_events(rtems_event_set events)
+{
+ if (events == EVENT_SETS_NONE_PENDING) /* value is 0 */
+ return fprintf(stdout," NONE ");
+
+ return fprintf(stdout,"%08" PRIx32, events);
+}
+
+int
+rtems_monitor_dump_notepad(uint32_t *notepad)
+{
+ int length = 0;
+ int i;
+
+ for (i=0; i < RTEMS_NUMBER_NOTEPADS; i++)
+ if (notepad[i])
+ length += fprintf(stdout,"%d: 0x%" PRIx32, i, notepad[i]);
+
+ return length;
+}
diff --git a/cpukit/libmisc/monitor/mon-queue.c b/cpukit/libmisc/monitor/mon-queue.c
new file mode 100644
index 0000000000..4237b01780
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-queue.c
@@ -0,0 +1,68 @@
+/*
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+void
+rtems_monitor_queue_canonical(
+ rtems_monitor_queue_t *canonical_queue,
+ void *queue_void
+)
+{
+ Message_queue_Control *rtems_queue = (Message_queue_Control *) queue_void;
+
+ canonical_queue->attributes = rtems_queue->attribute_set;
+ canonical_queue->maximum_message_size = rtems_queue->message_queue.maximum_message_size;
+ canonical_queue->maximum_pending_messages = rtems_queue->message_queue.maximum_pending_messages;
+ canonical_queue->number_of_pending_messages = rtems_queue->message_queue.number_of_pending_messages;
+}
+
+void
+rtems_monitor_queue_dump_header(
+ bool verbose __attribute__((unused))
+)
+{
+ fprintf(stdout,"\
+ ID NAME ATTRIBUTES PEND MAXPEND MAXSIZE\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+
+/*
+ * Dump out the "next" queue indicated by 'id'.
+ * Returns next one to check.
+ * Returns RTEMS_OBJECT_ID_FINAL when all done
+ */
+
+void
+rtems_monitor_queue_dump(
+ rtems_monitor_queue_t *monitor_queue,
+ bool verbose __attribute__((unused))
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_dump_id(monitor_queue->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_queue->id);
+ length += rtems_monitor_pad(19, length);
+ length += rtems_monitor_dump_attributes(monitor_queue->attributes);
+ length += rtems_monitor_pad(31, length);
+ length += rtems_monitor_dump_decimal(monitor_queue->number_of_pending_messages);
+ length += rtems_monitor_pad(39, length);
+ length += rtems_monitor_dump_decimal(monitor_queue->maximum_pending_messages);
+ length += rtems_monitor_pad(48, length);
+ length += rtems_monitor_dump_decimal(monitor_queue->maximum_message_size);
+
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/mon-region.c b/cpukit/libmisc/monitor/mon-region.c
new file mode 100644
index 0000000000..271cbf82f4
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-region.c
@@ -0,0 +1,73 @@
+/*
+ * RTEMS Monitor region support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include "monitor.h"
+#include <rtems/rtems/attr.inl>
+#include <stdio.h>
+#include <string.h> /* memcpy() */
+
+void
+rtems_monitor_region_canonical(
+ rtems_monitor_region_t *canonical_region,
+ void *region_void
+)
+{
+ Region_Control *rtems_region = (Region_Control *) region_void;
+
+ canonical_region->attribute = rtems_region->attribute_set;
+ canonical_region->start_addr = rtems_region->starting_address;
+ canonical_region->length = rtems_region->length;
+ canonical_region->page_size = rtems_region->page_size;
+ canonical_region->max_seg_size = rtems_region->maximum_segment_size;
+ canonical_region->used_blocks = rtems_region->number_of_used_blocks;
+}
+
+
+void
+rtems_monitor_region_dump_header(
+ bool verbose __attribute__((unused))
+)
+{
+ printf("\
+ ID NAME ATTR STARTADDR LENGTH PAGE_SIZE USED_BLOCKS\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 1234
+ 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+/*
+ */
+
+void
+rtems_monitor_region_dump(
+ rtems_monitor_region_t *monitor_region,
+ bool verbose __attribute__((unused))
+)
+{
+ int length = 0;
+
+ length += rtems_monitor_dump_id(monitor_region->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_region->id);
+ length += rtems_monitor_pad(18, length);
+ length += rtems_monitor_dump_attributes(monitor_region->attribute);
+ length += rtems_monitor_pad(30, length);
+ length += rtems_monitor_dump_addr(monitor_region->start_addr);
+ length += rtems_monitor_pad(40, length);
+ length += rtems_monitor_dump_hex(monitor_region->length);
+ length += rtems_monitor_pad(50, length);
+ length += rtems_monitor_dump_hex(monitor_region->page_size);
+ length += rtems_monitor_pad(60, length);
+ length += rtems_monitor_dump_hex(monitor_region->used_blocks);
+ printf("\n");
+}
+
diff --git a/cpukit/libmisc/monitor/mon-sema.c b/cpukit/libmisc/monitor/mon-sema.c
new file mode 100644
index 0000000000..276601c04c
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-sema.c
@@ -0,0 +1,84 @@
+/*
+ * RTEMS Monitor semaphore support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include "monitor.h"
+#include <rtems/rtems/attr.inl>
+#include <stdio.h>
+#include <string.h> /* memcpy() */
+
+void
+rtems_monitor_sema_canonical(
+ rtems_monitor_sema_t *canonical_sema,
+ void *sema_void
+)
+{
+ Semaphore_Control *rtems_sema = (Semaphore_Control *) sema_void;
+
+ canonical_sema->attribute = rtems_sema->attribute_set;
+ canonical_sema->priority_ceiling =
+ rtems_sema->Core_control.mutex.Attributes.priority_ceiling;
+
+ canonical_sema->holder_id =
+ rtems_sema->Core_control.mutex.holder_id;
+
+ if (_Attributes_Is_counting_semaphore(canonical_sema->attribute)) {
+ /* we have a counting semaphore */
+ canonical_sema->cur_count =
+ rtems_sema->Core_control.semaphore.count;
+
+ canonical_sema->max_count =
+ rtems_sema->Core_control.semaphore.Attributes.maximum_count;
+ }
+ else {
+ /* we have a binary semaphore (mutex) */
+ canonical_sema->cur_count = rtems_sema->Core_control.mutex.lock;
+ canonical_sema->max_count = 1; /* mutex is either 0 or 1 */
+ }
+}
+
+
+void
+rtems_monitor_sema_dump_header(
+ bool verbose __attribute__((unused))
+)
+{
+ printf("\
+ ID NAME ATTR PRICEIL CURR_CNT HOLDID \n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 1234
+ 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+/*
+ */
+
+void
+rtems_monitor_sema_dump(
+ rtems_monitor_sema_t *monitor_sema,
+ bool verbose __attribute__((unused))
+)
+{
+ int length = 0;
+
+ length += rtems_monitor_dump_id(monitor_sema->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_sema->id);
+ length += rtems_monitor_pad(18, length);
+ length += rtems_monitor_dump_attributes(monitor_sema->attribute);
+ length += rtems_monitor_pad(30, length);
+ length += rtems_monitor_dump_priority(monitor_sema->priority_ceiling);
+ length += rtems_monitor_pad(38, length);
+ length += rtems_monitor_dump_decimal(monitor_sema->cur_count);
+ length += rtems_monitor_pad(47, length);
+ length += rtems_monitor_dump_id(monitor_sema->holder_id);
+ printf("\n");
+}
diff --git a/cpukit/libmisc/monitor/mon-server.c b/cpukit/libmisc/monitor/mon-server.c
new file mode 100644
index 0000000000..03bc1932b2
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-server.c
@@ -0,0 +1,309 @@
+/*
+ * RTEMS monitor server (handles requests for info from RTEMS monitors
+ * running on other nodes)
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rtems/monitor.h>
+
+/*
+ * Various id's for the server
+ */
+
+rtems_id rtems_monitor_server_task_id;
+rtems_id rtems_monitor_server_request_queue_id; /* our server */
+rtems_id *rtems_monitor_server_request_queue_ids; /* all servers */
+rtems_id rtems_monitor_server_response_queue_id; /* our server */
+
+
+/*
+ * Send a request to a server task
+ */
+
+rtems_status_code
+rtems_monitor_server_request(
+ uint32_t server_node,
+ rtems_monitor_server_request_t *request,
+ rtems_monitor_server_response_t *response
+)
+{
+ rtems_id server_id;
+ rtems_status_code status;
+ size_t size;
+
+ /*
+ * What is id of monitor on target node?
+ * Look it up if we don't know it yet.
+ */
+
+ server_id = rtems_monitor_server_request_queue_ids[server_node];
+ if (server_id == 0)
+ {
+ status = rtems_message_queue_ident(RTEMS_MONITOR_QUEUE_NAME,
+ server_node,
+ &server_id);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "ident of remote server failed");
+ goto done;
+ }
+
+ rtems_monitor_server_request_queue_ids[server_node] = server_id;
+ }
+
+ request->return_id = rtems_monitor_server_response_queue_id;
+
+ status = rtems_message_queue_send(server_id, request, sizeof(*request));
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "monitor server request send failed");
+ goto done;
+ }
+
+ /*
+ * Await response, if requested
+ */
+
+ if (response)
+ {
+ status = rtems_message_queue_receive(rtems_monitor_server_response_queue_id,
+ response,
+ &size,
+ RTEMS_WAIT,
+ 100);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "server did not respond");
+
+ /* maybe server task was restarted; look it up again next time */
+ rtems_monitor_server_request_queue_ids[server_node] = 0;
+
+ goto done;
+ }
+
+ if (response->command != RTEMS_MONITOR_SERVER_RESPONSE)
+ {
+ status = RTEMS_INCORRECT_STATE;
+ goto done;
+ }
+ }
+
+done:
+ return status;
+}
+
+
+
+/*
+ * monitor server task
+ */
+
+void
+rtems_monitor_server_task(
+ rtems_task_argument monitor_flags __attribute__((unused))
+)
+{
+ rtems_monitor_server_request_t request;
+ rtems_monitor_server_response_t response;
+ rtems_status_code status;
+ size_t size;
+
+ for (;;)
+ {
+ status = rtems_message_queue_receive(
+ rtems_monitor_server_request_queue_id,
+ &request,
+ &size,
+ RTEMS_WAIT,
+ (rtems_interval) 0);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "monitor server msg queue receive error");
+ goto failed;
+ }
+
+ if (size != sizeof(request))
+ {
+ rtems_error(0, "monitor server bad size on receive");
+ goto failed;
+ }
+
+ switch (request.command)
+ {
+ case RTEMS_MONITOR_SERVER_CANONICAL:
+ {
+ rtems_monitor_object_type_t object_type;
+ rtems_id id;
+ rtems_id next_id;
+
+ object_type = (rtems_monitor_object_type_t) request.argument0;
+ id = (rtems_id) request.argument1;
+ next_id = rtems_monitor_object_canonical_get(object_type,
+ id,
+ &response.payload,
+ &size);
+
+ response.command = RTEMS_MONITOR_SERVER_RESPONSE;
+ response.result0 = next_id;
+ response.result1 = size;
+
+#define SERVER_OVERHEAD (RTEMS_offsetof(rtems_monitor_server_response_t, \
+ payload))
+
+ status = rtems_message_queue_send(request.return_id,
+ &response,
+ size + SERVER_OVERHEAD);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "response send failed");
+ goto failed;
+ }
+ break;
+ }
+
+ default:
+ {
+ rtems_error(0, "invalid command to monitor server: %d", request.command);
+ goto failed;
+ }
+ }
+ }
+
+failed:
+ rtems_task_delete(RTEMS_SELF);
+}
+
+
+/*
+ * Kill off any old server
+ * Not sure if this is useful, but it doesn't help
+ */
+
+void
+rtems_monitor_server_kill(void)
+{
+ if (rtems_monitor_server_task_id)
+ rtems_task_delete(rtems_monitor_server_task_id);
+ rtems_monitor_server_task_id = 0;
+
+ if (rtems_monitor_server_request_queue_id)
+ rtems_message_queue_delete(rtems_monitor_server_request_queue_id);
+ rtems_monitor_server_request_queue_ids = 0;
+
+ if (rtems_monitor_server_response_queue_id)
+ rtems_message_queue_delete(rtems_monitor_server_response_queue_id);
+ rtems_monitor_server_response_queue_id = 0;
+
+ if (rtems_monitor_server_request_queue_ids)
+ free(rtems_monitor_server_request_queue_ids);
+ rtems_monitor_server_request_queue_ids = 0;
+}
+
+
+void
+rtems_monitor_server_init(
+ uint32_t monitor_flags __attribute__((unused))
+)
+{
+ #if defined(RTEMS_MULTIPROCESSING)
+ rtems_status_code status;
+
+ if (_System_state_Is_multiprocessing &&
+ (_Configuration_MP_table->maximum_nodes > 1))
+ {
+ uint32_t maximum_nodes = _Configuration_MP_table->maximum_nodes;
+
+ /*
+ * create the msg que our server will listen
+ * Since we only get msgs from other RTEMS monitors, we just
+ * need reserve space for 1 msg from each node.
+ */
+
+ status = rtems_message_queue_create(
+ RTEMS_MONITOR_QUEUE_NAME,
+ maximum_nodes,
+ sizeof(rtems_monitor_server_request_t),
+ RTEMS_GLOBAL,
+ &rtems_monitor_server_request_queue_id);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor server message queue");
+ goto done;
+ }
+
+ /*
+ * create the msg que our responses will come on
+ * Since monitor just does one thing at a time, we only need 1 item
+ * message queue.
+ */
+
+ status = rtems_message_queue_create(
+ RTEMS_MONITOR_RESPONSE_QUEUE_NAME,
+ 1, /* depth */
+ sizeof(rtems_monitor_server_response_t),
+ RTEMS_GLOBAL,
+ &rtems_monitor_server_response_queue_id);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor response message queue");
+ goto done;
+ }
+
+ /* need an id for queue of each other server we might talk to */
+ /* indexed by node, so add 1 to maximum_nodes */
+ rtems_monitor_server_request_queue_ids =
+ (rtems_id *) malloc((maximum_nodes + 1) * sizeof(rtems_id));
+ (void) memset(rtems_monitor_server_request_queue_ids,
+ 0,
+ (maximum_nodes + 1) * sizeof(rtems_id));
+
+ rtems_monitor_server_request_queue_ids[rtems_monitor_node] =
+ rtems_monitor_server_request_queue_id;
+
+ /*
+ * create the server task
+ */
+ status = rtems_task_create(RTEMS_MONITOR_SERVER_NAME,
+ 1,
+ 0 /* default stack */,
+ RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &rtems_monitor_server_task_id);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor server task");
+ goto done;
+ }
+
+ /*
+ * Start the server task
+ */
+ status = rtems_task_start(rtems_monitor_server_task_id,
+ rtems_monitor_server_task,
+ monitor_flags);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not start monitor server");
+ goto done;
+ }
+ }
+
+done:
+ #endif
+ return;
+}
diff --git a/cpukit/libmisc/monitor/mon-symbols.c b/cpukit/libmisc/monitor/mon-symbols.c
new file mode 100644
index 0000000000..38a5716c6f
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-symbols.c
@@ -0,0 +1,490 @@
+/*
+ * File: symbols.c
+ *
+ * Description:
+ * Symbol table manager for the RTEMS monitor.
+ * These routines may be used by other system resources also.
+ *
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include <rtems/monitor.h>
+#include "symbols.h"
+
+
+rtems_symbol_table_t *
+rtems_symbol_table_create(void)
+{
+ rtems_symbol_table_t *table;
+
+ table = (rtems_symbol_table_t *) malloc(sizeof(rtems_symbol_table_t));
+ memset((void *) table, 0, sizeof(*table));
+
+ table->growth_factor = 30; /* 30 percent */
+
+ return table;
+}
+
+void
+rtems_symbol_table_destroy(rtems_symbol_table_t *table)
+{
+ rtems_symbol_string_block_t *p, *pnext;
+
+ if (table)
+ {
+ if (table->addresses)
+ (void) free(table->addresses);
+ table->addresses = 0;
+ p = table->string_buffer_head;
+ while (p)
+ {
+ pnext = p->next;
+ free(p);
+ p = pnext;
+ }
+ table->string_buffer_head = 0;
+ table->string_buffer_current = 0;
+
+ free(table);
+ }
+}
+
+rtems_symbol_t *
+rtems_symbol_create(
+ rtems_symbol_table_t *table,
+ const char *name,
+ uint32_t value
+ )
+{
+ size_t symbol_length;
+ size_t newsize;
+ rtems_symbol_t *sp;
+
+ symbol_length = strlen(name) + 1; /* include '\000' in length */
+
+ /* need to grow the table? */
+ if (table->next >= table->size)
+ {
+ if (table->size == 0)
+ newsize = 100;
+ else
+ newsize = table->size + (table->size / (100 / table->growth_factor));
+
+ table->addresses = (rtems_symbol_t *) realloc((void *) table->addresses, newsize * sizeof(rtems_symbol_t));
+ if (table->addresses == 0) /* blew it; lost orig */
+ goto failed;
+ table->size = newsize;
+ }
+
+ sp = &table->addresses[table->next];
+ sp->value = value;
+
+ /* Have to add it to string pool */
+ /* need to grow pool? */
+
+ if ((table->string_buffer_head == 0) ||
+ (table->strings_next + symbol_length) >= SYMBOL_STRING_BLOCK_SIZE)
+ {
+ rtems_symbol_string_block_t *p;
+
+ p = (rtems_symbol_string_block_t *) malloc(sizeof(rtems_symbol_string_block_t));
+ if (p == 0)
+ goto failed;
+ p->next = 0;
+ if (table->string_buffer_head == 0)
+ table->string_buffer_head = p;
+ else
+ table->string_buffer_current->next = p;
+ table->string_buffer_current = p;
+
+ table->strings_next = 0;
+ }
+
+ sp->name = table->string_buffer_current->buffer + table->strings_next;
+ (void) strcpy(sp->name, name);
+
+ table->strings_next += symbol_length;
+ table->sorted = 0;
+ table->next++;
+
+ return sp;
+
+/* XXX Not sure what to do here. We've possibly destroyed the initial
+ symbol table due to realloc failure */
+failed:
+ return 0;
+}
+
+/*
+ * Qsort entry point for compare by address
+ */
+
+static int
+rtems_symbol_compare(const void *e1,
+ const void *e2)
+{
+ rtems_symbol_t *s1, *s2;
+ s1 = (rtems_symbol_t *) e1;
+ s2 = (rtems_symbol_t *) e2;
+
+ if (s1->value < s2->value)
+ return -1;
+ if (s1->value > s2->value)
+ return 1;
+ return 0;
+}
+
+
+/*
+ * Sort the symbol table using qsort
+ */
+
+static void
+rtems_symbol_sort(rtems_symbol_table_t *table)
+{
+ qsort((void *) table->addresses, (size_t) table->next,
+ sizeof(rtems_symbol_t), rtems_symbol_compare);
+ table->sorted = 1;
+}
+
+
+/*
+ * Search the symbol table by address
+ * This code based on CYGNUS newlib bsearch, but changed
+ * to allow for finding closest symbol <= key
+ */
+
+rtems_symbol_t *
+rtems_symbol_value_lookup(
+ rtems_symbol_table_t *table,
+ uint32_t value
+ )
+{
+ rtems_symbol_t *sp;
+ rtems_symbol_t *base;
+ rtems_symbol_t *best = 0;
+ uint32_t distance;
+ uint32_t best_distance = ~0;
+ uint32_t elements;
+
+ if (table == 0)
+ table = rtems_monitor_symbols;
+
+ if ((table == 0) || (table->size == 0))
+ return 0;
+
+ if (table->sorted == 0)
+ rtems_symbol_sort(table);
+
+ base = table->addresses;
+ elements = table->next;
+
+ while (elements)
+ {
+ sp = base + (elements / 2);
+ if (value < sp->value)
+ elements /= 2;
+ else if (value > sp->value)
+ {
+ distance = value - sp->value;
+ if (distance < best_distance)
+ {
+ best_distance = distance;
+ best = sp;
+ }
+ base = sp + 1;
+ elements = (elements / 2) - (elements % 2 ? 0 : 1);
+ }
+ else
+ return sp;
+ }
+
+ if (value == base->value)
+ return base;
+
+ return best;
+}
+
+/*
+ * Search the symbol table for the exact matching address.
+ * If the symbol table has already been sorted, then
+ * call the regular symbol value lookup, however, it it
+ * has not yet been sorted, search it sequentially.
+ * This routine is primarily used for low level symbol
+ * lookups (eg. from exception handler and interrupt routines)
+ * where the penality of sorted is not wanted and where
+ * an exact match is needed such that symbol table order
+ * is not important.
+ */
+const rtems_symbol_t *
+rtems_symbol_value_lookup_exact(
+ rtems_symbol_table_t *table,
+ uint32_t value
+ )
+{
+ uint32_t s;
+ rtems_symbol_t *sp;
+
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return NULL;
+ }
+
+ if (table->sorted)
+ {
+ sp = rtems_symbol_value_lookup(table, value);
+ if ( rtems_symbol_value(sp) == value )
+ return sp;
+ else
+ return NULL; /* not an exact match */
+ }
+
+ for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
+ {
+ if ( sp->value == value )
+ return sp;
+ }
+
+ return NULL;
+
+}
+
+
+/*
+ * Search the symbol table by string name (case independent)
+ */
+
+rtems_symbol_t *
+rtems_symbol_name_lookup(
+ rtems_symbol_table_t *table,
+ const char *name
+ )
+{
+ uint32_t s;
+ rtems_symbol_t *sp;
+
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return NULL;
+ }
+
+ for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
+ {
+ if ( strcasecmp(sp->name, name) == 0 )
+ return sp;
+ }
+
+ return NULL;
+}
+
+void *
+rtems_monitor_symbol_next(
+ void *object_info,
+ rtems_monitor_symbol_t *canonical __attribute__((unused)),
+ rtems_id *next_id
+)
+{
+ rtems_symbol_table_t *table;
+ uint32_t n = rtems_object_id_get_index(*next_id);
+
+ table = *(rtems_symbol_table_t **) object_info;
+ if (table == 0)
+ goto failed;
+
+ if (n >= table->next)
+ goto failed;
+
+ /* NOTE: symbols do not have id and name fields */
+
+ if (table->sorted == 0)
+ rtems_symbol_sort(table);
+
+ _Thread_Disable_dispatch();
+
+ *next_id += 1;
+ return (void *) (table->addresses + n);
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+void
+rtems_monitor_symbol_canonical(
+ rtems_monitor_symbol_t *canonical_symbol,
+ rtems_symbol_t *sp
+)
+{
+ canonical_symbol->value = sp->value;
+ canonical_symbol->offset = 0;
+ strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name)-1);
+}
+
+
+void
+rtems_monitor_symbol_canonical_by_name(
+ rtems_monitor_symbol_t *canonical_symbol,
+ const char *name
+)
+{
+ rtems_symbol_t *sp;
+
+ sp = rtems_symbol_name_lookup(0, name);
+
+ canonical_symbol->value = sp ? sp->value : 0;
+
+ strncpy(canonical_symbol->name, name, sizeof(canonical_symbol->name) - 1);
+ canonical_symbol->offset = 0;
+}
+
+void
+rtems_monitor_symbol_canonical_by_value(
+ rtems_monitor_symbol_t *canonical_symbol,
+ void *value_void_p
+)
+{
+ uintptr_t value = (uintptr_t) value_void_p;
+ rtems_symbol_t *sp;
+
+ sp = rtems_symbol_value_lookup(0, value);
+ if (sp)
+ {
+ canonical_symbol->value = sp->value;
+ canonical_symbol->offset = value - sp->value;
+ strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name)-1);
+ }
+ else
+ {
+ canonical_symbol->value = value;
+ canonical_symbol->offset = 0;
+ canonical_symbol->name[0] = '\0';
+ }
+}
+
+
+uint32_t
+rtems_monitor_symbol_dump(
+ rtems_monitor_symbol_t *canonical_symbol,
+ bool verbose
+)
+{
+ uint32_t length = 0;
+
+ /*
+ * print the name if it exists AND if value is non-zero
+ * Ie: don't print some garbage symbol for address 0
+ */
+
+ if (canonical_symbol->name[0] && (canonical_symbol->value != 0))
+ {
+ if (canonical_symbol->offset == 0)
+ length += fprintf(stdout,"%.*s",
+ (int) sizeof(canonical_symbol->name),
+ canonical_symbol->name);
+ else
+ length += fprintf(stdout,"<%.*s+0x%" PRIx32 ">",
+ (int) sizeof(canonical_symbol->name),
+ canonical_symbol->name,
+ canonical_symbol->offset);
+ if (verbose)
+ length += fprintf(stdout,
+ " [0x%" PRIx32 "]", canonical_symbol->value);
+ }
+ else
+ length += fprintf(stdout,"[0x%" PRIx32 "]", canonical_symbol->value);
+
+ return length;
+}
+
+
+void
+rtems_monitor_symbol_dump_all(
+ rtems_symbol_table_t *table,
+ bool verbose __attribute__((unused))
+)
+{
+ uint32_t s;
+ rtems_symbol_t *sp;
+
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return;
+ }
+
+ if (table->sorted == 0)
+ rtems_symbol_sort(table);
+
+ for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
+ {
+ rtems_monitor_symbol_t canonical_symbol;
+
+ rtems_monitor_symbol_canonical(&canonical_symbol, sp);
+ rtems_monitor_symbol_dump(&canonical_symbol, true);
+ fprintf(stdout,"\n");
+ }
+}
+
+
+/*
+ * 'symbol' command
+ */
+
+void rtems_monitor_symbol_cmd(
+ int argc,
+ char **argv,
+ const rtems_monitor_command_arg_t *command_arg,
+ bool verbose
+)
+{
+ int arg;
+ rtems_symbol_table_t *table;
+
+ table = *command_arg->symbol_table;
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return;
+ }
+
+ /*
+ * Use object command to dump out whole symbol table
+ */
+ if (argc == 1)
+ rtems_monitor_symbol_dump_all(table, verbose);
+ else
+ {
+ rtems_monitor_symbol_t canonical_symbol;
+
+ for (arg=1; argv[arg]; arg++)
+ {
+ rtems_monitor_symbol_canonical_by_name(&canonical_symbol, argv[arg]);
+ rtems_monitor_symbol_dump(&canonical_symbol, verbose);
+ fprintf(stdout,"\n");
+ }
+ }
+}
diff --git a/cpukit/libmisc/monitor/mon-task.c b/cpukit/libmisc/monitor/mon-task.c
new file mode 100644
index 0000000000..6007b3f879
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-task.c
@@ -0,0 +1,105 @@
+/*
+ * RTEMS Monitor task support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <string.h> /* memcpy() */
+
+void
+rtems_monitor_task_canonical(
+ rtems_monitor_task_t *canonical_task,
+ void *thread_void
+)
+{
+ Thread_Control *rtems_thread = (Thread_Control *) thread_void;
+ RTEMS_API_Control *api;
+
+ api = rtems_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ canonical_task->entry = rtems_thread->Start.entry_point;
+ canonical_task->argument = rtems_thread->Start.numeric_argument;
+ canonical_task->stack = rtems_thread->Start.Initial_stack.area;
+ canonical_task->stack_size = rtems_thread->Start.Initial_stack.size;
+ canonical_task->priority = rtems_thread->current_priority;
+ canonical_task->state = rtems_thread->current_state;
+ canonical_task->wait_id = rtems_thread->Wait.id;
+ canonical_task->events = api->pending_events;
+ /*
+ * FIXME: make this optionally cpu_time_executed
+ */
+#if 0
+ canonical_task->ticks = rtems_thread->cpu_time_executed;
+#else
+ canonical_task->ticks = 0;
+#endif
+
+/* XXX modes and attributes only exist in the RTEMS API .. */
+/* XXX not directly in the core thread.. they will have to be derived */
+/* XXX if they are important enough to include anymore. */
+ canonical_task->modes = 0; /* XXX FIX ME.... rtems_thread->current_modes; */
+ canonical_task->attributes = 0 /* XXX FIX ME rtems_thread->API_Extensions[ THREAD_API_RTEMS ]->attribute_set */;
+ (void) memcpy(canonical_task->notepad, api ->Notepads, sizeof(canonical_task->notepad));
+/* XXX more to fix */
+/*
+ (void) memcpy(&canonical_task->wait_args, &rtems_thread->Wait.Extra, sizeof(canonical_task->wait_args));
+*/
+}
+
+
+void
+rtems_monitor_task_dump_header(
+ bool verbose __attribute__((unused))
+)
+{
+ fprintf(stdout,"\
+ ID NAME PRI STATE MODES EVENTS WAITID WAITARG NOTES\n\
+");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+/*
+ */
+
+void
+rtems_monitor_task_dump(
+ rtems_monitor_task_t *monitor_task,
+ bool verbose __attribute__((unused))
+)
+{
+ int length = 0;
+
+ length += rtems_monitor_dump_id(monitor_task->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_task->id);
+ length += rtems_monitor_pad(26, length);
+ length += rtems_monitor_dump_priority(monitor_task->priority);
+ length += rtems_monitor_pad(29, length);
+ length += rtems_monitor_dump_state(monitor_task->state);
+ length += rtems_monitor_pad(37, length);
+ length += rtems_monitor_dump_modes(monitor_task->modes);
+ length += rtems_monitor_pad(45, length);
+ length += rtems_monitor_dump_events(monitor_task->events);
+ if (monitor_task->wait_id)
+ {
+ length += rtems_monitor_pad(54, length);
+ length += rtems_monitor_dump_id(monitor_task->wait_id);
+ length += rtems_monitor_pad(63, length);
+ length += rtems_monitor_dump_hex(monitor_task->wait_args);
+ }
+
+ length += rtems_monitor_pad(72, length);
+ length += rtems_monitor_dump_notepad(monitor_task->notepad);
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/monitor.h b/cpukit/libmisc/monitor/monitor.h
new file mode 100644
index 0000000000..84a360b976
--- /dev/null
+++ b/cpukit/libmisc/monitor/monitor.h
@@ -0,0 +1,531 @@
+/**
+ * @file rtems/monitor.h
+ *
+ * The RTEMS monitor task.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef __MONITOR_H
+#define __MONITOR_H
+
+#include <rtems/error.h> /* rtems_error() */
+#include <rtems/config.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward decls from symbols.h */
+typedef struct _rtems_symbol_t rtems_symbol_t;
+typedef struct _rtems_symbol_table_t rtems_symbol_table_t;
+
+/*
+ * Monitor types are derived from rtems object classes
+ */
+
+typedef enum {
+ RTEMS_MONITOR_OBJECT_INVALID = OBJECTS_CLASSIC_NO_CLASS,
+ RTEMS_MONITOR_OBJECT_TASK = OBJECTS_RTEMS_TASKS,
+ RTEMS_MONITOR_OBJECT_EXTENSION = OBJECTS_RTEMS_EXTENSIONS,
+ RTEMS_MONITOR_OBJECT_QUEUE = OBJECTS_RTEMS_MESSAGE_QUEUES,
+ RTEMS_MONITOR_OBJECT_SEMAPHORE = OBJECTS_RTEMS_SEMAPHORES,
+ RTEMS_MONITOR_OBJECT_PARTITION = OBJECTS_RTEMS_PARTITIONS,
+ RTEMS_MONITOR_OBJECT_REGION = OBJECTS_RTEMS_REGIONS,
+ RTEMS_MONITOR_OBJECT_PORT = OBJECTS_RTEMS_PORTS,
+
+ /* following monitor objects are not known to RTEMS, but
+ * we like to have "types" for them anyway */
+
+ RTEMS_MONITOR_OBJECT_DRIVER = OBJECTS_RTEMS_CLASSES_LAST+1,
+ RTEMS_MONITOR_OBJECT_DNAME,
+ RTEMS_MONITOR_OBJECT_CONFIG,
+ RTEMS_MONITOR_OBJECT_INIT_TASK,
+ RTEMS_MONITOR_OBJECT_MPCI,
+ RTEMS_MONITOR_OBJECT_SYMBOL,
+ #if defined(RTEMS_POSIX_API)
+ RTEMS_MONITOR_OBJECT_PTHREAD,
+ #endif
+} rtems_monitor_object_type_t;
+
+/*
+ * rtems_monitor_init() flags
+ */
+
+#define RTEMS_MONITOR_SUSPEND 0x0001 /* suspend monitor on startup */
+#define RTEMS_MONITOR_GLOBAL 0x0002 /* monitor should be global */
+#define RTEMS_MONITOR_NOTASK 0x0004 /* do not start monitor task */
+#define RTEMS_MONITOR_NOSYMLOAD 0x0008 /* do not load symbols */
+#define RTEMS_MONITOR_WAITQUIT 0x0010 /* wait for monitor task to terminate */
+
+/*
+ * Public interfaces for RTEMS data structures monitor is aware of.
+ * These are only used by the monitor.
+ *
+ * NOTE:
+ * All the canonical objects that correspond to RTEMS managed "objects"
+ * must have an identical first portion with 'id' and 'name' fields.
+ *
+ * Others do not have that restriction, even tho we would like them to.
+ * This is because some of the canonical structures are almost too big
+ * for shared memory driver (eg: mpci) and we are nickel and diming it.
+ */
+
+/*
+ * Type of a pointer that may be a symbol
+ */
+
+#define MONITOR_SYMBOL_LEN 20
+typedef struct {
+ char name[MONITOR_SYMBOL_LEN];
+ uint32_t value;
+ uint32_t offset;
+} rtems_monitor_symbol_t;
+
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+} rtems_monitor_generic_t;
+
+/*
+ * Task
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ Thread_Entry entry;
+ Thread_Entry_numeric_type argument;
+ void *stack;
+ uint32_t stack_size;
+ rtems_task_priority priority;
+ States_Control state;
+ rtems_event_set events;
+ rtems_mode modes;
+ rtems_attribute attributes;
+ uint32_t notepad[RTEMS_NUMBER_NOTEPADS];
+ rtems_id wait_id;
+ uint32_t wait_args;
+ uint32_t ticks;
+} rtems_monitor_task_t;
+
+/*
+ * Init task
+ */
+
+typedef struct {
+ rtems_id id; /* not really an id */
+ rtems_name name;
+ /* end of common portion */
+ rtems_monitor_symbol_t entry;
+ uint32_t argument;
+ uint32_t stack_size;
+ rtems_task_priority priority;
+ rtems_mode modes;
+ rtems_attribute attributes;
+} rtems_monitor_init_task_t;
+
+
+/*
+ * Message queue
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ rtems_attribute attributes;
+ uint32_t number_of_pending_messages;
+ uint32_t maximum_pending_messages;
+ size_t maximum_message_size;
+} rtems_monitor_queue_t;
+
+/*
+ * Semaphore
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ rtems_attribute attribute;
+ rtems_task_priority priority_ceiling;
+ uint32_t max_count;
+ uint32_t cur_count;
+ rtems_id holder_id;
+} rtems_monitor_sema_t;
+
+/*
+ * Extension
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ rtems_monitor_symbol_t e_create;
+ rtems_monitor_symbol_t e_start;
+ rtems_monitor_symbol_t e_restart;
+ rtems_monitor_symbol_t e_delete;
+ rtems_monitor_symbol_t e_tswitch;
+ rtems_monitor_symbol_t e_begin;
+ rtems_monitor_symbol_t e_exitted;
+ rtems_monitor_symbol_t e_fatal;
+} rtems_monitor_extension_t;
+
+ /*
+ * Region
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ rtems_attribute attribute;
+ void * start_addr;
+ uint32_t length;
+ uint32_t page_size;
+ uint32_t max_seg_size;
+ uint32_t used_blocks;
+} rtems_monitor_region_t;
+
+/*
+ * Partition
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ rtems_attribute attribute;
+ void * start_addr;
+ uint32_t length;
+ uint32_t buf_size;
+ uint32_t used_blocks;
+} rtems_monitor_part_t;
+
+/*
+ * Device driver
+ */
+
+typedef struct {
+ rtems_id id; /* not really an id (should be tho) */
+ rtems_name name; /* ditto */
+ /* end of common portion */
+ rtems_monitor_symbol_t initialization; /* initialization procedure */
+ rtems_monitor_symbol_t open; /* open request procedure */
+ rtems_monitor_symbol_t close; /* close request procedure */
+ rtems_monitor_symbol_t read; /* read request procedure */
+ rtems_monitor_symbol_t write; /* write request procedure */
+ rtems_monitor_symbol_t control; /* special functions procedure */
+} rtems_monitor_driver_t;
+
+/*
+ * System config
+ */
+
+typedef struct {
+ void *work_space_start;
+ uint32_t work_space_size;
+ uint32_t maximum_tasks;
+ uint32_t maximum_timers;
+ uint32_t maximum_semaphores;
+ uint32_t maximum_message_queues;
+ uint32_t maximum_partitions;
+ uint32_t maximum_regions;
+ uint32_t maximum_ports;
+ uint32_t maximum_periods;
+ uint32_t maximum_extensions;
+ uint32_t microseconds_per_tick;
+ uint32_t ticks_per_timeslice;
+ uint32_t number_of_initialization_tasks;
+} rtems_monitor_config_t;
+
+/*
+ * MPCI config
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+typedef struct {
+ uint32_t node; /* local node number */
+ uint32_t maximum_nodes; /* maximum # nodes in system */
+ uint32_t maximum_global_objects; /* maximum # global objects */
+ uint32_t maximum_proxies; /* maximum # proxies */
+
+ uint32_t default_timeout; /* in ticks */
+ size_t maximum_packet_size;
+ rtems_monitor_symbol_t initialization;
+ rtems_monitor_symbol_t get_packet;
+ rtems_monitor_symbol_t return_packet;
+ rtems_monitor_symbol_t send_packet;
+ rtems_monitor_symbol_t receive_packet;
+} rtems_monitor_mpci_t;
+#endif
+
+/*
+ * The generic canonical information union
+ */
+
+typedef union {
+ rtems_monitor_generic_t generic;
+ rtems_monitor_task_t task;
+ rtems_monitor_queue_t queue;
+ rtems_monitor_sema_t sema;
+ rtems_monitor_extension_t extension;
+ rtems_monitor_driver_t driver;
+ rtems_monitor_config_t config;
+ rtems_monitor_region_t region;
+ rtems_monitor_part_t part;
+#if defined(RTEMS_MULTIPROCESSING)
+ rtems_monitor_mpci_t mpci;
+#endif
+ rtems_monitor_init_task_t itask;
+} rtems_monitor_union_t;
+
+/*
+ * Support for talking to other monitors
+ */
+
+/*
+ * Names of other monitors
+ */
+
+#define RTEMS_MONITOR_NAME (rtems_build_name('R', 'M', 'O', 'N'))
+#define RTEMS_MONITOR_SERVER_NAME (rtems_build_name('R', 'M', 'S', 'V'))
+#define RTEMS_MONITOR_QUEUE_NAME (rtems_build_name('R', 'M', 'S', 'Q'))
+#define RTEMS_MONITOR_RESPONSE_QUEUE_NAME (rtems_build_name('R', 'M', 'R', 'Q'))
+
+#define RTEMS_MONITOR_SERVER_RESPONSE 0x0001
+#define RTEMS_MONITOR_SERVER_CANONICAL 0x0002
+
+typedef struct
+{
+ uint32_t command;
+ rtems_id return_id;
+ uint32_t argument0;
+ uint32_t argument1;
+ uint32_t argument2;
+ uint32_t argument3;
+ uint32_t argument4;
+ uint32_t argument5;
+} rtems_monitor_server_request_t;
+
+typedef struct
+{
+ uint32_t command;
+ uint32_t result0;
+ uint32_t result1;
+ rtems_monitor_union_t payload;
+} rtems_monitor_server_response_t;
+
+extern rtems_id rtems_monitor_task_id;
+
+extern uint32_t rtems_monitor_node; /* our node number */
+extern uint32_t rtems_monitor_default_node; /* current default for commands */
+
+/*
+ * Monitor command function and table entry
+ */
+
+typedef struct rtems_monitor_command_entry_s rtems_monitor_command_entry_t;
+typedef union _rtems_monitor_command_arg_t rtems_monitor_command_arg_t;
+
+typedef void (*rtems_monitor_command_function_t)(
+ int argc,
+ char **argv,
+ const rtems_monitor_command_arg_t *command_arg,
+ bool verbose
+);
+
+union _rtems_monitor_command_arg_t {
+ rtems_monitor_object_type_t monitor_object;
+ rtems_status_code status_code;
+ rtems_symbol_table_t **symbol_table;
+ const rtems_monitor_command_entry_t *monitor_command_entry;
+};
+
+struct rtems_monitor_command_entry_s {
+ const char *command; /* command name */
+ const char *usage; /* usage string for the command */
+ uint32_t arguments_required; /* # of required args */
+ rtems_monitor_command_function_t command_function;
+ /* Some argument for the command */
+ rtems_monitor_command_arg_t command_arg;
+ const rtems_monitor_command_entry_t *next;
+};
+
+
+typedef void *(*rtems_monitor_object_next_fn)(void *, void *, rtems_id *);
+typedef void (*rtems_monitor_object_canonical_fn)(void *, void *);
+typedef void (*rtems_monitor_object_dump_header_fn)(bool);
+typedef void (*rtems_monitor_object_dump_fn)(void *, bool);
+
+typedef struct {
+ rtems_monitor_object_type_t type;
+ void *object_information;
+ int size; /* of canonical object */
+ rtems_monitor_object_next_fn next;
+ rtems_monitor_object_canonical_fn canonical;
+ rtems_monitor_object_dump_header_fn dump_header;
+ rtems_monitor_object_dump_fn dump;
+} rtems_monitor_object_info_t;
+
+typedef bool (*rtems_monitor_per_command_routine)(const rtems_monitor_command_entry_t *, void *);
+
+/* monitor.c */
+void rtems_monitor_pause_cmd(int, char **, const rtems_monitor_command_arg_t*, bool);
+void rtems_monitor_fatal_cmd(int, char **, const rtems_monitor_command_arg_t*, bool);
+void rtems_monitor_continue_cmd(int, char **, const rtems_monitor_command_arg_t*, bool);
+void rtems_monitor_debugger_cmd(int, char **, const rtems_monitor_command_arg_t*, bool);
+void rtems_monitor_reset_cmd(int, char **, const rtems_monitor_command_arg_t*, bool);
+void rtems_monitor_node_cmd(int, char **, const rtems_monitor_command_arg_t*, bool);
+void rtems_monitor_symbols_loadup(void);
+int rtems_monitor_insert_cmd(rtems_monitor_command_entry_t *);
+void rtems_monitor_wakeup(void);
+void rtems_monitor_command_iterate(rtems_monitor_per_command_routine routine, void *arg);
+rtems_status_code rtems_monitor_suspend(rtems_interval timeout);
+
+/* editor.c */
+void rtems_monitor_kill(void);
+void rtems_monitor_init(uint32_t);
+void rtems_monitor_task(rtems_task_argument);
+
+/* server.c */
+void rtems_monitor_server_kill(void);
+rtems_status_code rtems_monitor_server_request(uint32_t , rtems_monitor_server_request_t *, rtems_monitor_server_response_t *);
+void rtems_monitor_server_task(rtems_task_argument);
+void rtems_monitor_server_init(uint32_t );
+
+/* command.c */
+int rtems_monitor_make_argv(char *, int *, char **);
+int rtems_monitor_command_read(char *, int *, char **);
+void rtems_monitor_command_usage(const rtems_monitor_command_entry_t *, const char *);
+void rtems_monitor_help_cmd(int, char **, const rtems_monitor_command_arg_t *, bool);
+const rtems_monitor_command_entry_t *rtems_monitor_command_lookup(const char *name);
+
+/* prmisc.c */
+void rtems_monitor_separator(void);
+uint32_t rtems_monitor_pad(uint32_t dest_col, uint32_t curr_col);
+int rtems_monitor_dump_decimal(uint32_t num);
+int rtems_monitor_dump_hex(uint32_t num);
+int rtems_monitor_dump_addr(void *addr);
+int rtems_monitor_dump_id(rtems_id id);
+int rtems_monitor_dump_name(rtems_id id);
+int rtems_monitor_dump_priority(rtems_task_priority priority);
+int rtems_monitor_dump_state(States_Control state);
+int rtems_monitor_dump_modes(rtems_mode modes);
+int rtems_monitor_dump_attributes(rtems_attribute attributes);
+int rtems_monitor_dump_events(rtems_event_set events);
+int rtems_monitor_dump_notepad(uint32_t *notepad);
+
+/* object.c */
+rtems_id rtems_monitor_id_fixup(rtems_id, uint32_t , rtems_monitor_object_type_t);
+const rtems_monitor_object_info_t *rtems_monitor_object_lookup(rtems_monitor_object_type_t type);
+rtems_id rtems_monitor_object_canonical_get(rtems_monitor_object_type_t, rtems_id, void *, size_t *size_p);
+rtems_id rtems_monitor_object_canonical_next(const rtems_monitor_object_info_t *, rtems_id, void *);
+void *rtems_monitor_object_next(void *, void *, rtems_id, rtems_id *);
+rtems_id rtems_monitor_object_canonical(rtems_id, void *);
+void rtems_monitor_object_cmd(int, char **, const rtems_monitor_command_arg_t*, bool);
+
+/* manager.c */
+void *rtems_monitor_manager_next(void *, void *, rtems_id *);
+
+/* config.c */
+void rtems_monitor_config_canonical(rtems_monitor_config_t *, void *);
+void *rtems_monitor_config_next(void *, rtems_monitor_config_t *, rtems_id *);
+void rtems_monitor_config_dump_header(bool);
+int rtems_monitor_config_dump(rtems_monitor_config_t *, bool verbose);
+
+/* mpci.c */
+#if defined(RTEMS_MULTIPROCESSING)
+void rtems_monitor_mpci_canonical(rtems_monitor_mpci_t *, void *);
+void *rtems_monitor_mpci_next(void *, rtems_monitor_mpci_t *, rtems_id *);
+void rtems_monitor_mpci_dump_header(bool);
+void rtems_monitor_mpci_dump(rtems_monitor_mpci_t *, bool verbose);
+#endif
+
+/* itask.c */
+void rtems_monitor_init_task_canonical(rtems_monitor_init_task_t *, void *);
+void *rtems_monitor_init_task_next(void *, rtems_monitor_init_task_t *, rtems_id *);
+void rtems_monitor_init_task_dump_header(bool);
+void rtems_monitor_init_task_dump(rtems_monitor_init_task_t *, bool verbose);
+
+/* extension.c */
+void rtems_monitor_extension_canonical(rtems_monitor_extension_t *, void *);
+void rtems_monitor_extension_dump_header(bool verbose);
+void rtems_monitor_extension_dump(rtems_monitor_extension_t *, bool);
+
+/* task.c */
+void rtems_monitor_task_canonical(rtems_monitor_task_t *, void *);
+void rtems_monitor_task_dump_header(bool verbose);
+void rtems_monitor_task_dump(rtems_monitor_task_t *, bool);
+
+/* sema.c */
+void rtems_monitor_sema_canonical(rtems_monitor_sema_t *, void *);
+void rtems_monitor_sema_dump_header(bool verbose);
+void rtems_monitor_sema_dump(rtems_monitor_sema_t *, bool);
+
+/* queue.c */
+void rtems_monitor_queue_canonical(rtems_monitor_queue_t *, void *);
+void rtems_monitor_queue_dump_header(bool verbose);
+void rtems_monitor_queue_dump(rtems_monitor_queue_t *, bool);
+
+/* region.c */
+void rtems_monitor_region_canonical(rtems_monitor_region_t *, void *);
+void rtems_monitor_region_dump_header(bool verbose);
+void rtems_monitor_region_dump(rtems_monitor_region_t *, bool);
+
+/* partition.c */
+void rtems_monitor_part_canonical(rtems_monitor_part_t *, void *);
+void rtems_monitor_part_dump_header(bool verbose);
+void rtems_monitor_part_dump(rtems_monitor_part_t *, bool);
+
+/* driver.c */
+void *rtems_monitor_driver_next(void *, rtems_monitor_driver_t *, rtems_id *);
+void rtems_monitor_driver_canonical(rtems_monitor_driver_t *, void *);
+void rtems_monitor_driver_dump_header(bool);
+void rtems_monitor_driver_dump(rtems_monitor_driver_t *, bool);
+
+/* symbols.c */
+rtems_symbol_table_t *rtems_symbol_table_create(void);
+void rtems_symbol_table_destroy(rtems_symbol_table_t *table);
+
+rtems_symbol_t *rtems_symbol_create(rtems_symbol_table_t *, const char *, uint32_t );
+rtems_symbol_t *rtems_symbol_value_lookup(rtems_symbol_table_t *, uint32_t );
+const rtems_symbol_t *rtems_symbol_value_lookup_exact(rtems_symbol_table_t *, uint32_t );
+rtems_symbol_t *rtems_symbol_name_lookup(rtems_symbol_table_t *, const char *);
+void *rtems_monitor_symbol_next(void *object_info, rtems_monitor_symbol_t *, rtems_id *);
+void rtems_monitor_symbol_canonical(rtems_monitor_symbol_t *, rtems_symbol_t *);
+void rtems_monitor_symbol_canonical_by_name(rtems_monitor_symbol_t *, const char *);
+void rtems_monitor_symbol_canonical_by_value(rtems_monitor_symbol_t *, void *);
+uint32_t rtems_monitor_symbol_dump(rtems_monitor_symbol_t *, bool);
+void rtems_monitor_symbol_cmd(int, char **, const rtems_monitor_command_arg_t*, bool);
+
+#if defined(RTEMS_NETWORKING)
+void mon_ifconfig(
+ int argc,
+ char *argv[],
+ uint32_t command_arg,
+ bool verbose
+);
+void mon_route(
+ int argc,
+ char *argv[],
+ uint32_t command_arg,
+ bool verbose
+);
+#endif
+
+/* mon-object.c */
+const rtems_monitor_object_info_t *rtems_monitor_object_lookup(
+ rtems_monitor_object_type_t type
+);
+
+/* shared data */
+extern rtems_symbol_table_t *rtems_monitor_symbols;
+
+#define MONITOR_WAKEUP_EVENT RTEMS_EVENT_0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! __MONITOR_H */
diff --git a/cpukit/libmisc/monitor/symbols.h b/cpukit/libmisc/monitor/symbols.h
new file mode 100644
index 0000000000..6246379a94
--- /dev/null
+++ b/cpukit/libmisc/monitor/symbols.h
@@ -0,0 +1,64 @@
+/*
+ * RTEMS monitor symbol table functions
+ *
+ * Description:
+ * Entry points for symbol table routines.
+ *
+ *
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifndef _INCLUDE_SYMBOLS_H
+#define _INCLUDE_SYMBOLS_H
+
+#include <rtems/monitor.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _rtems_symbol_t {
+ uint32_t value;
+ char *name;
+} ;
+
+#define SYMBOL_STRING_BLOCK_SIZE 4080
+typedef struct rtems_symbol_string_block_s {
+ struct rtems_symbol_string_block_s *next;
+ char buffer[SYMBOL_STRING_BLOCK_SIZE];
+} rtems_symbol_string_block_t;
+
+struct _rtems_symbol_table_t {
+
+ uint32_t sorted; /* are symbols sorted right now? */
+ uint32_t growth_factor; /* % to grow by when needed */
+ uint32_t next; /* next symbol slot to use when adding */
+ uint32_t size; /* max # of symbols */
+
+ /*
+ * Symbol list -- sorted by address (when we do a lookup)
+ */
+
+ rtems_symbol_t *addresses; /* symbol array by address */
+
+ /*
+ * String pool, unsorted, a list of blocks of string data
+ */
+
+ rtems_symbol_string_block_t *string_buffer_head;
+ rtems_symbol_string_block_t *string_buffer_current;
+ uint32_t strings_next; /* next byte to use in this block */
+
+} ;
+
+#define rtems_symbol_name(sp) ((sp)->name)
+#define rtems_symbol_value(sp) ((sp)->value)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_SYMBOLS_H */
diff --git a/cpukit/libmisc/mouse/README b/cpukit/libmisc/mouse/README
new file mode 100644
index 0000000000..ab684a6d0b
--- /dev/null
+++ b/cpukit/libmisc/mouse/README
@@ -0,0 +1,214 @@
+#
+# $Id$
+#
+
+SOURCE: http://www.kryslix.com/nsfaq/Q.12.html
+
+Subject: What protocol do mice use?
+Date: 09/16/97
+Updated: 11/16/00 This document was adapated from a web page produced by
+Tomi Engdahl <then@delta.hut.fi>
+Microsoft serial mouse
+Description
+
+The Microsoft serial mouse is the most popular 2 button mouse. It is
+supported by all major operating systems. The maximum tracking rate for
+a Microsoft mouse is 40 reports/second * 127 counts per report, in other
+words, 5080 counts per second. The most common range for mice is is 100
+to 400 CPI (counts per inch) but can be up to 1000 CPI. A 100CPI mouse
+can discriminate motion up to 50.8 inches/second while a 400 CPI mouse
+can only discriminate motion up to 12.7 inches/second.
+Pinout
+
+9 pin 25 pin Line Comments
+shell 1 GND
+3 2 TD Serial data from host to mouse (only for power)
+2 3 RD Serial data from mouse to host
+7 4 RTS Positive voltage to mouse
+8 5 CTS
+6 6 DSR
+5 7 SGND
+4 20 DTR Positive voltage to mouse and reset/detection
+
+RTS = Request to Send CTS = Clear to Send
+DSR = Data Set Ready DTR = Data Terminal Ready
+GND = Protective Ground SGND = Signal Ground
+
+To function correctly, both the RTS and DTR lines must be
+positive. DTR/DSR and RTS/CTS must NOT be shorted. RTS may be toggled
+negative for at least 100ms to reset the mouse. (After a cold boot, the
+RTS line is usually negative. This provides an automatic toggle when
+RTS is brought positive). When DTR is toggled the mouse should send a
+single byte 0x45 (ASCII 'M').
+
+Serial data parameters:
+1200bps, 7 databits, 1 stop-bit
+
+Data packet format:
+
+Data is sent in 3 byte packets for each event (a button is pressed or
+released or the mouse moves):
+
+ D7 D6 D5 D4 D3 D2 D1 D0
+
+Byte 1 X 1 LB RB Y7 Y6 X7 X6
+Byte 2 X 0 X5 X4 X3 X2 X1 X0
+Byte 3 X 0 Y5 Y4 Y3 Y2 Y1 Y0
+
+LB is the state of the left button (1 means down)
+RB is the state of the right button (1 means down)
+X7-X0 movement in X direction since last packet (signed byte)
+Y7-Y0 movement in Y direction since last packet (signed byte)
+
+The high order bit of each byte (D7) is ignored. Bit D6 indicates the start of an event, which allows the software to synchronize with the mouse.
+
+Graphical representation of a packet
+
+ 1st byte 2nd byte 3rd byte
+ ================ =============== ================
+ - 1 ? ? Y Y X X - 0 X X X X X X - 0 Y Y Y Y Y Y
+ ================ =============== ================
+ | | \ / \ / \---------/ \---------/
+ | | | | | |
+ | | | \----\ | |
+ | | \--------|-------|--------\ |
+ | | / \ /---------\ / \ /---------\
+ | | ================ =================
+ | | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ Left Button --/ | ================ =================
+Right Button ----/ X increment Y increment
+
+3 Button Logitech extension
+
+Logitech extended the 2 button mouse protocol to support 3 button mice
+by adding a 4th byte when the middle button is pressed (and the first
+packet after it is released). If a 4th byte is encountered (i.e., an
+extra byte with D6 set to 0) then D5 of that byte (0x20) indicates the
+status of the middle mouse button.
+
+Mouse systems mouse
+
+Serial data parameters:
+
+1200bps, 8 databits, 1 stop-bit
+
+5 byte Mouse Systems packet
+
+ D7 D6 D5 D4 D3 D2 D1 D0
+
+Byte 1 1 0 0 0 0 LB CB RB
+Byte 2 X7 X6 X5 X4 X3 X2 X1 X0
+Byte 3 Y7 Y6 Y5 Y4 Y3 Y4 Y1 Y0
+Byte 4 X7' X6' X5' X4' X3' X2' X1' X0'
+Byte 5 Y7' Y6' Y5' Y4' Y3' Y4' Y1' Y0'
+
+LB is left button state (0=pressed, 1=released)
+CB is center button state (0=pressed, 1=released)
+RB is right button state (0=pressed, 1=released)
+X7-X0 movement in X direction since last packet in signed byte
+ format (-128..+127), positive direction right
+Y7-Y0 movement in Y direction since last packet in signed byte
+ format (-128..+127), positive direction up
+X7'-X0' movement in X direction since sending of X7-X0 packet in signed byte
+ format (-128..+127), positive direction right
+Y7'-Y0' movement in Y direction since sending of Y7-Y0 in signed byte
+ format (-128..+127), positive direction up
+
+The last two bytes in the packet (bytes 4 and 5) contain information
+about movement data changes which have occured after data bytes 2 and
+3 have been sent.
+
+PS/2 mouse
+
+The standard PS/2 mouse (such as the Logitech mouse) defaults to 160 CPI
+and can be switched to 40, 80, 160 or 320 CPI via software. The Microsoft
+mouse driver for Windows 3.x and Windows 95 defaults to 160 counts per
+inch. The maximum tracking rate for PS/2 mouse is 40 reports/second *
+255 counts per report, or 10200 counts per second. A 100 CPI mouse could
+discriminate motion up to 102 inches per second while a 400 CPI mouse
+could discriminate motion up to 25.2 inches per second.
+
+Connector pinout
+
+Pin Wire Name
+1 DATA
+2 Reserved
+3 Ground
+4 +5V Supply
+5 CLK
+6 Reserved
+Shield Chassis
+
+Packet Format
+
+ D7 D6 D5 D4 D3 D2 D1 D0
+Byte 1 XV XV YS XS 1 M R L
+Byte 2 X7 X6 X5 X4 X3 X2 X1 X0
+Byte 3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+
+L Left button state (1 = pressed down)
+M Middle button state (1 = pressed down)
+R Right button state (1 = pressed down)
+X0-X7 Movement in X direction
+Y0-Y7 Movement in Y direction
+XS,YS Movement data sign bits (1 = negative)
+XV,YV Movement data overflow bits (1 = overflow has occured)
+
+Physical connector
+
+The PS/2 mouse connector has the following pinout when looking at the
+connector on the back of the computer:
+
+ 4 u 6
+ 1 . 2
+ 3 5
+
+1. GND
+2. +5V
+3. DATA
+4. CLOCK
+5. Not used
+6. Not used
+
+Bi-directional transmission is controlled by the CLK and DATA lines. Both
+are fed by an open collector device which lets either host or mouse force
+the line to "0". During non-transmission, CLK is at "1" and DATA can be at
+"0" or "1".
+
+The host can inhibit mouse transmission by forcing CLK to "0". If the
+host inhibits the mouse while it is transmitting, the byte must be
+retransmitted (if the inhibit state arrived before the 11th clock).
+
+Receiving data: Check 'clock'. If inactive, there is a bit on the 'data'
+line. Each transmission unit is one start bit, eight data bits, odd
+parity and one stop bit. Start bits are low, stop bits high. Each clock
+active or inactive period is 30 to 50 microseconds. Data transition to
+falling edge of clock is 5 to 25 microseconds.
+
+Sending: Check that both clock and data are high. Pull down data for
+start bit, and start clocking.
+
+NOTE: Logitech has made the extension to this protocol to allow three
+buttons (the M bit is always 0 on 2 button mice).
+
+References
+
+* Original PC mouse info page by Tomi Engdahl
+ http://www.hut.fi/~then/mytexts/mouse.html
+
+* PC Magazine May 28, 1991
+
+* Programmer's Reference to Genius Mouse
+ ftp://x2ftp.oulu.fi/pub/msdos/programming/docs/gmouse.doc
+
+* Logitech Pointing Device Hardware Information Product Support Document # 1410
+ ftp://ftp.logitech.com/pub/TechSupport/MOUSE/HELP/1410.txt
+
+* Mice: How do they work? by Richard Torrens
+ http://box.argonet.co.uk/users/4qd/meece.html
+
+* In Pursuit Of The Perfect Portable Pointer by Intelink Electronics
+from EDN Products Edition April 16, 1977 pages 43-45
+
+* Programming the Microsoft Mouse
+ http://www.geocities.com/SiliconValley/2151/mouse.html
diff --git a/cpukit/libmisc/mouse/mouse_parser.c b/cpukit/libmisc/mouse/mouse_parser.c
new file mode 100644
index 0000000000..9d78bbd979
--- /dev/null
+++ b/cpukit/libmisc/mouse/mouse_parser.c
@@ -0,0 +1,311 @@
+/*
+ * This code is derived from a UNIX Serial Port Mouse Driver with
+ * the following notice:
+ *
+ * ==================================================================
+ * Copyright (c) 1999 Greg Haerr <greg@censoft.com>
+ * Portions Copyright (c) 1991 David I. Bell
+ * Permission is granted to use, distribute, or modify this source,
+ * provided that this copyright notice remains intact.
+ *
+ * UNIX Serial Port Mouse Driver
+ *
+ * This driver opens a serial port directly, and interprets serial data.
+ * Microsoft, PC, Logitech and PS/2 mice are supported. The PS/2 mouse
+ * is only supported if the OS runs the mouse byte codes through the
+ * serial port.
+ *
+ * Mouse Types Supported: pc ms, logi, ps2
+ * ==================================================================
+ *
+ * It has been modified to support the concept of being just a parser
+ * fed data from an arbitrary source. It is independent of either
+ * a PS/2 driver or a serial port.
+ *
+ * It was moved to cpukit/libmisc/mouse by Joel Sherrill.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcmp */
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/mouse_parser.h>
+#include <rtems/mw_uid.h>
+
+/* states for the mouse */
+#define IDLE 0 /* start of byte sequence */
+#define XSET 1 /* setting x delta */
+#define YSET 2 /* setting y delta */
+#define XADD 3 /* adjusting x delta */
+#define YADD 4 /* adjusting y delta */
+
+/* values in the bytes returned by the mouse for the buttons*/
+#define PC_LEFT_BUTTON 4
+#define PC_MIDDLE_BUTTON 2
+#define PC_RIGHT_BUTTON 1
+
+#define MS_LEFT_BUTTON 2
+#define MS_RIGHT_BUTTON 1
+
+#define PS2_CTRL_BYTE 0x08
+#define PS2_LEFT_BUTTON 1
+#define PS2_RIGHT_BUTTON 2
+
+/* Bit fields in the bytes sent by the mouse.*/
+#define TOP_FIVE_BITS 0xf8
+#define BOTTOM_THREE_BITS 0x07
+#define TOP_BIT 0x80
+#define SIXTH_BIT 0x40
+#define BOTTOM_TWO_BITS 0x03
+#define THIRD_FOURTH_BITS 0x0c
+#define BOTTOM_SIX_BITS 0x3f
+
+/* local data */
+static int state; /* IDLE, XSET, ... */
+static BUTTON buttons; /* current mouse buttons pressed*/
+static BUTTON availbuttons; /* which buttons are available */
+static COORD xd; /* change in x */
+static COORD yd; /* change in y */
+
+static int left; /* because the button values change */
+static int middle; /* between mice, the buttons are */
+static int right; /* redefined */
+
+static int (*parse)( int ); /* parse routine */
+
+/* local routines*/
+static int ParsePC(int); /* routine to interpret PC mouse */
+static int ParseMS(int); /* routine to interpret MS mouse */
+static int ParsePS2(int); /* routine to interpret PS/2 mouse */
+
+/*
+ * Open up the mouse device.
+ * Returns the fd if successful, or negative if unsuccessful.
+ */
+int mouse_parser_initialize(const char *type)
+{
+ /* set button bits and parse procedure*/
+ if (!strcmp(type, "pc") || !strcmp(type, "logi")) {
+ /* pc or logitech mouse*/
+ left = PC_LEFT_BUTTON;
+ middle = PC_MIDDLE_BUTTON;
+ right = PC_RIGHT_BUTTON;
+ parse = ParsePC;
+ } else if (strcmp(type, "ms") == 0) {
+ /* microsoft mouse*/
+ left = MS_LEFT_BUTTON;
+ right = MS_RIGHT_BUTTON;
+ middle = 0;
+ parse = ParseMS;
+ } else if (strcmp(type, "ps2") == 0) {
+ /* PS/2 mouse*/
+ left = PS2_LEFT_BUTTON;
+ right = PS2_RIGHT_BUTTON;
+ middle = 0;
+ parse = ParsePS2;
+ } else
+ return -1;
+
+ printk("Device: /dev/mouse -- mouse type is: %s\n", type );
+
+ /* initialize data*/
+ availbuttons = left | middle | right;
+ state = IDLE;
+ buttons = 0;
+ xd = 0;
+ yd = 0;
+ return 0;
+}
+
+/*
+ * Attempt to read bytes from the mouse and interpret them.
+ * Returns -1 on error, 0 if either no bytes were read or not enough
+ * was read for a complete state, or 1 if the new state was read.
+ * When a new state is read, the current buttons and x and y deltas
+ * are returned. This routine does not block.
+ */
+int MOU_Data( int ch, COORD *dx, COORD *dy, COORD *dz, BUTTON *bptr)
+{
+ int b;
+
+ if ( !parse ) {
+ printk( "Mouse parser is not initialized!\n" );
+ return -1;
+ }
+
+ /*
+ * Loop over all the bytes read in the buffer, parsing them.
+ * When a complete state has been read, return the results,
+ * leaving further bytes in the buffer for later calls.
+ */
+ if ( (*parse)( ch ) ) {
+ *dx = xd;
+ *dy = yd;
+ *dz = 0;
+ b = 0;
+ if (buttons & left)
+ b |= LBUTTON;
+ if (buttons & right)
+ b |= RBUTTON;
+ if (buttons & middle)
+ b |= MBUTTON;
+ *bptr = b;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Input routine for PC mouse.
+ * Returns nonzero when a new mouse state has been completed.
+ */
+static int ParsePC(int byte)
+{
+ int sign; /* sign of movement */
+
+ switch (state) {
+ case IDLE:
+ if ((byte & TOP_FIVE_BITS) == TOP_BIT) {
+ buttons = ~byte & BOTTOM_THREE_BITS;
+ state = XSET;
+ }
+ break;
+
+ case XSET:
+ sign = 1;
+ if (byte > 127) {
+ byte = 256 - byte;
+ sign = -1;
+ }
+ xd = byte * sign;
+ state = YSET;
+ break;
+
+ case YSET:
+ sign = 1;
+ if (byte > 127) {
+ byte = 256 - byte;
+ sign = -1;
+ }
+ yd = -byte * sign;
+ state = XADD;
+ break;
+
+ case XADD:
+ sign = 1;
+ if (byte > 127) {
+ byte = 256 - byte;
+ sign = -1;
+ }
+ xd += byte * sign;
+ state = YADD;
+ break;
+
+ case YADD:
+ sign = 1;
+ if (byte > 127) {
+ byte = 256 - byte;
+ sign = -1;
+ }
+ yd -= byte * sign;
+ state = IDLE;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Input routine for Microsoft mouse.
+ * Returns nonzero when a new mouse state has been completed.
+ */
+static int ParseMS(int byte)
+{
+ switch (state) {
+ case IDLE:
+ if (byte & SIXTH_BIT) {
+ buttons = (byte >> 4) & BOTTOM_TWO_BITS;
+ yd = ((byte & THIRD_FOURTH_BITS) << 4);
+ xd = ((byte & BOTTOM_TWO_BITS) << 6);
+ state = XADD;
+ }
+ break;
+
+ case XADD:
+ xd |= (byte & BOTTOM_SIX_BITS);
+ state = YADD;
+ break;
+
+ case YADD:
+ yd |= (byte & BOTTOM_SIX_BITS);
+ state = IDLE;
+ if (xd > 127)
+ xd -= 256;
+ if (yd > 127)
+ yd -= 256;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Input routine for PS/2 mouse.
+ * Returns nonzero when a new mouse state has been completed.
+ */
+static int ParsePS2(int byte)
+{
+ switch (state) {
+ case IDLE:
+ if (byte & PS2_CTRL_BYTE) {
+ buttons = byte &
+ (PS2_LEFT_BUTTON|PS2_RIGHT_BUTTON);
+ state = XSET;
+ }
+ break;
+
+ case XSET:
+ if(byte > 127)
+ byte -= 256;
+ xd = byte;
+ state = YSET;
+ break;
+
+ case YSET:
+ if(byte > 127)
+ byte -= 256;
+ yd = -byte;
+ state = IDLE;
+ return 1;
+ }
+ return 0;
+}
+
+/* generic mouse parser */
+void mouse_parser_enqueue( unsigned char *buffer, size_t size )
+{
+ COORD dx;
+ COORD dy;
+ COORD dz;
+ BUTTON bptr;
+
+ while( size-- ) {
+ if ( MOU_Data( *buffer++, &dx, &dy, &dz, &bptr ) ) {
+ struct MW_UID_MESSAGE m;
+
+ m.type = MV_UID_REL_POS;
+ /* buttons definitons have been selected to match */
+ m.m.pos.btns = bptr;
+ m.m.pos.x = dx;
+ m.m.pos.y = dy;
+ m.m.pos.z = dz;
+ /* printk( "Mouse: msg: dx=%d, dy=%d, btn=%X\n", dx, dy, bptr ); */
+ uid_send_message( &m );
+ }
+ }
+}
+
diff --git a/cpukit/libmisc/mouse/mouse_parser.h b/cpukit/libmisc/mouse/mouse_parser.h
new file mode 100644
index 0000000000..59b6abb2f3
--- /dev/null
+++ b/cpukit/libmisc/mouse/mouse_parser.h
@@ -0,0 +1,108 @@
+/*
+ * This file is the header file for the Mouse Parser Engine which
+ * is derived from a UNIX Serial Port Mouse Driver with the following
+ * notice:
+ *
+ * ==================================================================
+ * Copyright (c) 1999 Greg Haerr <greg@censoft.com>
+ * Portions Copyright (c) 1991 David I. Bell
+ * Permission is granted to use, distribute, or modify this source,
+ * provided that this copyright notice remains intact.
+ *
+ * UNIX Serial Port Mouse Driver
+ *
+ * This driver opens a serial port directly, and interprets serial data.
+ * Microsoft, PC, Logitech and PS/2 mice are supported. The PS/2 mouse
+ * is only supported if the OS runs the mouse byte codes through the
+ * serial port.
+ *
+ * Mouse Types Supported: pc ms, logi, ps2
+ * ==================================================================
+ *
+ * It has been modified to support the concept of being just a parser
+ * fed data from an arbitrary source. It is independent of either
+ * a PS/2 driver or a serial port.
+ *
+ * It was moved to cpukit/libmisc/mouse by Joel Sherrill.
+ *
+ * $Id$
+ */
+
+#ifndef __MOUSE_PARSER_h__
+#define __MOUSE_PARSER_h__
+
+#include <rtems/mw_uid.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This is the mask for the right button.
+ *
+ * @note Use the same definitions as the user interface.
+ */
+#define RBUTTON MV_BUTTON_RIGHT
+
+/**
+ * This is the mask for the center button.
+ *
+ * @note Use the same definitions as the user interface.
+ */
+#define MBUTTON MV_BUTTON_CENTER
+
+/**
+ * This is the mask for the left button.
+ *
+ * @note Use the same definitions as the user interface.
+ */
+#define LBUTTON MV_BUTTON_LEFT
+
+/**
+ * This type is the device coordinates.
+ */
+typedef int COORD;
+
+/**
+ * This type is the mouse button mask.
+ */
+typedef unsigned int BUTTON;
+
+/**
+ * This type defines a pointer to the enqueue method. It is
+ * available since some device drivers keep pointers to the method
+ * to know when to enqueue or not.
+ */
+typedef void (*mouse_parser_enqueue_handler)(unsigned char *, size_t);
+
+/**
+ * @brief Initialize the Mouse Parser Engine
+ *
+ * This method initializes the Mouse Parser Engine for the mouse
+ * of @a type. The @a type should be one of the following strings:
+ * pc ms, logi, ps2.
+ *
+ * @a param[in] type indicates the type of mouse.
+ *
+ * @return This method returns 0 on success and -1 on error.
+ */
+int mouse_parser_initialize(const char *type);
+
+/**
+ * @brief Enqueue Input to the Mouse Parser Engine
+ *
+ * This method is used to pass mouse input to the Mouse Parser Engine.
+ *
+ * @a param[in] buffer is the data to enqueue
+ * @a param[in] size is the amount of data to enqueue
+ */
+void mouse_parser_enqueue(
+ unsigned char *buffer,
+ size_t size
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/mouse/serial_mouse.c b/cpukit/libmisc/mouse/serial_mouse.c
new file mode 100644
index 0000000000..c61401626d
--- /dev/null
+++ b/cpukit/libmisc/mouse/serial_mouse.c
@@ -0,0 +1,184 @@
+/*
+ * COPYRIGHT (c) 1989-2011.
+ * 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$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <rtems/libio.h>
+#include <termios.h>
+#include <rtems/termiostypes.h>
+#include <rtems/mouse_parser.h>
+#include <rtems/serial_mouse.h>
+
+int serial_mouse_fd = -1;
+const char *serial_mouse_device;
+const char *serial_mouse_type;
+
+int serial_mouse_l_rint(int c, struct rtems_termios_tty *tp)
+{
+ unsigned char buf = c;
+
+ /* call mouse_parser( void *ptr, char *buffer, int size ) */
+ mouse_parser_enqueue( &buf, 1 );
+ return 0;
+}
+
+static struct rtems_termios_linesw serial_mouse_linesw = {
+ .l_open = NULL,
+ .l_close = NULL,
+ .l_read = NULL,
+ .l_write = NULL,
+ .l_rint = serial_mouse_l_rint,
+ .l_start = NULL,
+ .l_ioctl = NULL,
+ .l_modem = NULL
+};
+
+
+/*
+ * Serial Mouse - device driver INITIALIZE entry point.
+ */
+rtems_device_driver serial_mouse_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ bool status;
+
+ status = bsp_get_serial_mouse_device(
+ &serial_mouse_device,
+ &serial_mouse_type
+ );
+
+ (void) rtems_io_register_name( "/dev/mouse", major, 0 );
+
+ rtems_termios_linesw[ 6 ] = serial_mouse_linesw;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * serial_mouse - device driver OPEN entry point
+ */
+rtems_device_driver serial_mouse_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *args
+)
+{
+ struct termios termios_attr;
+ int status;
+ int disc = 6;
+
+ /* XXX open(2) the configured /dev/comX */
+ /* XXX save the file descriptor */
+ serial_mouse_fd = open( serial_mouse_device, O_RDONLY );
+ if ( serial_mouse_fd == -1 ) {
+ printk(
+ "Error opening serial_mouse device on %s\n",
+ serial_mouse_device
+ );
+ return RTEMS_IO_ERROR;
+ }
+
+ /* 1200-8-N-1, without hardware flow control */
+ /* BSP_uart_init( BSP_UART_PORT, 1200, CHR_8_BITS, 0, 0, 0 ); */
+ status = tcgetattr(serial_mouse_fd, &termios_attr );
+ if (status != 0) {
+ printk("Error getting mouse attributes\n");
+ return RTEMS_IO_ERROR;
+ }
+ termios_attr.c_lflag &= ~(ICANON|ECHO|ECHONL|ECHOK|ECHOE|ECHOPRT|ECHOCTL);
+ termios_attr.c_iflag &= ~(IXON|IXANY|IXOFF);
+ /*
+ termios_attr.c_cc[VMIN] = itask_VMIN;
+ termios_attr.c_cc[VTIME] = itask_VTIME;
+ */
+ termios_attr.c_cflag |= B1200;
+ termios_attr.c_cflag |= CS8;
+ status = tcsetattr( serial_mouse_fd, TCSANOW, &termios_attr );
+ if (status != 0) {
+ printk("Error setting mouse attributes\n");
+ return RTEMS_IO_ERROR;
+ }
+
+ status = ioctl(serial_mouse_fd, TIOCSETD, &disc);
+ if (status != 0) {
+ printk("Error setting mouse attributes\n");
+ return RTEMS_IO_ERROR;
+ }
+
+ sleep(5);
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver serial_mouse_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ close( serial_mouse_fd );
+
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver serial_mouse_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+
+rtems_device_driver serial_mouse_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+
+rtems_device_driver serial_mouse_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_libio_ioctl_args_t *args = (rtems_libio_ioctl_args_t *)arg;
+
+ switch( args->command ) {
+
+ case MW_UID_REGISTER_DEVICE:
+ printk( "SerialMouse: reg=%s\n", args->buffer );
+ mouse_parser_initialize( serial_mouse_type );
+ break;
+
+ case MW_UID_UNREGISTER_DEVICE:
+ break;
+
+ default:
+ args->ioctl_return = ioctl(serial_mouse_fd, args->command, args->buffer );
+ if ( !args->ioctl_return )
+ return RTEMS_SUCCESSFUL;
+ return RTEMS_IO_ERROR;
+ }
+ args->ioctl_return = 0;
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/mouse/serial_mouse.h b/cpukit/libmisc/mouse/serial_mouse.h
new file mode 100644
index 0000000000..65e98089cb
--- /dev/null
+++ b/cpukit/libmisc/mouse/serial_mouse.h
@@ -0,0 +1,156 @@
+/**
+ * @file rtems/serial_mouse.h
+ *
+ * This file describes the Serial Mouse Driver for all boards.
+ * This driver assumes that the BSP or application will provide
+ * an implementation of the method bsp_get_serial_mouse_device()
+ * which tells the driver what serial port device to open() and
+ * what type of mouse is connected.
+ *
+ * This driver relies on the Mouse Parser Engine.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2011.
+ * 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 __SERIAL_MOUSE_h__
+#define __SERIAL_MOUSE_h__
+
+/* functions */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This macro defines the serial mouse device driver entry points.
+ */
+#define SERIAL_MOUSE_DRIVER_TABLE_ENTRY \
+ { serial_mouse_initialize, serial_mouse_open, serial_mouse_close, \
+ serial_mouse_read, serial_mouse_write, serial_mouse_control }
+
+/**
+ * @brief Serial Mouse Driver Initialization
+ *
+ * This method initializes the serial mouse driver.
+ *
+ * @param[in] major is the mouse device major number
+ * @param[in] minor is the mouse device minor number
+ * @param[in] arguments points to device driver arguments
+ */
+rtems_device_driver serial_mouse_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
+
+/**
+ * @brief Serial Mouse Driver Open
+ *
+ * This method implements the Open device driver entry
+ * point for the serial mouse driver.
+ *
+ * @param[in] major is the mouse device major number
+ * @param[in] minor is the mouse device minor number
+ * @param[in] arguments points to device driver arguments
+ */
+rtems_device_driver serial_mouse_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
+
+/**
+ * @brief Serial Mouse Driver Close
+ *
+ * This method implements the Close device driver entry
+ * point for the serial mouse driver.
+ *
+ * @param[in] major is the mouse device major number
+ * @param[in] minor is the mouse device minor number
+ * @param[in] arguments points to device driver arguments
+ */
+rtems_device_driver serial_mouse_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
+
+/**
+ * @brief Serial Mouse Driver Read
+ *
+ * This method implements the Read device driver entry
+ * point for the serial mouse driver.
+ *
+ * @param[in] major is the mouse device major number
+ * @param[in] minor is the mouse device minor number
+ * @param[in] arguments points to device driver arguments
+ */
+rtems_device_driver serial_mouse_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
+
+/**
+ * @brief Serial Mouse Driver Write
+ *
+ * This method implements the Write device driver entry
+ * point for the serial mouse driver.
+ *
+ * @param[in] major is the mouse device major number
+ * @param[in] minor is the mouse device minor number
+ * @param[in] arguments points to device driver arguments
+ */
+rtems_device_driver serial_mouse_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
+
+/**
+ * @brief Serial Mouse Driver IO Control
+ *
+ * This method implements the IO Control device driver entry
+ * point for the serial mouse driver.
+ *
+ * @param[in] major is the mouse device major number
+ * @param[in] minor is the mouse device minor number
+ * @param[in] arguments points to device driver arguments
+ */
+rtems_device_driver serial_mouse_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
+
+/**
+ * @brief Obtain Serial Mouse Configuration Information
+ *
+ * This method is implemented by the BSP or application and
+ * tells the driver what device to open() and what type of
+ * mouse is connected.
+ *
+ * @param[in] name will point to a string with the device name
+ * of the serial port with the mouse connected.
+ * @param[in] type will point to a string with the type of mouse connected.
+ *
+ * @return This method returns true on success and false on error.
+ */
+bool bsp_get_serial_mouse_device(
+ const char **name,
+ const char **type
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __tty_drv__ */
diff --git a/cpukit/libmisc/preinstall.am b/cpukit/libmisc/preinstall.am
new file mode 100644
index 0000000000..f6a7e763d2
--- /dev/null
+++ b/cpukit/libmisc/preinstall.am
@@ -0,0 +1,9 @@
+## Automatically generated by ampolish3 - Do not edit
+
+if AMPOLISH3
+$(srcdir)/preinstall.am: Makefile.am
+ $(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am
+endif
+
+if LIBSHELL
+endif
diff --git a/cpukit/libmisc/serdbg/README b/cpukit/libmisc/serdbg/README
new file mode 100644
index 0000000000..338249c928
--- /dev/null
+++ b/cpukit/libmisc/serdbg/README
@@ -0,0 +1,138 @@
+#
+# $Id$
+#
+
+This directory contains three useful packages related to the termios I/O
+system:
+
+PACKAGE SERDBGIO
+================
+"serdbgio" provides the "serial gdb" standard I/O functions "getDebugChar"
+and "putDebugChar" for any device driver supporting polled termios mode.
+
+The initialization function "serdbg_open" opens the v.24 port intended
+for the serial debug connection, and sets the desired baud rate. The
+"getDebugChar" and "putDebugChar" functions then interact with the
+corresponding driver using the calls intended for polled termios
+operation.
+
+Specification for the debug device, baud rate and other parameters is
+done in a global structure of type "serdbg_conf_t". A configuration
+mechanism quite similar to the overall RTEMS configuration is available.
+
+PACKAGE SERDBG
+==============
+"serdbg" provides a means to optionally initialize and/or start a
+serial gdb session as soon as possible, this means as soon as all
+drivers have been initialized. The serial debug I/O functions can
+either be integrated as special routines of the BSP drivers, or using
+the package "serdbgio"
+
+PACKAGE TERMIOS_PRINTK
+======================
+"termios_printk" provides a standard output function suitable to use
+with "printk". It uses the same technique as serdbgio, hooking the
+interface between a polled device driver and the termios system.
+
+
+REQUIREMENTS
+============
+
+- These two packages can be used with any polled termios device
+driver.
+- For standard initialization, they need a modified "bsppost.c"
+to perform the initialization calls.
+
+USAGE
+=====
+
+For using these packages add the following to your "init" module or
+your "system.h" file (Note: most macro settings fall back to a
+default, if not set.):
+
+/*
+ * CONFIGURE_USE_SERDBG
+ * set this macro, if you want to connect gdb over a serial line
+ * when set, the debug stub will be connected after driver
+ * initialization in "bsppost.c"
+ */
+#define CONFIGURE_USE_SERDBG
+
+
+/*
+ * CONFIGURE_SERDBG_SKIP_INIT_BKPT
+ * set this macro, if you do not want the gdb interface to wait for a
+ * debugger connection directly after initialization
+ * If you set this macro, the gdb stub will only hook various
+ * exception vectors when called from "bsppost.c".
+ */
+/* #define CONFIGURE_SERDBG_SKIP_INIT_BKPT */
+
+/*
+ * CONFIGURE_SERDBG_USE_POLLED_TERMIOS
+ * set this macro, if you want "serdbgio" to provide the I/O
+ * functions for the serial gdb connection
+ */
+#define CONFIGURE_SERDBG_USE_POLLED_TERMIOS
+
+/*
+ * CONFIGURE_SERDBG_DEVNAME
+ * use this macro to specify the serial device to use
+ * for "serdbgio".
+ * Only used, when CONFIGURE_SERDBG_USE_POLLED_TERMIOS is set
+ */
+#define CONFIGURE_SERDBG_DEVNAME "/dev/tty03"
+
+/*
+ * CONFIGURE_SERDBG_BAUDRATE
+ * use this macro to specify the baud rate to use
+ * for "serdbgio".
+ * Only used, when CONFIGURE_SERDBG_USE_POLLED_TERMIOS is set
+ */
+#define CONFIGURE_SERDBG_BAUDRATE 57600
+
+/*
+ * CONFIGURE_SERDBG_CALLOUT
+ * use this macro to specify a routine that will called during I/O polling
+ * Only used, when CONFIGURE_SERDBG_USE_POLLED_TERMIOS is set
+ * This function of type "void pollfnc(void)" can be used for e.g.
+ * tickling a watchdog
+ */
+/* #define CONFIGURE_SERDBG_CALLOUT tickle_my_watchdog_fnc */
+
+#include <serdbgcnf.h>
+
+/*
+ * CONFIGURE_USE_TERMIOS_PRINTK
+ * set this macro, if you want printk output to be sent to a serial
+ * driver using the polled termios interface
+ * when set, the printk output function will be connected after driver
+ * initialization in "bsppost.c"
+ */
+#define CONFIGURE_USE_TERMIOS_PRINTK
+
+/*
+ * CONFIGURE_TERMIOS_PRINTK_DEVNAME
+ * use this macro to specify the serial device to use
+ * for printk output.
+ * Only used, when CONFIGURE_USE_TERMIOS_PRINTK is set
+ */
+#define CONFIGURE_TERMIOS_PRINTK_DEVNAME "/dev/console"
+
+/*
+ * CONFIGURE_TERMIOS_PRINTK_BAUDRATE
+ * use this macro to specify the baudrate to use
+ * for printk output.
+ * Only used, when CONFIGURE_USE_TERMIOS_PRINTK is set
+ */
+#define CONFIGURE_TERMIOS_PRINTK_BAUDRATE 9600
+
+/*
+ * CONFIGURE_TERMIOS_PRINTK_CALLOUT
+ * use this macro to specify a routine that will called during I/O polling
+ * This function of type "void pollfnc(void)" can be used for e.g.
+ * tickling a watchdog
+ */
+/* #define CONFIGURE_TERMIOS_PRINTK_CALLOUT tickle_my_watchdog_fnc */
+
+#include <termios_printk_cnf.h>
diff --git a/cpukit/libmisc/serdbg/serdbg.c b/cpukit/libmisc/serdbg/serdbg.c
new file mode 100644
index 0000000000..2f9abf6824
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbg.c
@@ -0,0 +1,92 @@
+/*===============================================================*\
+| Project: RTEMS remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: serdbg.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file contains intialization and utility functions to add |
+| a gdb remote debug stub to an RTEMS system |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 04.04.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <rtems/serdbg.h>
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_init_dbg
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| initialize remote gdb session over serial line |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+{
+ static bool is_initialized = false;
+
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+ if (is_initialized) {
+ return RTEMS_SUCCESSFUL;
+ }
+ is_initialized = true;
+ /*
+ * try to open serial device
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ if ((serdbg_conf.open_io != NULL) &&
+ (0 > serdbg_conf.open_io(serdbg_conf.devname,serdbg_conf.baudrate))) {
+ fprintf(stderr,
+ "remote_gdb_init: cannot open device %s "
+ "for gdb connection:%s\n",serdbg_conf.devname,strerror(errno));
+ rc = RTEMS_IO_ERROR;
+ }
+ }
+ /*
+ * initialize gdb stub
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ set_debug_traps();
+ }
+ /*
+ * now activate gdb stub
+ */
+ if ((rc == RTEMS_SUCCESSFUL) &&
+ !serdbg_conf.skip_init_bkpt) {
+ breakpoint();
+ }
+
+ /*
+ * return to original function
+ * this may be already unter gdb control
+ */
+ return rc;
+}
diff --git a/cpukit/libmisc/serdbg/serdbg.h b/cpukit/libmisc/serdbg/serdbg.h
new file mode 100644
index 0000000000..375b03b5d5
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbg.h
@@ -0,0 +1,187 @@
+/*===============================================================*\
+| Project: RTEMS remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: serdbg.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| a gdb remote debug stub to an RTEMS system |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 04.04.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _SERDBG_H
+#define _SERDBG_H
+
+#include <rtems.h>
+#include <termios.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ uint32_t baudrate; /* debug baud rate, e.g. 57600 */
+ void (*callout)(void); /* callout pointer during polling */
+ int (*open_io)(const char *dev_name, uint32_t baudrate); /* I/O open fnc */
+ const char *devname; /* debug device, e.g. "/dev/tty01" */
+ bool skip_init_bkpt; /* if TRUE, do not stop when initializing */
+} serdbg_conf_t;
+
+/*
+ * must be defined in init module...
+ */
+extern serdbg_conf_t serdbg_conf;
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void putDebugChar
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send character to remote debugger |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ char c /* char to send */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int getDebugChar
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| get character from remote debugger |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void /* <none> */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void serdbg_exceptionHandler
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| hook directly to an exception vector |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ int vecnum, /* vector index to hook at */
+ void *vector /* address of handler function */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_init
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| initialize remote gdb session over serial line |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+
+/*
+ * stuff from serdbgio.c
+ */
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void putDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int getDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+
+/*
+ * Assumed to be provided by the BSP
+ */
+extern void set_debug_traps(void);
+extern void breakpoint(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SERDBG_H */
diff --git a/cpukit/libmisc/serdbg/serdbgcnf.h b/cpukit/libmisc/serdbg/serdbgcnf.h
new file mode 100644
index 0000000000..3820f61f8a
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbgcnf.h
@@ -0,0 +1,89 @@
+/*===============================================================*\
+| Project: RTEMS configure remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: serdbgcnf.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| a gdb remote debug stub to an RTEMS system |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.05.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _SERDBGCNF_H
+#define _SERDBGCNF_H
+
+#include <rtems/serdbg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CONFIGURE_INIT
+
+/*
+ * fallback for baud rate to use
+ */
+#ifndef CONFIGURE_SERDBG_BAUDRATE
+#define CONFIGURE_SERDBG_BAUDRATE 9600
+#endif
+
+/*
+ * fallback for device name to use
+ */
+#ifndef CONFIGURE_SERDBG_DEVNAME
+#define CONFIGURE_SERDBG_DEVNAME "/dev/tty01"
+#endif
+
+/*
+ * fill in serdbg_conf structure
+ */
+serdbg_conf_t serdbg_conf = {
+ CONFIGURE_SERDBG_BAUDRATE,
+
+#ifdef CONFIGURE_SERDBG_CALLOUT
+ CONFIGURE_SERDBG_CALLOUT,
+#else
+ NULL,
+#endif
+
+#ifdef CONFIGURE_SERDBG_USE_POLLED_TERMIOS
+ serdbg_open,
+#else
+ NULL,
+#endif
+
+ CONFIGURE_SERDBG_DEVNAME,
+
+#ifdef CONFIGURE_SERDBG_SKIP_INIT_BKPT
+ true,
+#else
+ false,
+#endif
+};
+
+int serdbg_init(void) {
+#ifdef CONFIGURE_USE_SERDBG
+ extern int serdbg_init_dbg(void);
+ return serdbg_init_dbg();
+#else
+ return 0;
+#endif
+}
+
+#endif /* CONFIGURE_INIT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SERDBGCNF_H */
diff --git a/cpukit/libmisc/serdbg/serdbgio.c b/cpukit/libmisc/serdbg/serdbgio.c
new file mode 100644
index 0000000000..6ab5b3c716
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbgio.c
@@ -0,0 +1,256 @@
+/*===============================================================*\
+| File: serdbgio.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| Hebststr. 8, 82178 Puchheim, Germany |
+| <Thomas.Doerfler@imd-systems.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. |
+| all rights reserved |
++-----------------------------------------------------------------+
+| TERMIOS serial gdb interface support |
+| the functions in this file allow the standard gdb stubs like |
+| "m68k-stub.c" to access any serial interfaces that work with |
+| RTEMS termios in polled mode |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 10.05.02 creation doe |
+|*****************************************************************|
+|* $Id$
+ *
+|*****************************************************************|
+\*===============================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <errno.h>
+#include <unistd.h> /* close */
+#include <stdio.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#include <rtems/termiostypes.h>
+#include <rtems/serdbg.h>
+
+
+/*
+ * internal variables
+ */
+int serdbg_fd = -1;
+struct rtems_termios_tty *serdbg_tty;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+{
+ bool err_occurred = false;
+ rtems_libio_t *iop = NULL;
+ struct termios act_termios;
+ tcflag_t baudcode = B0;
+
+#define FD_STORE_CNT 3
+ int fd_store[FD_STORE_CNT];
+ int fd_store_used = 0;
+
+ /*
+ * translate baudrate into baud code
+ */
+ switch(baudrate) {
+ case 50: baudcode = B50; break;
+ case 75: baudcode = B75; break;
+ case 110: baudcode = B110; break;
+ case 134: baudcode = B134; break;
+ case 150: baudcode = B150; break;
+ case 200: baudcode = B200; break;
+ case 300: baudcode = B300; break;
+ case 600: baudcode = B600; break;
+ case 1200: baudcode = B1200; break;
+ case 1800: baudcode = B1800; break;
+ case 2400: baudcode = B2400; break;
+ case 4800: baudcode = B4800; break;
+ case 9600: baudcode = B9600; break;
+ case 19200: baudcode = B19200; break;
+ case 38400: baudcode = B38400; break;
+ case 57600: baudcode = B57600; break;
+ case 115200: baudcode = B115200; break;
+ case 230400: baudcode = B230400; break;
+ case 460800: baudcode = B460800; break;
+ default : err_occurred = true; errno = EINVAL; break;
+ }
+
+ /*
+ * open device for serdbg operation
+ * skip any fds that are between 0..2, because they are
+ * reserved for stdin/out/err
+ */
+ if (!err_occurred &&
+ (dev_name != NULL) &&
+ (dev_name[0] != '\0')) {
+ do {
+ serdbg_fd = open(dev_name,O_RDWR);
+ if (serdbg_fd < 0) {
+ err_occurred = true;
+ }
+ else {
+ if (serdbg_fd < 3) {
+ if (fd_store_used >= FD_STORE_CNT) {
+ err_occurred = true;
+ }
+ else {
+ fd_store[fd_store_used++] = serdbg_fd;
+ }
+ }
+ }
+ } while (!err_occurred &&
+ (serdbg_fd < 3));
+ }
+ /*
+ * close any fds, that have been placed in fd_store
+ * so fd 0..2 are reusable again
+ */
+ while (--fd_store_used >= 0) {
+ close(fd_store[fd_store_used]);
+ }
+
+ /*
+ * capture tty structure
+ */
+ if (!err_occurred) {
+ iop = &rtems_libio_iops[serdbg_fd];
+ serdbg_tty = iop->data1;
+ }
+ /*
+ * set device baudrate
+ * (and transp mode, this is not really needed)
+ * ...
+ */
+ /*
+ * ... get fd settings
+ */
+ if (!err_occurred &&
+ (0 != tcgetattr(serdbg_fd,&act_termios))) {
+ err_occurred = true;
+ }
+ if (!err_occurred) {
+ act_termios.c_iflag
+ &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+ |INLCR|IGNCR|ICRNL|IXON);
+ act_termios.c_oflag
+ &= ~OPOST;
+
+ act_termios.c_lflag
+ &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+
+ cfsetospeed(&act_termios,baudcode);
+ cfsetispeed(&act_termios,baudcode);
+
+ if (0 != tcsetattr(serdbg_fd,TCSANOW,&act_termios)) {
+ err_occurred = true;
+ }
+ }
+ return (err_occurred
+ ? -1
+ : 0);
+}
+
+void putDebugChar(char c) __attribute__ ((__weak__));
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void putDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ /*
+ * call serdbg polling callout, if available
+ */
+ if (serdbg_conf.callout != NULL) {
+ serdbg_conf.callout();
+ }
+ /*
+ * check, whether debug serial port is available
+ */
+ if ((serdbg_tty != NULL) &&
+ (serdbg_tty->device.write != NULL)) {
+ /*
+ * send character to debug serial port
+ */
+ serdbg_tty->device.write(serdbg_tty->minor,&c,1);
+ }
+}
+
+int getDebugChar(void) __attribute__ ((__weak__));
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int getDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+{
+ int c = -1;
+ /*
+ * check, whether debug serial port is available
+ */
+ if ((serdbg_tty != NULL) &&
+ (serdbg_tty->device.pollRead != NULL)) {
+ do {
+ /*
+ * call serdbg polling callout, if available
+ */
+ if (serdbg_conf.callout != NULL) {
+ serdbg_conf.callout();
+ }
+ /*
+ * get character from debug serial port
+ */
+ c = serdbg_tty->device.pollRead(serdbg_tty->minor);
+ } while (c < 0);
+ }
+ return c;
+}
diff --git a/cpukit/libmisc/serdbg/termios_printk.c b/cpukit/libmisc/serdbg/termios_printk.c
new file mode 100644
index 0000000000..bcbfe482fa
--- /dev/null
+++ b/cpukit/libmisc/serdbg/termios_printk.c
@@ -0,0 +1,241 @@
+/*===============================================================*\
+| File: termios_printk.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| Hebststr. 8, 82178 Puchheim, Germany |
+| <Thomas.Doerfler@imd-systems.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. |
+| all rights reserved |
++-----------------------------------------------------------------+
+| TERMIOS printk support |
+| this module performs low-level printk output using |
+| a polled termios driver |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.05.02 creation doe |
+|*****************************************************************|
+|* $Id$
+ *
+|*****************************************************************|
+\*===============================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#include <rtems/termiostypes.h>
+#include <rtems/bspIo.h>
+#include <rtems/termios_printk.h>
+
+/*
+ * internal variables
+ */
+int termios_printk_fd = -1;
+struct rtems_termios_tty *termios_printk_tty;
+
+static void _termios_printk_null_char(
+ char c __attribute__((unused)))
+{
+ return;
+}
+
+BSP_output_char_function_type BSP_output_char = _termios_printk_null_char;
+BSP_polling_getchar_function_type BSP_poll_char;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void termios_printk_outputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ static const char cr = '\r';
+ /*
+ * check, whether printk serial port is available
+ */
+
+ if ((termios_printk_tty != NULL) &&
+ (termios_printk_tty->device.write != NULL)) {
+ /*
+ * call termios_printk polling callout, if available
+ */
+ if (termios_printk_conf.callout != NULL) {
+ termios_printk_conf.callout();
+ }
+ /*
+ * send character to debug serial port
+ */
+ if (c == '\n') {
+ termios_printk_tty->device.write(termios_printk_tty->minor,&cr,1);
+ }
+ termios_printk_tty->device.write(termios_printk_tty->minor,&c,1);
+ }
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int termios_printk_inputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+{
+ int c = -1;
+ /*
+ * check, whether debug serial port is available
+ */
+ if ((termios_printk_tty != NULL) &&
+ (termios_printk_tty->device.pollRead != NULL)) {
+ do {
+ /*
+ * call termios_printk polling callout, if available
+ */
+ if (termios_printk_conf.callout != NULL) {
+ termios_printk_conf.callout();
+ }
+ /*
+ * get character from debug serial port
+ */
+ c = termios_printk_tty->device.pollRead(termios_printk_tty->minor);
+ } while (c < 0);
+ }
+ return c;
+}
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int termios_printk_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+{
+ bool err_occurred = false;
+ rtems_libio_t *iop = NULL;
+ struct termios act_termios;
+ tcflag_t baudcode = B0;
+
+ if (termios_printk_fd >= 0) {
+ /*
+ * already initialized
+ */
+ return 0;
+ }
+ /*
+ * translate baudrate into baud code
+ */
+ switch(baudrate) {
+ case 50: baudcode = B50; break;
+ case 75: baudcode = B75; break;
+ case 110: baudcode = B110; break;
+ case 134: baudcode = B134; break;
+ case 150: baudcode = B150; break;
+ case 200: baudcode = B200; break;
+ case 300: baudcode = B300; break;
+ case 600: baudcode = B600; break;
+ case 1200: baudcode = B1200; break;
+ case 1800: baudcode = B1800; break;
+ case 2400: baudcode = B2400; break;
+ case 4800: baudcode = B4800; break;
+ case 9600: baudcode = B9600; break;
+ case 19200: baudcode = B19200; break;
+ case 38400: baudcode = B38400; break;
+ case 57600: baudcode = B57600; break;
+ case 115200: baudcode = B115200; break;
+ case 230400: baudcode = B230400; break;
+ case 460800: baudcode = B460800; break;
+ default : err_occurred = true; errno = EINVAL; break;
+ }
+ /*
+ * open device for serdbg operation
+ */
+ if (!err_occurred &&
+ (dev_name != NULL) &&
+ (dev_name[0] != '\0')) {
+ termios_printk_fd = open(dev_name,O_RDWR);
+ if (termios_printk_fd < 0) {
+ err_occurred = true;
+ }
+ }
+ /*
+ * capture tty structure
+ */
+ if (!err_occurred) {
+ iop = &rtems_libio_iops[termios_printk_fd];
+ termios_printk_tty = iop->data1;
+ }
+ /*
+ * set device baudrate
+ * (and transp mode, this is not really needed)
+ * ...
+ */
+ /*
+ * ... get fd settings
+ */
+ if (!err_occurred &&
+ (0 != tcgetattr(termios_printk_fd,&act_termios))) {
+ err_occurred = true;
+ }
+ if (!err_occurred) {
+
+ cfsetospeed(&act_termios,baudcode);
+ cfsetispeed(&act_termios,baudcode);
+
+ if (0 != tcsetattr(termios_printk_fd,TCSANOW,&act_termios)) {
+ err_occurred = true;
+ }
+ }
+ if (!err_occurred) {
+ BSP_output_char = termios_printk_outputchar;
+ BSP_poll_char = termios_printk_inputchar;
+ }
+ return (err_occurred
+ ? -1
+ : 0);
+}
diff --git a/cpukit/libmisc/serdbg/termios_printk.h b/cpukit/libmisc/serdbg/termios_printk.h
new file mode 100644
index 0000000000..4f484df62f
--- /dev/null
+++ b/cpukit/libmisc/serdbg/termios_printk.h
@@ -0,0 +1,104 @@
+/*===============================================================*\
+| Project: RTEMS remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: termios_printk.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| printk polled output via termios polled drivers |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.04.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _TERMIOS_PRINTK_H
+#define _TERMIOS_PRINTK_H
+
+#include <rtems.h>
+#include <termios.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ uint32_t baudrate; /* debug baud rate, e.g. 57600 */
+ void (*callout)(void); /* callout pointer during polling */
+ const char *devname; /* debug device, e.g. "/dev/tty01" */
+} termios_printk_conf_t;
+
+/*
+ * must be defined in init module...
+ */
+extern termios_printk_conf_t termios_printk_conf;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void termios_printk_outputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int termios_printk_inputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int termios_printk_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TERMIOS_PRINTK_H */
diff --git a/cpukit/libmisc/serdbg/termios_printk_cnf.h b/cpukit/libmisc/serdbg/termios_printk_cnf.h
new file mode 100644
index 0000000000..2e8a7ac043
--- /dev/null
+++ b/cpukit/libmisc/serdbg/termios_printk_cnf.h
@@ -0,0 +1,78 @@
+/*===============================================================*\
+| Project: RTEMS configure remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: termios_printk_cnf.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| printk support via polled termios |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.05.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _TERMIOS_PRINTK_CNF_H
+#define _TERMIOS_PRINTK_CNF_H
+
+#include <rtems/termios_printk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CONFIGURE_INIT
+
+/*
+ * fallback for baud rate to use
+ */
+#ifndef CONFIGURE_TERMIOS_PRINTK_BAUDRATE
+#define CONFIGURE_TERMIOS_PRINTK_BAUDRATE 9600
+#endif
+
+/*
+ * fallback for device name to use
+ */
+#ifndef CONFIGURE_TERMIOS_PRINTK_DEVNAME
+#define CONFIGURE_TERMIOS_PRINTK_DEVNAME "/dev/console"
+#endif
+
+#ifdef CONFIGURE_USE_TERMIOS_PRINTK
+/*
+ * fill in termios_printk_conf structure
+ */
+termios_printk_conf_t termios_printk_conf = {
+ CONFIGURE_TERMIOS_PRINTK_BAUDRATE,
+
+#ifdef CONFIGURE_TERMIOS_PRINTK_CALLOUT
+ CONFIGURE_TERMIOS_PRINTK_CALLOUT,
+#else
+ NULL,
+#endif
+ CONFIGURE_TERMIOS_PRINTK_DEVNAME,
+};
+#endif
+
+int termios_printk_init(void) {
+#ifdef CONFIGURE_USE_TERMIOS_PRINTK
+ return termios_printk_open(termios_printk_conf.devname,
+ termios_printk_conf.baudrate);
+#else
+ return 0;
+#endif
+}
+
+#endif /* CONFIGURE_INIT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TERMIOS_PRINTK_CNF_H */
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);
+ }
+}
+
+
diff --git a/cpukit/libmisc/stackchk/README b/cpukit/libmisc/stackchk/README
new file mode 100644
index 0000000000..5421a77434
--- /dev/null
+++ b/cpukit/libmisc/stackchk/README
@@ -0,0 +1,53 @@
+#
+# $Id$
+#
+
+Introduction
+============
+
+This directory contains a stack bounds checker. It provides two
+primary features:
+
+ + check for stack overflow at each context switch
+ + provides an educated guess at each task's stack usage
+
+Enabling
+========
+
+Add the stack checker extension to the initial user extension set.
+If using confdefs.h to build your configuration table, this is
+as simple as adding -DSTACK_CHECK_ON to the gcc command line which
+compiles the file defining the configuration table. In the RTEMS
+test suites and samples, this is always init.c
+
+Background
+==========
+
+The stack overflow check at context switch works by looking for
+a 16 byte pattern at the logical end of the stack to be corrupted.
+The "guesser" assumes that the entire stack was prefilled with a known
+pattern and assumes that the pattern is still in place if the memory
+has not been used as a stack.
+
+Both of these can be fooled by pushing large holes onto the stack
+and not writing to them... or (much more unlikely) writing the
+magic patterns into memory.
+
+This code has not been extensively tested. It is provided as a tool
+for RTEMS users to catch the most common mistake in multitasking
+systems ... too little stack space. Suggestions and comments are appreciated.
+
+NOTES:
+
+1. Stack usage information is questionable on CPUs which push
+ large holes on stack.
+
+2. The stack checker has a tendency to generate a fault when
+ trying to print the helpful diagnostic message. If it comes
+ out, congratulations. If not, then the variable Stack_check_Blown_task
+ contains a pointer to the TCB of the offending task. This
+ is usually enough to go on.
+
+FUTURE:
+
+1. Determine how/if gcc will generate stack probe calls and support that.
diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c
new file mode 100644
index 0000000000..d2c0b1001b
--- /dev/null
+++ b/cpukit/libmisc/stackchk/check.c
@@ -0,0 +1,515 @@
+/*
+ * Stack Overflow Check User Extension Set
+ *
+ * NOTE: This extension set automatically determines at
+ * initialization time whether the stack for this
+ * CPU grows up or down and installs the correct
+ * extension routines for that direction.
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * 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 <rtems.h>
+#include <inttypes.h>
+
+/*
+ * The stack dump information may be printed by a "fatal" extension.
+ * Fatal extensions only get called via rtems_fatal_error_occurred()
+ * and not when rtems_shutdown_executive() is called.
+ * When that happens, this #define should be deleted and all the code
+ * it marks.
+ */
+#define DONT_USE_FATAL_EXTENSION
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <rtems/bspIo.h>
+#include <rtems/stackchk.h>
+#include "internal.h"
+
+/*
+ * Variable to indicate when the stack checker has been initialized.
+ */
+static int Stack_check_Initialized = 0;
+
+/*
+ * The "magic pattern" used to mark the end of the stack.
+ */
+Stack_check_Control Stack_check_Pattern;
+
+/*
+ * Helper function to report if the actual stack pointer is in range.
+ *
+ * NOTE: This uses a GCC specific method.
+ */
+static inline bool Stack_check_Frame_pointer_in_range(
+ Stack_Control *the_stack
+)
+{
+ #if defined(__GNUC__)
+ void *sp = __builtin_frame_address(0);
+
+ if ( sp < the_stack->area ) {
+ return false;
+ }
+ if ( sp > (the_stack->area + the_stack->size) ) {
+ return false;
+ }
+ #else
+ #error "How do I check stack bounds on a non-GNU compiler?"
+ #endif
+ return true;
+}
+
+/*
+ * Where the pattern goes in the stack area is dependent upon
+ * whether the stack grow to the high or low area of the memory.
+ */
+#if (CPU_STACK_GROWS_UP == TRUE)
+ #define Stack_check_Get_pattern( _the_stack ) \
+ ((char *)(_the_stack)->area + \
+ (_the_stack)->size - sizeof( Stack_check_Control ) )
+
+ #define Stack_check_Calculate_used( _low, _size, _high_water ) \
+ ((char *)(_high_water) - (char *)(_low))
+
+ #define Stack_check_usable_stack_start(_the_stack) \
+ ((_the_stack)->area)
+
+#else
+ /*
+ * We need this magic offset because during a task delete the task stack will
+ * be freed before we enter the task switch extension which checks the stack.
+ * The task stack free operation will write the next and previous pointers
+ * for the free list into this area.
+ */
+ #define Stack_check_Get_pattern( _the_stack ) \
+ ((char *)(_the_stack)->area + sizeof(Heap_Block) - HEAP_BLOCK_HEADER_SIZE)
+
+ #define Stack_check_Calculate_used( _low, _size, _high_water) \
+ ( ((char *)(_low) + (_size)) - (char *)(_high_water) )
+
+ #define Stack_check_usable_stack_start(_the_stack) \
+ ((char *)(_the_stack)->area + sizeof(Stack_check_Control))
+
+#endif
+
+/*
+ * Obtain a properly typed pointer to the area to check.
+ */
+#define Stack_check_Get_pattern_area( _the_stack ) \
+ (Stack_check_Control *) Stack_check_Get_pattern( _the_stack )
+
+/*
+ * The assumption is that if the pattern gets overwritten, the task
+ * is too close. This defines the usable stack memory.
+ */
+#define Stack_check_usable_stack_size(_the_stack) \
+ ((_the_stack)->size - sizeof(Stack_check_Control))
+
+#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
+ /*
+ * Did RTEMS allocate the interrupt stack? If so, put it in
+ * Stack_Control format.
+ */
+ Stack_Control Stack_check_Interrupt_stack;
+#endif
+
+/*
+ * Fill an entire stack area with BYTE_PATTERN. This will be used
+ * to check for amount of actual stack used.
+ */
+#define Stack_check_Dope_stack(_stack) \
+ memset((_stack)->area, BYTE_PATTERN, (_stack)->size)
+
+/*
+ * Stack_check_Initialize
+ */
+void Stack_check_Initialize( void )
+{
+ int i;
+ uint32_t *p;
+ static uint32_t pattern[ 4 ] = {
+ 0xFEEDF00D, 0x0BAD0D06, /* FEED FOOD to BAD DOG */
+ 0xDEADF00D, 0x600D0D06 /* DEAD FOOD but GOOD DOG */
+ };
+
+ if ( Stack_check_Initialized )
+ return;
+
+ /*
+ * Dope the pattern and fill areas
+ */
+ p = Stack_check_Pattern.pattern;
+ for ( i = 0; i < PATTERN_SIZE_WORDS; i++ ) {
+ p[i] = pattern[ i%4 ];
+ }
+
+ /*
+ * If appropriate, setup the interrupt stack for high water testing
+ * also.
+ */
+ #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
+ if (_CPU_Interrupt_stack_low && _CPU_Interrupt_stack_high) {
+ Stack_check_Interrupt_stack.area = _CPU_Interrupt_stack_low;
+ Stack_check_Interrupt_stack.size = (char *) _CPU_Interrupt_stack_high -
+ (char *) _CPU_Interrupt_stack_low;
+ Stack_check_Dope_stack(&Stack_check_Interrupt_stack);
+ }
+ #endif
+
+ Stack_check_Initialized = 1;
+}
+
+/*
+ * rtems_stack_checker_create_extension
+ */
+bool rtems_stack_checker_create_extension(
+ Thread_Control *running __attribute__((unused)),
+ Thread_Control *the_thread
+)
+{
+ Stack_check_Initialize();
+
+ if (the_thread)
+ Stack_check_Dope_stack(&the_thread->Start.Initial_stack);
+
+ return true;
+}
+
+/*
+ * rtems_stack_checker_Begin_extension
+ */
+void rtems_stack_checker_begin_extension(
+ Thread_Control *the_thread
+)
+{
+ Stack_check_Control *the_pattern;
+
+ if ( the_thread->Object.id == 0 ) /* skip system tasks */
+ return;
+
+ the_pattern = Stack_check_Get_pattern_area(&the_thread->Start.Initial_stack);
+
+ *the_pattern = Stack_check_Pattern;
+}
+
+/*
+ * Stack_check_report_blown_task
+ *
+ * Report a blown stack. Needs to be a separate routine
+ * so that interrupt handlers can use this too.
+ *
+ * NOTE: The system is in a questionable state... we may not get
+ * the following message out.
+ */
+void Stack_check_report_blown_task(
+ Thread_Control *running,
+ bool pattern_ok
+) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
+
+void Stack_check_report_blown_task(Thread_Control *running, bool pattern_ok)
+{
+ Stack_Control *stack = &running->Start.Initial_stack;
+ void *pattern_area = Stack_check_Get_pattern(stack);
+ char name[32];
+
+ printk("BLOWN STACK!!!\n");
+ printk("task control block: 0x%08" PRIxPTR "\n", running);
+ printk("task ID: 0x%08lx\n", (unsigned long) running->Object.id);
+ printk(
+ "task name: 0x%08" PRIx32 "\n",
+ running->Object.name.name_u32
+ );
+ printk(
+ "task name string: %s\n",
+ rtems_object_get_name(running->Object.id, sizeof(name), name)
+ );
+ printk(
+ "task stack area (%lu Bytes): 0x%08" PRIxPTR " .. 0x%08" PRIxPTR "\n",
+ (unsigned long) stack->size,
+ stack->area,
+ ((char *) stack->area + stack->size)
+ );
+ if (!pattern_ok) {
+ printk(
+ "damaged pattern area (%lu Bytes): 0x%08" PRIxPTR " .. 0x%08" PRIxPTR "\n",
+ (unsigned long) PATTERN_SIZE_BYTES,
+ pattern_area,
+ (pattern_area + PATTERN_SIZE_BYTES)
+ );
+ }
+
+ #if defined(RTEMS_MULTIPROCESSING)
+ if (rtems_configuration_get_user_multiprocessing_table()) {
+ printk(
+ "node: 0x%08" PRIxPTR "\n",
+ rtems_configuration_get_user_multiprocessing_table()->node
+ );
+ }
+ #endif
+
+ rtems_fatal_error_occurred(0x81);
+}
+
+/*
+ * rtems_stack_checker_switch_extension
+ */
+void rtems_stack_checker_switch_extension(
+ Thread_Control *running __attribute__((unused)),
+ Thread_Control *heir __attribute__((unused))
+)
+{
+ Stack_Control *the_stack = &running->Start.Initial_stack;
+ void *pattern;
+ bool sp_ok;
+ bool pattern_ok = true;
+
+ pattern = Stack_check_Get_pattern_area(the_stack);
+
+ /*
+ * Check for an out of bounds stack pointer or an overwrite
+ */
+ sp_ok = Stack_check_Frame_pointer_in_range( the_stack );
+
+ pattern_ok = (!memcmp( pattern,
+ (void *) Stack_check_Pattern.pattern, PATTERN_SIZE_BYTES));
+
+ if ( !sp_ok || !pattern_ok ) {
+ Stack_check_report_blown_task( running, pattern_ok );
+ }
+}
+
+/*
+ * Check if blown
+ */
+bool rtems_stack_checker_is_blown( void )
+{
+ Stack_Control *the_stack = &_Thread_Executing->Start.Initial_stack;
+ bool sp_ok;
+ bool pattern_ok = true;
+
+ /*
+ * Check for an out of bounds stack pointer
+ */
+
+ sp_ok = Stack_check_Frame_pointer_in_range( the_stack );
+
+ /*
+ * The stack checker must be initialized before the pattern is there
+ * to check.
+ */
+ if ( Stack_check_Initialized ) {
+ pattern_ok = (!memcmp(
+ Stack_check_Get_pattern(the_stack),
+ (void *) Stack_check_Pattern.pattern,
+ PATTERN_SIZE_BYTES
+ ));
+ }
+
+
+ /*
+ * Let's report as much as we can.
+ */
+ if ( !sp_ok || !pattern_ok ) {
+ Stack_check_report_blown_task( _Thread_Executing, pattern_ok );
+ /* DOES NOT RETURN */
+ }
+
+ /*
+ * The Stack Pointer and the Pattern Area are OK so return false.
+ */
+ return false;
+}
+
+/*
+ * Stack_check_find_high_water_mark
+ */
+static inline void *Stack_check_find_high_water_mark(
+ const void *s,
+ size_t n
+)
+{
+ const uint32_t *base, *ebase;
+ uint32_t length;
+
+ base = s;
+ length = n/4;
+
+ #if ( CPU_STACK_GROWS_UP == TRUE )
+ /*
+ * start at higher memory and find first word that does not
+ * match pattern
+ */
+
+ base += length - 1;
+ for (ebase = s; base > ebase; base--)
+ if (*base != U32_PATTERN)
+ return (void *) base;
+ #else
+ /*
+ * start at lower memory and find first word that does not
+ * match pattern
+ */
+
+ base += PATTERN_SIZE_WORDS;
+ for (ebase = base + length; base < ebase; base++)
+ if (*base != U32_PATTERN)
+ return (void *) base;
+ #endif
+
+ return (void *)0;
+}
+
+/*
+ * Stack_check_Dump_threads_usage
+ *
+ * Try to print out how much stack was actually used by the task.
+ */
+static void *print_context;
+static rtems_printk_plugin_t print_handler;
+
+void Stack_check_Dump_threads_usage(
+ Thread_Control *the_thread
+)
+{
+ uint32_t size, used;
+ void *low;
+ void *high_water_mark;
+ void *current;
+ Stack_Control *stack;
+ char name[5];
+
+ /*
+ * The pointer passed in for the_thread is guaranteed to be non-NULL from
+ * rtems_iterate_over_all_threads() so no need to check it here.
+ */
+
+ /*
+ * Obtain interrupt stack information
+ */
+ #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
+ if (the_thread == (Thread_Control *) -1) {
+ if (!Stack_check_Interrupt_stack.area)
+ return;
+ stack = &Stack_check_Interrupt_stack;
+ the_thread = 0;
+ current = 0;
+ } else
+ #endif
+ {
+ stack = &the_thread->Start.Initial_stack;
+ current = (void *)_CPU_Context_Get_SP( &the_thread->Registers );
+ }
+
+ low = Stack_check_usable_stack_start(stack);
+ size = Stack_check_usable_stack_size(stack);
+
+ high_water_mark = Stack_check_find_high_water_mark(low, size);
+
+ if ( high_water_mark )
+ used = Stack_check_Calculate_used( low, size, high_water_mark );
+ else
+ used = 0;
+
+
+ #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
+ if ( the_thread )
+ #endif
+ {
+ (*print_handler)(
+ print_context,
+ "0x%08" PRIx32 " %4s",
+ the_thread->Object.id,
+ rtems_object_get_name( the_thread->Object.id, sizeof(name), name )
+ );
+ }
+ #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
+ else {
+ (*print_handler)( print_context, "0x%08" PRIx32 " INTR", ~0 );
+ }
+ #endif
+
+ (*print_handler)(
+ print_context,
+ " %010p - %010p %010p %8" PRId32 " ",
+ stack->area,
+ stack->area + stack->size - 1,
+ current,
+ size
+ );
+
+ if (Stack_check_Initialized == 0) {
+ (*print_handler)( print_context, "Unavailable\n" );
+ } else {
+ (*print_handler)( print_context, "%8" PRId32 "\n", used );
+ }
+
+
+}
+
+/*
+ * rtems_stack_checker_fatal_extension
+ */
+#ifndef DONT_USE_FATAL_EXTENSION
+ void rtems_stack_checker_fatal_extension(
+ Internal_errors_Source source,
+ bool is_internal,
+ uint32_t status
+ )
+ {
+ if (status == 0)
+ rtems_stack_checker_report_usage();
+ }
+#endif
+
+/*PAGE
+ *
+ * rtems_stack_checker_report_usage
+ */
+
+void rtems_stack_checker_report_usage_with_plugin(
+ void *context,
+ rtems_printk_plugin_t print
+)
+{
+ if ( !print )
+ return;
+
+ print_context = context;
+ print_handler = print;
+
+ (*print)( context, "Stack usage by thread\n");
+ (*print)( context,
+" ID NAME LOW HIGH CURRENT AVAILABLE USED\n"
+ );
+
+ /* iterate over all threads and dump the usage */
+ rtems_iterate_over_all_threads( Stack_check_Dump_threads_usage );
+
+ #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
+ /* dump interrupt stack info if any */
+ Stack_check_Dump_threads_usage((Thread_Control *) -1);
+ #endif
+
+ print_context = NULL;
+ print_handler = NULL;
+}
+
+void rtems_stack_checker_report_usage( void )
+{
+ rtems_stack_checker_report_usage_with_plugin( NULL, printk_plugin );
+}
diff --git a/cpukit/libmisc/stackchk/internal.h b/cpukit/libmisc/stackchk/internal.h
new file mode 100644
index 0000000000..a16a61e30e
--- /dev/null
+++ b/cpukit/libmisc/stackchk/internal.h
@@ -0,0 +1,95 @@
+/* internal.h
+ *
+ * This include file contains internal information
+ * for the RTEMS stack checker.
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * 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 __INTERNAL_STACK_CHECK_h
+#define __INTERNAL_STACK_CHECK_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure is used to fill in and compare the "end of stack"
+ * marker pattern.
+ * pattern area must be a multiple of 4 words.
+ */
+
+#ifdef CPU_STACK_CHECK_SIZE
+#define PATTERN_SIZE_WORDS (((CPU_STACK_CHECK_SIZE / 4) + 3) & ~0x3)
+#else
+#define PATTERN_SIZE_WORDS (4)
+#endif
+
+#define PATTERN_SIZE_BYTES (PATTERN_SIZE_WORDS * sizeof(uint32_t))
+
+typedef struct {
+ uint32_t pattern[ PATTERN_SIZE_WORDS ];
+} Stack_check_Control;
+
+/*
+ * The pattern used to fill the entire stack.
+ */
+
+#define BYTE_PATTERN 0xA5
+#define U32_PATTERN 0xA5A5A5A5
+
+/*
+ * rtems_stack_checker_create_extension
+ */
+
+bool rtems_stack_checker_create_extension(
+ Thread_Control *running,
+ Thread_Control *the_thread
+);
+
+/*
+ * rtems_stack_checker_begin_extension
+ */
+
+void rtems_stack_checker_begin_extension(
+ Thread_Control *the_thread
+);
+
+/*
+ * rtems_stack_checker_switch_extension
+ */
+
+void rtems_stack_checker_switch_extension(
+ Thread_Control *running,
+ Thread_Control *heir
+);
+
+/*
+ * rtems_stack_checker_fatal_extension
+ */
+
+void rtems_stack_checker_fatal_extension(
+ Internal_errors_Source source,
+ bool is_internal,
+ uint32_t status
+);
+
+/*
+ * rtems_stack_checker_report_usage
+ */
+
+void rtems_stack_checker_report_usage( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/stackchk/stackchk.h b/cpukit/libmisc/stackchk/stackchk.h
new file mode 100644
index 0000000000..02bbac3a45
--- /dev/null
+++ b/cpukit/libmisc/stackchk/stackchk.h
@@ -0,0 +1,135 @@
+/** @file rtems/stackchk.h
+ *
+ * This include file contains information necessary to utilize
+ * and install the stack checker mechanism.
+ */
+
+/*
+ * 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_STACKCHK_H
+#define _RTEMS_STACKCHK_H
+
+#include <stdbool.h> /* bool */
+
+#include <rtems/score/percpu.h> /* Thread_Control */
+#include <rtems/bspIo.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Has Current Task Blown Its Stack
+ *
+ * This method is used to determine if the current stack pointer
+ * of the currently executing task is within bounds.
+ *
+ * @return This method returns true if the currently executing task
+ * has blown its stack.
+ *
+ */
+bool rtems_stack_checker_is_blown( void );
+
+/** @brief Print Stack Usage Report
+ *
+ * This method prints a stack usage report for the curently executing
+ * task.
+ *
+ * @note It uses printk to print the report.
+ */
+void rtems_stack_checker_report_usage( void );
+
+/** @brief Print Stack Usage Report
+ *
+ * This method prints a stack usage report for the curently executing
+ * task.
+ *
+ * @param[in] context is the context to pass to the print handler
+ * @param[in] print is the print handler
+ *
+ * @note It uses the caller's routine to print the report.
+ */
+void rtems_stack_checker_report_usage_with_plugin(
+ void *context,
+ rtems_printk_plugin_t print
+);
+
+/*************************************************************
+ *************************************************************
+ ** Prototyped only so the user extension can be installed **
+ *************************************************************
+ *************************************************************/
+
+/** @brief Stack Checker Task Create Extension
+ *
+ * This method is the task create extension for the stack checker.
+ *
+ * @param[in] running points to the currently executing task
+ * @param[in] the_thread points to the newly created task
+ *
+ * @note If this this the first task created, the stack checker
+ * will automatically intialize itself.
+ */
+bool rtems_stack_checker_create_extension(
+ Thread_Control *running,
+ Thread_Control *the_thread
+);
+
+/** @brief Stack Checker Task Begin Extension
+ *
+ * This method is the task begin extension for the stack checker.
+ *
+ * @param[in] the_thread points to task starting to execute
+ *
+ * @note This is called from the internal method _Thread_Handler.
+ */
+void rtems_stack_checker_begin_extension(
+ Thread_Control *the_thread
+);
+
+/** @brief Stack Checker Task Context Switch Extension
+ *
+ * This method is the task context switch extension for the stack checker.
+ *
+ * @param[in] running points to the currently executing task which
+ * is being context switched out
+ * @param[in] running points to the heir task which we are switching to
+ *
+ * @note This is called from the internal method _Thread_Dispatch.
+ */
+void rtems_stack_checker_switch_extension(
+ Thread_Control *running,
+ Thread_Control *heir
+);
+
+/** @brief Stack Checker Extension Set Definition
+ *
+ * This macro defines the user extension handler set for the stack
+ * checker. This macro is normally only used by confdefs.h.
+ */
+#define RTEMS_STACK_CHECKER_EXTENSION \
+{ \
+ rtems_stack_checker_create_extension, /* rtems_task_create */ \
+ 0, /* rtems_task_start */ \
+ 0, /* rtems_task_restart */ \
+ 0, /* rtems_task_delete */ \
+ rtems_stack_checker_switch_extension, /* task_switch */ \
+ rtems_stack_checker_begin_extension, /* task_begin */ \
+ 0, /* task_exitted */ \
+ 0 /* rtems_stack_checker_fatal_extension */, /* fatal */ \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/stringto/stringto.h b/cpukit/libmisc/stringto/stringto.h
new file mode 100644
index 0000000000..dfb1617bc9
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringto.h
@@ -0,0 +1,246 @@
+/*
+ * COPYRIGHT (c) 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$
+ */
+
+#ifndef _RTEMS_STRINGTO_H
+#define _RTEMS_STRINGTO_H
+
+#include <rtems.h>
+
+/**
+ * @brief Convert String to Pointer (with validation)
+ *
+ * This method converts a string to a pointer (void *) with
+ * basic numeric validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_pointer(
+ const char *s,
+ void **n,
+ char **endptr
+);
+
+/**
+ * @brief Convert String to Unsigned Character (with validation)
+ *
+ * This method converts a string to an unsigned character with
+ * range validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ * @param[in] base is the expected base of the number
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_unsigned_char(
+ const char *s,
+ unsigned char *n,
+ char **endptr,
+ int base
+);
+
+/**
+ * @brief Convert String to Int (with validation)
+ *
+ * This method converts a string to an int with range validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ * @param[in] base is the expected base of the number
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_int(
+ const char *s,
+ int *n,
+ char **endptr,
+ int base
+);
+
+/**
+ * @brief Convert String to Unsigned Int (with validation)
+ *
+ * This method converts a string to an unsigned int with range validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ * @param[in] base is the expected base of the number
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_unsigned_int(
+ const char *s,
+ unsigned int *n,
+ char **endptr,
+ int base
+);
+
+/**
+ * @brief Convert String to Long (with validation)
+ *
+ * This method converts a string to a long with
+ * range validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ * @param[in] base is the expected base of the number
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_long(
+ const char *s,
+ long *n,
+ char **endptr,
+ int base
+);
+
+/**
+ * @brief Convert String to Unsigned Long (with validation)
+ *
+ * This method converts a string to an unsigned long with
+ * range validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ * @param[in] base is the expected base of the number
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_unsigned_long(
+ const char *s,
+ unsigned long *n,
+ char **endptr,
+ int base
+);
+
+/**
+ * @brief Convert String to Long Long (with validation)
+ *
+ * This method converts a string to a long long with
+ * range validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ * @param[in] base is the expected base of the number
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_long_long(
+ const char *s,
+ long long *n,
+ char **endptr,
+ int base
+);
+
+/**
+ * @brief Convert String to Unsigned Long Long (with validation)
+ *
+ * This method converts a string to an unsigned character with
+ * range validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ * @param[in] base is the expected base of the number
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_unsigned_long_long(
+ const char *s,
+ unsigned long long *n,
+ char **endptr,
+ int base
+);
+
+/**
+ * @brief Convert String to Float (with validation)
+ *
+ * This method converts a string to a float with range validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_float(
+ const char *s,
+ float *n,
+ char **endptr
+);
+
+/**
+ * @brief Convert String to Double (with validation)
+ *
+ * This method converts a string to a double with range validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_double(
+ const char *s,
+ double *n,
+ char **endptr
+);
+
+/**
+ * @brief Convert String to long double (with validation)
+ *
+ * This method converts a string to a long double with range validation.
+ *
+ * @param[in] s is the string to convert
+ * @param[in] n points to the variable to place the converted output in
+ * @param[in] endptr is used to keep track of the position in the string
+ *
+ * @return This method returns RTEMS_SUCCESSFUL on successful conversion
+ * and *n is filled in. Otherwise, the status indicates the
+ * source of the error.
+ */
+rtems_status_code rtems_string_to_long_double(
+ const char *s,
+ long double *n,
+ char **endptr
+);
+
+#endif
diff --git a/cpukit/libmisc/stringto/stringtodouble.c b/cpukit/libmisc/stringto/stringtodouble.c
new file mode 100644
index 0000000000..ec50a1332b
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtodouble.c
@@ -0,0 +1,58 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <rtems/stringto.h>
+
+/*
+ * Instantiate an error checking wrapper for strtod (double)
+ */
+
+rtems_status_code rtems_string_to_double (
+ const char *s,
+ double *n,
+ char **endptr
+)
+{
+ double result;
+ char *end;
+
+ if ( !n )
+ return RTEMS_INVALID_ADDRESS;
+
+ errno = 0;
+ *n = 0;
+
+ result = strtod( s, &end );
+
+ if ( endptr )
+ *endptr = end;
+
+ if ( end == s )
+ return RTEMS_NOT_DEFINED;
+
+ if ( ( errno == ERANGE ) &&
+ (( result == 0 ) || ( result == HUGE_VAL ) || ( result == -HUGE_VAL )))
+ return RTEMS_INVALID_NUMBER;
+
+ *n = result;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/stringto/stringtofloat.c b/cpukit/libmisc/stringto/stringtofloat.c
new file mode 100644
index 0000000000..05ebe33566
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtofloat.c
@@ -0,0 +1,58 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <rtems/stringto.h>
+
+/*
+ * Instantiate an error checking wrapper for strtof (float)
+ */
+
+rtems_status_code rtems_string_to_float (
+ const char *s,
+ float *n,
+ char **endptr
+)
+{
+ float result;
+ char *end;
+
+ if ( !n )
+ return RTEMS_INVALID_ADDRESS;
+
+ errno = 0;
+ *n = 0;
+
+ result = strtof( s, &end );
+
+ if ( endptr )
+ *endptr = end;
+
+ if ( end == s )
+ return RTEMS_NOT_DEFINED;
+
+ if ( ( errno == ERANGE ) &&
+ (( result == 0 ) || ( result == HUGE_VALF ) || ( result == -HUGE_VALF )))
+ return RTEMS_INVALID_NUMBER;
+
+ *n = result;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/stringto/stringtoint.c b/cpukit/libmisc/stringto/stringtoint.c
new file mode 100644
index 0000000000..8e3663b496
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtoint.c
@@ -0,0 +1,73 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <rtems/stringto.h>
+
+/*
+ * Instantiate an error checking wrapper for strtol (int)
+ */
+
+rtems_status_code rtems_string_to_int (
+ const char *s,
+ int *n,
+ char **endptr,
+ int base
+)
+{
+ long result;
+ char *end;
+
+ if ( !n )
+ return RTEMS_INVALID_ADDRESS;
+
+ errno = 0;
+ *n = 0;
+
+ result = strtol( s, &end, base );
+
+ if ( endptr )
+ *endptr = end;
+
+ if ( end == s )
+ return RTEMS_NOT_DEFINED;
+
+ if ( ( errno == ERANGE ) &&
+ (( result == 0 ) || ( result == LONG_MAX ) || ( result == LONG_MIN )))
+ return RTEMS_INVALID_NUMBER;
+
+#if (INT_MAX < LONG_MAX)
+ if ( result > INT_MAX ) {
+ errno = ERANGE;
+ return RTEMS_INVALID_NUMBER;
+ }
+#endif
+
+#if (INT_MIN < LONG_MIN)
+ if ( result < INT_MIN ) {
+ errno = ERANGE;
+ return RTEMS_INVALID_NUMBER;
+ }
+#endif
+
+ *n = result;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/stringto/stringtolong.c b/cpukit/libmisc/stringto/stringtolong.c
new file mode 100644
index 0000000000..e77b8822b8
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtolong.c
@@ -0,0 +1,59 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <rtems/stringto.h>
+
+/*
+ * Instantiate an error checking wrapper for strtol (long)
+ */
+
+rtems_status_code rtems_string_to_long (
+ const char *s,
+ long *n,
+ char **endptr,
+ int base
+)
+{
+ long result;
+ char *end;
+
+ if ( !n )
+ return RTEMS_INVALID_ADDRESS;
+
+ errno = 0;
+ *n = 0;
+
+ result = strtol( s, &end, base );
+
+ if ( endptr )
+ *endptr = end;
+
+ if ( end == s )
+ return RTEMS_NOT_DEFINED;
+
+ if ( ( errno == ERANGE ) &&
+ (( result == 0 ) || ( result == LONG_MAX ) || ( result == LONG_MIN )))
+ return RTEMS_INVALID_NUMBER;
+
+ *n = result;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/stringto/stringtolongdouble.c b/cpukit/libmisc/stringto/stringtolongdouble.c
new file mode 100644
index 0000000000..776f5e183b
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtolongdouble.c
@@ -0,0 +1,58 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <rtems/stringto.h>
+
+/*
+ * Instantiate an error checking wrapper for strtod (double)
+ */
+
+rtems_status_code rtems_string_to_long_double (
+ const char *s,
+ long double *n,
+ char **endptr
+)
+{
+ long double result;
+ char *end;
+
+ if ( !n )
+ return RTEMS_INVALID_ADDRESS;
+
+ errno = 0;
+ *n = 0;
+
+ result = strtold( s, &end );
+
+ if ( endptr )
+ *endptr = end;
+
+ if ( end == s )
+ return RTEMS_NOT_DEFINED;
+
+ if ( ( errno == ERANGE ) &&
+ (( result == 0 ) || ( result == HUGE_VALL ) || ( result == -HUGE_VALL )))
+ return RTEMS_INVALID_NUMBER;
+
+ *n = result;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/stringto/stringtolonglong.c b/cpukit/libmisc/stringto/stringtolonglong.c
new file mode 100644
index 0000000000..d291262477
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtolonglong.c
@@ -0,0 +1,68 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <rtems/stringto.h>
+
+/* c99 has LLONG_MAX instead of LONG_LONG_MAX */
+#ifndef LONG_LONG_MAX
+#define LONG_LONG_MAX LLONG_MAX
+#endif
+/* c99 has LLONG_MIN instead of LONG_LONG_MIN */
+#ifndef LONG_LONG_MIN
+#define LONG_LONG_MIN LLONG_MIN
+#endif
+
+/*
+ * Instantiate an error checking wrapper for strtoll (long long)
+ */
+
+rtems_status_code rtems_string_to_long_long (
+ const char *s,
+ long long *n,
+ char **endptr,
+ int base
+)
+{
+ long long result;
+ char *end;
+
+ if ( !n )
+ return RTEMS_INVALID_ADDRESS;
+
+ errno = 0;
+ *n = 0;
+
+ result = strtoll( s, &end, base );
+
+ if ( endptr )
+ *endptr = end;
+
+ if ( end == s )
+ return RTEMS_NOT_DEFINED;
+
+ if ( ( errno == ERANGE ) &&
+ (( result == 0 ) || ( result == LONG_LONG_MAX ) || ( result == LONG_LONG_MIN )))
+ return RTEMS_INVALID_NUMBER;
+
+ *n = result;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/stringto/stringtopointer.c b/cpukit/libmisc/stringto/stringtopointer.c
new file mode 100644
index 0000000000..3a99baa3b5
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtopointer.c
@@ -0,0 +1,47 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include <rtems/stringto.h>
+
+/*
+ * Instantiate an error checking wrapper for strtoul/strtoull (void *)
+ */
+
+#if (UINTPTR_MAX == ULONG_MAX)
+#define STRTOFUNC(a,b,c) rtems_string_to_unsigned_long(a, (unsigned long*) b, c, 0)
+#elif (UINTPTR_MAX == ULONG_LONG_MAX)
+#define STRTOFUNC(a,b,c) rtems_string_to_unsigned_long_long(a, (unsigned long long*) b, c, 0)
+#elif (UINTPTR_MAX == UINT_MAX)
+#define STRTOFUNC(a,b,c) rtems_string_to_unsigned_int(a, (unsigned int*) b, c, 0)
+#else
+/* Fallback to unsigned long */
+#define STRTOFUNC(a,b,c) rtems_string_to_unsigned_long(a, (unsigned long*) b, c, 0)
+#endif
+
+rtems_status_code rtems_string_to_pointer (
+ const char *s,
+ void **n,
+ char **endptr
+)
+{
+ return STRTOFUNC( s, n, endptr );
+}
diff --git a/cpukit/libmisc/stringto/stringtounsignedchar.c b/cpukit/libmisc/stringto/stringtounsignedchar.c
new file mode 100644
index 0000000000..5223b03fb7
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtounsignedchar.c
@@ -0,0 +1,66 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <rtems/stringto.h>
+
+/*
+ * Instantiate an error checking wrapper for strtoul (unsigned char)
+ */
+
+rtems_status_code rtems_string_to_unsigned_char (
+ const char *s,
+ unsigned char *n,
+ char **endptr,
+ int base
+)
+{
+ unsigned long result;
+ char *end;
+
+ if ( !n )
+ return RTEMS_INVALID_ADDRESS;
+
+ errno = 0;
+ *n = 0;
+
+ result = strtoul( s, &end, base );
+
+ if ( endptr )
+ *endptr = end;
+
+ if ( end == s )
+ return RTEMS_NOT_DEFINED;
+
+ if ( ( errno == ERANGE ) &&
+ (( result == 0 ) || ( result == ULONG_MAX )))
+ return RTEMS_INVALID_NUMBER;
+
+#if (UCHAR_MAX < ULONG_MAX)
+ if ( result > UCHAR_MAX ) {
+ errno = ERANGE;
+ return RTEMS_INVALID_NUMBER;
+ }
+#endif
+
+ *n = result;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/stringto/stringtounsignedint.c b/cpukit/libmisc/stringto/stringtounsignedint.c
new file mode 100644
index 0000000000..9821beff87
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtounsignedint.c
@@ -0,0 +1,66 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <rtems/stringto.h>
+
+/*
+ * Instantiate an error checking wrapper for strtoul (unsigned int)
+ */
+
+rtems_status_code rtems_string_to_unsigned_int (
+ const char *s,
+ unsigned int *n,
+ char **endptr,
+ int base
+)
+{
+ unsigned long result;
+ char *end;
+
+ if ( !n )
+ return RTEMS_INVALID_ADDRESS;
+
+ errno = 0;
+ *n = 0;
+
+ result = strtoul( s, &end, base );
+
+ if ( endptr )
+ *endptr = end;
+
+ if ( end == s )
+ return RTEMS_NOT_DEFINED;
+
+ if ( ( errno == ERANGE ) &&
+ (( result == 0 ) || ( result == ULONG_MAX )))
+ return RTEMS_INVALID_NUMBER;
+
+#if (UINT_MAX < ULONG_MAX)
+ if ( result > UINT_MAX ) {
+ errno = ERANGE;
+ return RTEMS_INVALID_NUMBER;
+ }
+#endif
+
+ *n = result;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/stringto/stringtounsignedlong.c b/cpukit/libmisc/stringto/stringtounsignedlong.c
new file mode 100644
index 0000000000..11c374c486
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtounsignedlong.c
@@ -0,0 +1,59 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <rtems/stringto.h>
+
+/*
+ * Instantiate an error checking wrapper for strtoul (unsigned long)
+ */
+
+rtems_status_code rtems_string_to_unsigned_long (
+ const char *s,
+ unsigned long *n,
+ char **endptr,
+ int base
+)
+{
+ unsigned long result;
+ char *end;
+
+ if ( !n )
+ return RTEMS_INVALID_ADDRESS;
+
+ errno = 0;
+ *n = 0;
+
+ result = strtoul( s, &end, base );
+
+ if ( endptr )
+ *endptr = end;
+
+ if ( end == s )
+ return RTEMS_NOT_DEFINED;
+
+ if ( ( errno == ERANGE ) &&
+ (( result == 0 ) || ( result == ULONG_MAX )))
+ return RTEMS_INVALID_NUMBER;
+
+ *n = result;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/stringto/stringtounsignedlonglong.c b/cpukit/libmisc/stringto/stringtounsignedlonglong.c
new file mode 100644
index 0000000000..61c6e2e063
--- /dev/null
+++ b/cpukit/libmisc/stringto/stringtounsignedlonglong.c
@@ -0,0 +1,64 @@
+/*
+ * COPYRIGHT (c) 2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011 Ralf Corsépius, Ulm, Germany.
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <rtems/stringto.h>
+
+/* c99 has ULLONG_MAX instead of ULONG_LONG_MAX */
+#ifndef ULONG_LONG_MAX
+#define ULONG_LONG_MAX ULLONG_MAX
+#endif
+
+/*
+ * Instantiate an error checking wrapper for strtoull (unsigned long long)
+ */
+
+rtems_status_code rtems_string_to_unsigned_long_long (
+ const char *s,
+ unsigned long long *n,
+ char **endptr,
+ int base
+)
+{
+ unsigned long long result;
+ char *end;
+
+ if ( !n )
+ return RTEMS_INVALID_ADDRESS;
+
+ errno = 0;
+ *n = 0;
+
+ result = strtoull( s, &end, base );
+
+ if ( endptr )
+ *endptr = end;
+
+ if ( end == s )
+ return RTEMS_NOT_DEFINED;
+
+ if ( ( errno == ERANGE ) &&
+ (( result == 0 ) || ( result == ULONG_LONG_MAX )))
+ return RTEMS_INVALID_NUMBER;
+
+ *n = result;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/untar/README b/cpukit/libmisc/untar/README
new file mode 100644
index 0000000000..24c9e7fa62
--- /dev/null
+++ b/cpukit/libmisc/untar/README
@@ -0,0 +1,26 @@
+#
+#
+# untar information
+#
+# Author: Jake Janovetz 7.6.1999
+#
+# $Id$
+#
+
+untar.c contains two procedures for extracting files from a UNIX
+tar file:
+
+ int Untar_FromMemory(unsigned char *tar_buf, unsigned long size);
+ int Untar_FromFile(char *tar_name);
+
+Untar_FromMemory(...) takes its input from a chunk of allocated memory.
+This is particularly useful when the tar is stored in Flash memory or
+comes from the FTP daemon by way of a hook.
+
+Untar_FromFile(...) is identical except the source is from an existing
+file. The fully qualified filename is passed through char *tar_name.
+
+
+
+BUGS: Please email janovetz@uiuc.edu
+-----
diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
new file mode 100644
index 0000000000..2c5c8e9cf3
--- /dev/null
+++ b/cpukit/libmisc/untar/untar.c
@@ -0,0 +1,384 @@
+/* FIXME:
+ * 1. Symbolic links are not created.
+ * 2. Untar_FromMemory uses FILE *fp.
+ * 3. How to determine end of archive?
+ *
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * 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 <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <rtems/untar.h>
+#include <rtems/bspIo.h>
+
+
+/**************************************************************************
+ * TAR file format:
+ *
+ * Offset Length Contents
+ * 0 100 bytes File name ('\0' terminated, 99 maxmum length)
+ * 100 8 bytes File mode (in octal ascii)
+ * 108 8 bytes User ID (in octal ascii)
+ * 116 8 bytes Group ID (in octal ascii)
+ * 124 12 bytes File size (s) (in octal ascii)
+ * 136 12 bytes Modify time (in octal ascii)
+ * 148 8 bytes Header checksum (in octal ascii)
+ * 156 1 bytes Link flag
+ * 157 100 bytes Linkname ('\0' terminated, 99 maxmum length)
+ * 257 8 bytes Magic PAX ("ustar\0" + 2 bytes padding)
+ * 257 8 bytes Magic GNU tar ("ustar \0")
+ * 265 32 bytes User name ('\0' terminated, 31 maxmum length)
+ * 297 32 bytes Group name ('\0' terminated, 31 maxmum length)
+ * 329 8 bytes Major device ID (in octal ascii)
+ * 337 8 bytes Minor device ID (in octal ascii)
+ * 345 155 bytes Prefix
+ * 512 (s+p)bytes File contents (s+p) := (((s) + 511) & ~511),
+ * round up to 512 bytes
+ *
+ * Checksum:
+ * int i, sum;
+ * char* header = tar_header_pointer;
+ * sum = 0;
+ * for(i = 0; i < 512; i++)
+ * sum += 0xFF & header[i];
+ *************************************************************************/
+
+#define MAX_NAME_FIELD_SIZE 99
+
+#define MIN(a,b) ((a)>(b)?(b):(a))
+
+
+/**************************************************************************
+ * This converts octal ASCII number representations into an
+ * unsigned long. Only support 32-bit numbers for now.
+ *************************************************************************/
+unsigned long
+_rtems_octal2ulong(
+ const char *octascii,
+ size_t len
+)
+{
+ size_t i;
+ unsigned long num;
+
+ num = 0;
+ for (i=0; i < len; i++)
+ {
+ if ((octascii[i] < '0') || (octascii[i] > '9'))
+ {
+ continue;
+ }
+ num = num * 8 + ((unsigned long)(octascii[i] - '0'));
+ }
+ return(num);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromMemory *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a block of memory. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * void * tar_buf - Pointer to TAR buffer. *
+ * size_t size - Length of TAR buffer. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************/
+int
+Untar_FromMemory(
+ void *tar_buf,
+ size_t size
+)
+{
+ FILE *fp;
+ const char *tar_ptr = (const char *)tar_buf;
+ const char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long ptr;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long file_size;
+ unsigned char linkflag;
+
+
+ ptr = 0;
+ while (1)
+ {
+ if (ptr + 512 > size)
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ /* Read the header */
+ bufr = &tar_ptr[ptr];
+ ptr += 512;
+ if (strncmp(&bufr[257], "ustar", 5))
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ file_size = _rtems_octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * Compute the TAR checksum and check with the value in
+ * the archive. The checksum is computed over the entire
+ * header, but the checksum field is substituted with blanks.
+ ******************************************************************/
+ hdr_chksum = _rtems_octal2ulong(&bufr[148], 8);
+ sum = _rtems_tar_header_checksum(bufr);
+
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == SYMTYPE)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ symlink(linkname, fname);
+ }
+ else if (linkflag == REGTYPE)
+ {
+ nblocks = (((file_size) + 511) & ~511) / 512;
+ if ((fp = fopen(fname, "w")) == NULL)
+ {
+ printk("Untar: failed to create file %s\n", fname);
+ ptr += 512 * nblocks;
+ }
+ else
+ {
+ unsigned long sizeToGo = file_size;
+ size_t len;
+
+ /***************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the file_size rounded to the nearest 512-byte boundary.
+ **************************************************************/
+ for (i=0; i<nblocks; i++)
+ {
+ len = ((sizeToGo < 512L)?(sizeToGo):(512L));
+ n = fwrite(&tar_ptr[ptr], 1, len, fp);
+ if (n != len)
+ {
+ printk("untar: Error during write\n");
+ break;
+ }
+ ptr += 512;
+ sizeToGo -= n;
+ }
+ fclose(fp);
+ }
+ }
+ else if (linkflag == DIRTYPE)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+
+ return(retval);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromFile *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a TAR file. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * const char *tar_name - TAR filename. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromFile(
+ const char *tar_name
+)
+{
+ int fd;
+ char *bufr;
+ ssize_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long size;
+ unsigned char linkflag;
+
+ retval = UNTAR_SUCCESSFUL;
+
+ if ((fd = open(tar_name, O_RDONLY)) < 0) {
+ return UNTAR_FAIL;
+ }
+
+ bufr = (char *)malloc(512);
+ if (bufr == NULL) {
+ return(UNTAR_FAIL);
+ }
+
+ while (1)
+ {
+ /* Read the header */
+ /* If the header read fails, we just consider it the end
+ of the tarfile. */
+ if ((n = read(fd, bufr, 512)) != 512)
+ {
+ break;
+ }
+
+ if (strncmp(&bufr[257], "ustar", 5))
+ {
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ size = _rtems_octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * Compute the TAR checksum and check with the value in
+ * the archive. The checksum is computed over the entire
+ * header, but the checksum field is substituted with blanks.
+ ******************************************************************/
+ hdr_chksum = _rtems_octal2ulong(&bufr[148], 8);
+ sum = _rtems_tar_header_checksum(bufr);
+
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == SYMTYPE)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ symlink(linkname,fname);
+ }
+ else if (linkflag == REGTYPE)
+ {
+ int out_fd;
+
+ /******************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the size rounded to the nearest 512-byte boundary.
+ *****************************************************************/
+ nblocks = (((size) + 511) & ~511) / 512;
+
+ if ((out_fd = creat(fname, 0644)) == -1)
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ }
+ }
+ else
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ n = MIN(n, size - i*512);
+ write(out_fd, bufr, n);
+ }
+ close(out_fd);
+ }
+ }
+ else if (linkflag == DIRTYPE)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+ free(bufr);
+ close(fd);
+
+ return(retval);
+}
+
+/************************************************************************
+ * Compute the TAR checksum and check with the value in
+ * the archive. The checksum is computed over the entire
+ * header, but the checksum field is substituted with blanks.
+ ************************************************************************/
+int
+_rtems_tar_header_checksum(
+ const char *bufr
+)
+{
+ int i, sum;
+
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ sum += 0xff & ' ';
+ else
+ sum += 0xff & bufr[i];
+ }
+ return(sum);
+}
diff --git a/cpukit/libmisc/untar/untar.h b/cpukit/libmisc/untar/untar.h
new file mode 100644
index 0000000000..264753f2f7
--- /dev/null
+++ b/cpukit/libmisc/untar/untar.h
@@ -0,0 +1,49 @@
+/*
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * 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_UNTAR_H
+#define _RTEMS_UNTAR_H
+
+#include <stddef.h>
+#include <tar.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UNTAR_SUCCESSFUL 0
+#define UNTAR_FAIL 1
+#define UNTAR_INVALID_CHECKSUM 2
+#define UNTAR_INVALID_HEADER 3
+
+
+int Untar_FromMemory(void *tar_buf, size_t size);
+int Untar_FromFile(const char *tar_name);
+
+/**************************************************************************
+ * This converts octal ASCII number representations into an
+ * unsigned long. Only support 32-bit numbers for now.
+ *************************************************************************/
+extern unsigned long
+_rtems_octal2ulong(const char *octascii, size_t len);
+
+/************************************************************************
+ * Compute the TAR checksum and check with the value in
+ * the archive. The checksum is computed over the entire
+ * header, but the checksum field is substituted with blanks.
+ ************************************************************************/
+extern int
+_rtems_tar_header_checksum(const char *bufr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTEMS_UNTAR_H */
diff --git a/cpukit/libmisc/uuid/COPYING b/cpukit/libmisc/uuid/COPYING
new file mode 100644
index 0000000000..2f17068367
--- /dev/null
+++ b/cpukit/libmisc/uuid/COPYING
@@ -0,0 +1,25 @@
+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, and the entire permission notice in its entirety,
+ including the disclaimer of warranties.
+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. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
diff --git a/cpukit/libmisc/uuid/README b/cpukit/libmisc/uuid/README
new file mode 100644
index 0000000000..6b5c9eee97
--- /dev/null
+++ b/cpukit/libmisc/uuid/README
@@ -0,0 +1,14 @@
+uuid - DCE compatible Universally Unique Identifier library
+
+The UUID library is used to generate unique identifiers for objects that may be
+accessible beyond the local system. This library generates UUIDs compatible
+with those created by the Open Software Foundation (OSF) Distributed Computing
+Environment (DCE) utility uuidgen.
+
+The UUIDs generated by this library can be reasonably expected to be unique
+within a system, and unique across all systems. They could be used, for
+instance, to generate unique HTTP cookies across multiple web servers without
+communication between the servers, and without fear of a name clash.
+
+This code is from the E2fsprogs project: http://e2fsprogs.sourceforge.net.
+The package was e2fsprogs-libs-1.41.5.tar.gz.
diff --git a/cpukit/libmisc/uuid/clear.c b/cpukit/libmisc/uuid/clear.c
new file mode 100644
index 0000000000..5a1d188f6e
--- /dev/null
+++ b/cpukit/libmisc/uuid/clear.c
@@ -0,0 +1,47 @@
+/*
+ * clear.c -- Clear a UUID
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "uuidP.h"
+
+void uuid_clear(uuid_t uu)
+{
+ memset(uu, 0, 16);
+}
+
diff --git a/cpukit/libmisc/uuid/compare.c b/cpukit/libmisc/uuid/compare.c
new file mode 100644
index 0000000000..888121f0ff
--- /dev/null
+++ b/cpukit/libmisc/uuid/compare.c
@@ -0,0 +1,59 @@
+/*
+ * compare.c --- compare whether or not two UUID's are the same
+ *
+ * Returns 0 if the two UUID's are different, and 1 if they are the same.
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include "uuidP.h"
+
+#define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1);
+
+int uuid_compare(const uuid_t uu1, const uuid_t uu2)
+{
+ struct uuid uuid1, uuid2;
+
+ uuid_unpack(uu1, &uuid1);
+ uuid_unpack(uu2, &uuid2);
+
+ UUCMP(uuid1.time_low, uuid2.time_low);
+ UUCMP(uuid1.time_mid, uuid2.time_mid);
+ UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
+ UUCMP(uuid1.clock_seq, uuid2.clock_seq);
+ return memcmp(uuid1.node, uuid2.node, 6);
+}
+
diff --git a/cpukit/libmisc/uuid/copy.c b/cpukit/libmisc/uuid/copy.c
new file mode 100644
index 0000000000..abf09d6fb3
--- /dev/null
+++ b/cpukit/libmisc/uuid/copy.c
@@ -0,0 +1,49 @@
+/*
+ * copy.c --- copy UUIDs
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "uuidP.h"
+
+void uuid_copy(uuid_t dst, const uuid_t src)
+{
+ unsigned char *cp1;
+ const unsigned char *cp2;
+ int i;
+
+ for (i=0, cp1 = dst, cp2 = src; i < 16; i++)
+ *cp1++ = *cp2++;
+}
diff --git a/cpukit/libmisc/uuid/gen_uuid.c b/cpukit/libmisc/uuid/gen_uuid.c
new file mode 100644
index 0000000000..7993ee5332
--- /dev/null
+++ b/cpukit/libmisc/uuid/gen_uuid.c
@@ -0,0 +1,670 @@
+/*
+ * gen_uuid.c --- generate a DCE-compatible uuid
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Force inclusion of SVID stuff since we need it if we're compiling in
+ * gcc-wall wall mode
+ */
+#define _SVID_SOURCE
+
+#ifdef _WIN32
+#define _WIN32_WINNT 0x0500
+#include <windows.h>
+#define UUID MYUUID
+#endif
+#include <stdio.h>
+#include <limits.h> /* for CHAR_BIT */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/wait.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NET_IF_DL_H
+#include <net/if_dl.h>
+#endif
+#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
+#include <sys/syscall.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#include "uuidP.h"
+#include "uuidd.h"
+
+#ifdef HAVE_SRANDOM
+#define srand(x) srandom(x)
+#define rand() random()
+#endif
+
+#ifdef TLS
+#define THREAD_LOCAL static TLS
+#else
+#define THREAD_LOCAL static
+#endif
+
+#if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48)
+#define DO_JRAND_MIX
+THREAD_LOCAL unsigned short jrand_seed[3];
+#endif
+
+#ifdef _WIN32
+static void gettimeofday (struct timeval *tv, void *dummy)
+{
+ FILETIME ftime;
+ uint64_t n;
+
+ GetSystemTimeAsFileTime (&ftime);
+ n = (((uint64_t) ftime.dwHighDateTime << 32)
+ + (uint64_t) ftime.dwLowDateTime);
+ if (n) {
+ n /= 10;
+ n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000;
+ }
+
+ tv->tv_sec = n / 1000000;
+ tv->tv_usec = n % 1000000;
+}
+
+static int getuid (void)
+{
+ return 1;
+}
+#endif
+
+static int get_random_fd(void)
+{
+ struct timeval tv;
+ static int fd = -2;
+ int i;
+
+ if (fd == -2) {
+ gettimeofday(&tv, 0);
+#ifndef _WIN32
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1)
+ fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
+ if (fd >= 0) {
+ i = fcntl(fd, F_GETFD);
+ if (i >= 0)
+ fcntl(fd, F_SETFD, i | FD_CLOEXEC);
+ }
+#endif
+ srand((getpid() << ((sizeof(pid_t)*CHAR_BIT)>>1)) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
+#ifdef DO_JRAND_MIX
+ jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF);
+ jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF);
+ jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
+#endif
+ }
+ /* Crank the random number generator a few times */
+ gettimeofday(&tv, 0);
+ for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
+ rand();
+ return fd;
+}
+
+
+/*
+ * Generate a series of random bytes. Use /dev/urandom if possible,
+ * and if not, use srandom/random.
+ */
+static void get_random_bytes(void *buf, int nbytes)
+{
+ int i, n = nbytes, fd = get_random_fd();
+ int lose_counter = 0;
+ unsigned char *cp = (unsigned char *) buf;
+#ifdef DO_JRAND_MIX
+ unsigned short tmp_seed[3];
+#endif
+
+ if (fd >= 0) {
+ while (n > 0) {
+ i = read(fd, cp, n);
+ if (i <= 0) {
+ if (lose_counter++ > 16)
+ break;
+ continue;
+ }
+ n -= i;
+ cp += i;
+ lose_counter = 0;
+ }
+ }
+
+ /*
+ * We do this all the time, but this is the only source of
+ * randomness if /dev/random/urandom is out to lunch.
+ */
+ for (cp = buf, i = 0; i < nbytes; i++)
+ *cp++ ^= (rand() >> 7) & 0xFF;
+#ifdef DO_JRAND_MIX
+ memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed));
+ jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid);
+ for (cp = buf, i = 0; i < nbytes; i++)
+ *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF;
+ memcpy(jrand_seed, tmp_seed,
+ sizeof(jrand_seed)-sizeof(unsigned short));
+#endif
+
+ return;
+}
+
+/*
+ * Get the ethernet hardware address, if we can find it...
+ *
+ * XXX for a windows version, probably should use GetAdaptersInfo:
+ * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451
+ * commenting out get_node_id just to get gen_uuid to compile under windows
+ * is not the right way to go!
+ */
+static int get_node_id(unsigned char *node_id)
+{
+#ifdef HAVE_NET_IF_H
+ int sd;
+ struct ifreq ifr, *ifrp;
+ struct ifconf ifc;
+ char buf[1024];
+ int n, i;
+ unsigned char *a;
+#ifdef HAVE_NET_IF_DL_H
+ struct sockaddr_dl *sdlp;
+#endif
+
+/*
+ * BSD 4.4 defines the size of an ifreq to be
+ * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
+ * However, under earlier systems, sa_len isn't present, so the size is
+ * just sizeof(struct ifreq)
+ */
+#ifdef HAVE_SA_LEN
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#define ifreq_size(i) max(sizeof(struct ifreq),\
+ sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
+#else
+#define ifreq_size(i) sizeof(struct ifreq)
+#endif /* HAVE_SA_LEN*/
+
+ sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (sd < 0) {
+ return -1;
+ }
+ memset(buf, 0, sizeof(buf));
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
+ close(sd);
+ return -1;
+ }
+ n = ifc.ifc_len;
+ for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
+ ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
+ strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
+#ifdef SIOCGIFHWADDR
+ if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
+ continue;
+ a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
+#else
+#ifdef SIOCGENADDR
+ if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
+ continue;
+ a = (unsigned char *) ifr.ifr_enaddr;
+#else
+#ifdef HAVE_NET_IF_DL_H
+ sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
+ if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
+ continue;
+ a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
+#else
+ /*
+ * XXX we don't have a way of getting the hardware
+ * address
+ */
+ close(sd);
+ return 0;
+#endif /* HAVE_NET_IF_DL_H */
+#endif /* SIOCGENADDR */
+#endif /* SIOCGIFHWADDR */
+ if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
+ continue;
+ if (node_id) {
+ memcpy(node_id, a, 6);
+ close(sd);
+ return 1;
+ }
+ }
+ close(sd);
+#endif
+ return 0;
+}
+
+/* Assume that the gettimeofday() has microsecond granularity */
+#define MAX_ADJUSTMENT 10
+
+static int get_clock(uint32_t *clock_high, uint32_t *clock_low,
+ uint16_t *ret_clock_seq, int *num)
+{
+ THREAD_LOCAL int adjustment = 0;
+ THREAD_LOCAL struct timeval last = {0, 0};
+ THREAD_LOCAL int state_fd = -2;
+ THREAD_LOCAL FILE *state_f;
+ THREAD_LOCAL uint16_t clock_seq;
+ struct timeval tv;
+ struct flock fl;
+ uint64_t clock_reg;
+ mode_t save_umask;
+ int len;
+
+ if (state_fd == -2) {
+ save_umask = umask(0);
+ state_fd = open("/var/lib/libuuid/clock.txt",
+ O_RDWR|O_CREAT, 0660);
+ (void) umask(save_umask);
+ state_f = fdopen(state_fd, "r+");
+ if (!state_f) {
+ close(state_fd);
+ state_fd = -1;
+ }
+ }
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_pid = 0;
+ if (state_fd >= 0) {
+ rewind(state_f);
+ while (fcntl(state_fd, F_SETLKW, &fl) < 0) {
+ if ((errno == EAGAIN) || (errno == EINTR))
+ continue;
+ fclose(state_f);
+ close(state_fd);
+ state_fd = -1;
+ break;
+ }
+ }
+ if (state_fd >= 0) {
+ unsigned int cl;
+ unsigned long tv1, tv2;
+ int a;
+
+ if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n",
+ &cl, &tv1, &tv2, &a) == 4) {
+ clock_seq = cl & 0x3FFF;
+ last.tv_sec = tv1;
+ last.tv_usec = tv2;
+ adjustment = a;
+ }
+ }
+
+ if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
+ get_random_bytes(&clock_seq, sizeof(clock_seq));
+ clock_seq &= 0x3FFF;
+ gettimeofday(&last, 0);
+ last.tv_sec--;
+ }
+
+try_again:
+ gettimeofday(&tv, 0);
+ if ((tv.tv_sec < last.tv_sec) ||
+ ((tv.tv_sec == last.tv_sec) &&
+ (tv.tv_usec < last.tv_usec))) {
+ clock_seq = (clock_seq+1) & 0x3FFF;
+ adjustment = 0;
+ last = tv;
+ } else if ((tv.tv_sec == last.tv_sec) &&
+ (tv.tv_usec == last.tv_usec)) {
+ if (adjustment >= MAX_ADJUSTMENT)
+ goto try_again;
+ adjustment++;
+ } else {
+ adjustment = 0;
+ last = tv;
+ }
+
+ clock_reg = tv.tv_usec*10 + adjustment;
+ clock_reg += ((uint64_t) tv.tv_sec)*10000000;
+ clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
+
+ if (num && (*num > 1)) {
+ adjustment += *num - 1;
+ last.tv_usec += adjustment / 10;
+ adjustment = adjustment % 10;
+ last.tv_sec += last.tv_usec / 1000000;
+ last.tv_usec = last.tv_usec % 1000000;
+ }
+
+ if (state_fd > 0) {
+ rewind(state_f);
+ len = fprintf(state_f,
+ "clock: %04x tv: %016lu %08lu adj: %08d\n",
+ clock_seq, last.tv_sec, last.tv_usec, adjustment);
+ fflush(state_f);
+ if (ftruncate(state_fd, len) < 0) {
+ fprintf(state_f, " \n");
+ fflush(state_f);
+ }
+ rewind(state_f);
+ fl.l_type = F_UNLCK;
+ fcntl(state_fd, F_SETLK, &fl);
+ }
+
+ *clock_high = clock_reg >> 32;
+ *clock_low = clock_reg;
+ *ret_clock_seq = clock_seq;
+ return 0;
+}
+
+/* unused */
+#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
+static ssize_t read_all(int fd, char *buf, size_t count)
+{
+ ssize_t ret;
+ ssize_t c = 0;
+
+ memset(buf, 0, count);
+ while (count > 0) {
+ ret = read(fd, buf, count);
+ if (ret < 0) {
+ if ((errno == EAGAIN) || (errno == EINTR))
+ continue;
+ return -1;
+ }
+ count -= ret;
+ buf += ret;
+ c += ret;
+ }
+ return c;
+}
+#endif
+
+#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
+
+/*
+ * Close all file descriptors
+ */
+static void close_all_fds(void)
+{
+ int i, max;
+
+#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
+ max = sysconf(_SC_OPEN_MAX);
+#elif defined(HAVE_GETDTABLESIZE)
+ max = getdtablesize();
+#elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
+ struct rlimit rl;
+
+ getrlimit(RLIMIT_NOFILE, &rl);
+ max = rl.rlim_cur;
+#else
+ max = OPEN_MAX;
+#endif
+
+ for (i=0; i < max; i++)
+ close(i);
+}
+
+#endif
+
+
+/*
+ * Try using the uuidd daemon to generate the UUID
+ *
+ * Returns 0 on success, non-zero on failure.
+ */
+static int get_uuid_via_daemon(int op, uuid_t out, int *num)
+{
+#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
+ char op_buf[64];
+ int op_len;
+ int s;
+ ssize_t ret;
+ int32_t reply_len = 0, expected = 16;
+ struct sockaddr_un srv_addr;
+ pid_t pid;
+ static const char *uuidd_path = UUIDD_PATH;
+ static int access_ret = -2;
+ static int start_attempts = 0;
+
+ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ return -1;
+
+ srv_addr.sun_family = AF_UNIX;
+ strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH);
+
+ if (connect(s, (const struct sockaddr *) &srv_addr,
+ sizeof(struct sockaddr_un)) < 0) {
+ if (access_ret == -2)
+ access_ret = access(uuidd_path, X_OK);
+ if (access_ret == 0 && start_attempts++ < 5) {
+ if ((pid = fork()) == 0) {
+ close_all_fds();
+ execl(uuidd_path, "uuidd", "-qT", "300",
+ (char *) NULL);
+ exit(1);
+ }
+ (void) waitpid(pid, 0, 0);
+ if (connect(s, (const struct sockaddr *) &srv_addr,
+ sizeof(struct sockaddr_un)) < 0)
+ goto fail;
+ } else
+ goto fail;
+ }
+ op_buf[0] = op;
+ op_len = 1;
+ if (op == UUIDD_OP_BULK_TIME_UUID) {
+ memcpy(op_buf+1, num, sizeof(*num));
+ op_len += sizeof(*num);
+ expected += sizeof(*num);
+ }
+
+ ret = write(s, op_buf, op_len);
+ if (ret < 1)
+ goto fail;
+
+ ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
+ if (ret < 0)
+ goto fail;
+
+ if (reply_len != expected)
+ goto fail;
+
+ ret = read_all(s, op_buf, reply_len);
+
+ if (op == UUIDD_OP_BULK_TIME_UUID)
+ memcpy(op_buf+16, num, sizeof(int));
+
+ memcpy(out, op_buf, 16);
+
+ close(s);
+ return ((ret == expected) ? 0 : -1);
+
+fail:
+ close(s);
+#endif
+ return -1;
+}
+
+void uuid__generate_time(uuid_t out, int *num)
+{
+ static unsigned char node_id[6];
+ static int has_init = 0;
+ struct uuid uu;
+ uint32_t clock_mid;
+
+ if (!has_init) {
+ if (get_node_id(node_id) <= 0) {
+ get_random_bytes(node_id, 6);
+ /*
+ * Set multicast bit, to prevent conflicts
+ * with IEEE 802 addresses obtained from
+ * network cards
+ */
+ node_id[0] |= 0x01;
+ }
+ has_init = 1;
+ }
+ get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num);
+ uu.clock_seq |= 0x8000;
+ uu.time_mid = (uint16_t) clock_mid;
+ uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
+ memcpy(uu.node, node_id, 6);
+ uuid_pack(&uu, out);
+}
+
+void uuid_generate_time(uuid_t out)
+{
+#ifdef TLS
+ THREAD_LOCAL int num = 0;
+ THREAD_LOCAL struct uuid uu;
+ THREAD_LOCAL time_t last_time = 0;
+ time_t now;
+
+ if (num > 0) {
+ now = time(0);
+ if (now > last_time+1)
+ num = 0;
+ }
+ if (num <= 0) {
+ num = 1000;
+ if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID,
+ out, &num) == 0) {
+ last_time = time(0);
+ uuid_unpack(out, &uu);
+ num--;
+ return;
+ }
+ num = 0;
+ }
+ if (num > 0) {
+ uu.time_low++;
+ if (uu.time_low == 0) {
+ uu.time_mid++;
+ if (uu.time_mid == 0)
+ uu.time_hi_and_version++;
+ }
+ num--;
+ uuid_pack(&uu, out);
+ return;
+ }
+#else
+ if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0)
+ return;
+#endif
+
+ uuid__generate_time(out, 0);
+}
+
+
+void uuid__generate_random(uuid_t out, int *num)
+{
+ uuid_t buf;
+ struct uuid uu;
+ int i, n;
+
+ if (!num || !*num)
+ n = 1;
+ else
+ n = *num;
+
+ for (i = 0; i < n; i++) {
+ get_random_bytes(buf, sizeof(buf));
+ uuid_unpack(buf, &uu);
+
+ uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
+ uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF)
+ | 0x4000;
+ uuid_pack(&uu, out);
+ out += sizeof(uuid_t);
+ }
+}
+
+void uuid_generate_random(uuid_t out)
+{
+ int num = 1;
+ /* No real reason to use the daemon for random uuid's -- yet */
+
+ uuid__generate_random(out, &num);
+}
+
+
+/*
+ * This is the generic front-end to uuid_generate_random and
+ * uuid_generate_time. It uses uuid_generate_random only if
+ * /dev/urandom is available, since otherwise we won't have
+ * high-quality randomness.
+ */
+void uuid_generate(uuid_t out)
+{
+ if (get_random_fd() >= 0)
+ uuid_generate_random(out);
+ else
+ uuid_generate_time(out);
+}
diff --git a/cpukit/libmisc/uuid/isnull.c b/cpukit/libmisc/uuid/isnull.c
new file mode 100644
index 0000000000..11bd765d98
--- /dev/null
+++ b/cpukit/libmisc/uuid/isnull.c
@@ -0,0 +1,52 @@
+/*
+ * isnull.c --- Check whether or not the UUID is null
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "uuidP.h"
+
+/* Returns 1 if the uuid is the NULL uuid */
+int uuid_is_null(const uuid_t uu)
+{
+ const unsigned char *cp;
+ int i;
+
+ for (i=0, cp = uu; i < 16; i++)
+ if (*cp++)
+ return 0;
+ return 1;
+}
+
diff --git a/cpukit/libmisc/uuid/pack.c b/cpukit/libmisc/uuid/pack.c
new file mode 100644
index 0000000000..d4c9955374
--- /dev/null
+++ b/cpukit/libmisc/uuid/pack.c
@@ -0,0 +1,73 @@
+/*
+ * Internal routine for packing UUID's
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include "uuidP.h"
+
+void uuid_pack(const struct uuid *uu, uuid_t ptr)
+{
+ uint32_t tmp;
+ unsigned char *out = ptr;
+
+ tmp = uu->time_low;
+ out[3] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[2] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[1] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[0] = (unsigned char) tmp;
+
+ tmp = uu->time_mid;
+ out[5] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[4] = (unsigned char) tmp;
+
+ tmp = uu->time_hi_and_version;
+ out[7] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[6] = (unsigned char) tmp;
+
+ tmp = uu->clock_seq;
+ out[9] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[8] = (unsigned char) tmp;
+
+ memcpy(out+10, uu->node, 6);
+}
+
diff --git a/cpukit/libmisc/uuid/parse.c b/cpukit/libmisc/uuid/parse.c
new file mode 100644
index 0000000000..d995df1db0
--- /dev/null
+++ b/cpukit/libmisc/uuid/parse.c
@@ -0,0 +1,83 @@
+/*
+ * parse.c --- UUID parsing
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "uuidP.h"
+
+int uuid_parse(const char *in, uuid_t uu)
+{
+ struct uuid uuid;
+ int i;
+ const char *cp;
+ char buf[3];
+
+ if (strlen(in) != 36)
+ return -1;
+ for (i=0, cp = in; i <= 36; i++,cp++) {
+ if ((i == 8) || (i == 13) || (i == 18) ||
+ (i == 23)) {
+ if (*cp == '-')
+ continue;
+ else
+ return -1;
+ }
+ if (i== 36)
+ if (*cp == 0)
+ continue;
+ if (!isxdigit((unsigned char)*cp))
+ return -1;
+ }
+ uuid.time_low = strtoul(in, NULL, 16);
+ uuid.time_mid = strtoul(in+9, NULL, 16);
+ uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
+ uuid.clock_seq = strtoul(in+19, NULL, 16);
+ cp = in+24;
+ buf[2] = 0;
+ for (i=0; i < 6; i++) {
+ buf[0] = *cp++;
+ buf[1] = *cp++;
+ uuid.node[i] = strtoul(buf, NULL, 16);
+ }
+
+ uuid_pack(&uuid, uu);
+ return 0;
+}
diff --git a/cpukit/libmisc/uuid/unpack.c b/cpukit/libmisc/uuid/unpack.c
new file mode 100644
index 0000000000..4520633b7e
--- /dev/null
+++ b/cpukit/libmisc/uuid/unpack.c
@@ -0,0 +1,67 @@
+/*
+ * Internal routine for unpacking UUID
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include "uuidP.h"
+
+void uuid_unpack(const uuid_t in, struct uuid *uu)
+{
+ const uint8_t *ptr = in;
+ uint32_t tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->time_low = tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->time_mid = tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->time_hi_and_version = tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->clock_seq = tmp;
+
+ memcpy(uu->node, ptr, 6);
+}
+
diff --git a/cpukit/libmisc/uuid/unparse.c b/cpukit/libmisc/uuid/unparse.c
new file mode 100644
index 0000000000..25cf07dc78
--- /dev/null
+++ b/cpukit/libmisc/uuid/unparse.c
@@ -0,0 +1,80 @@
+/*
+ * unparse.c -- convert a UUID to string
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "uuidP.h"
+
+static const char *fmt_lower =
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
+
+static const char *fmt_upper =
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X";
+
+#ifdef UUID_UNPARSE_DEFAULT_UPPER
+#define FMT_DEFAULT fmt_upper
+#else
+#define FMT_DEFAULT fmt_lower
+#endif
+
+static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt)
+{
+ struct uuid uuid;
+
+ uuid_unpack(uu, &uuid);
+ sprintf(out, fmt,
+ uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
+ uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
+ uuid.node[0], uuid.node[1], uuid.node[2],
+ uuid.node[3], uuid.node[4], uuid.node[5]);
+}
+
+void uuid_unparse_lower(const uuid_t uu, char *out)
+{
+ uuid_unparse_x(uu, out, fmt_lower);
+}
+
+void uuid_unparse_upper(const uuid_t uu, char *out)
+{
+ uuid_unparse_x(uu, out, fmt_upper);
+}
+
+void uuid_unparse(const uuid_t uu, char *out)
+{
+ uuid_unparse_x(uu, out, FMT_DEFAULT);
+}
diff --git a/cpukit/libmisc/uuid/uuid.h b/cpukit/libmisc/uuid/uuid.h
new file mode 100644
index 0000000000..ca846da0f0
--- /dev/null
+++ b/cpukit/libmisc/uuid/uuid.h
@@ -0,0 +1,103 @@
+/*
+ * Public include file for the UUID library
+ *
+ * Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifndef _UUID_UUID_H
+#define _UUID_UUID_H
+
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/time.h>
+#endif
+#include <time.h>
+
+typedef unsigned char uuid_t[16];
+
+/* UUID Variant definitions */
+#define UUID_VARIANT_NCS 0
+#define UUID_VARIANT_DCE 1
+#define UUID_VARIANT_MICROSOFT 2
+#define UUID_VARIANT_OTHER 3
+
+/* UUID Type definitions */
+#define UUID_TYPE_DCE_TIME 1
+#define UUID_TYPE_DCE_RANDOM 4
+
+/* Allow UUID constants to be defined */
+#ifdef __GNUC__
+#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
+ static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
+#else
+#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
+ static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* clear.c */
+void uuid_clear(uuid_t uu);
+
+/* compare.c */
+int uuid_compare(const uuid_t uu1, const uuid_t uu2);
+
+/* copy.c */
+void uuid_copy(uuid_t dst, const uuid_t src);
+
+/* gen_uuid.c */
+void uuid_generate(uuid_t out);
+void uuid_generate_random(uuid_t out);
+void uuid_generate_time(uuid_t out);
+
+/* isnull.c */
+int uuid_is_null(const uuid_t uu);
+
+/* parse.c */
+int uuid_parse(const char *in, uuid_t uu);
+
+/* unparse.c */
+void uuid_unparse(const uuid_t uu, char *out);
+void uuid_unparse_lower(const uuid_t uu, char *out);
+void uuid_unparse_upper(const uuid_t uu, char *out);
+
+/* uuid_time.c */
+time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
+int uuid_type(const uuid_t uu);
+int uuid_variant(const uuid_t uu);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UUID_UUID_H */
diff --git a/cpukit/libmisc/uuid/uuidP.h b/cpukit/libmisc/uuid/uuidP.h
new file mode 100644
index 0000000000..d0e24c6942
--- /dev/null
+++ b/cpukit/libmisc/uuid/uuidP.h
@@ -0,0 +1,63 @@
+/*
+ * uuid.h -- private header file for uuids
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <uuid/uuid_types.h>
+#endif
+#include <sys/types.h>
+
+#include "uuid.h"
+
+/*
+ * Offset between 15-Oct-1582 and 1-Jan-70
+ */
+#define TIME_OFFSET_HIGH 0x01B21DD2
+#define TIME_OFFSET_LOW 0x13814000
+
+struct uuid {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint16_t clock_seq;
+ uint8_t node[6];
+};
+
+
+/*
+ * prototypes
+ */
+void uuid_pack(const struct uuid *uu, uuid_t ptr);
+void uuid_unpack(const uuid_t in, struct uuid *uu);
diff --git a/cpukit/libmisc/uuid/uuid_time.c b/cpukit/libmisc/uuid/uuid_time.c
new file mode 100644
index 0000000000..f9325968df
--- /dev/null
+++ b/cpukit/libmisc/uuid/uuid_time.c
@@ -0,0 +1,175 @@
+/*
+ * uuid_time.c --- Interpret the time field from a uuid. This program
+ * violates the UUID abstraction barrier by reaching into the guts
+ * of a UUID and interpreting it.
+ *
+ * Copyright (C) 1998, 1999 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef _WIN32
+#define _WIN32_WINNT 0x0500
+#include <windows.h>
+#define UUID MYUUID
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <time.h>
+
+#include "uuidP.h"
+
+time_t uuid_time(const uuid_t uu, struct timeval *ret_tv)
+{
+ struct timeval tv;
+ struct uuid uuid;
+ uint32_t high;
+ uint64_t clock_reg;
+
+ uuid_unpack(uu, &uuid);
+
+ high = uuid.time_mid | ((uint32_t)(uuid.time_hi_and_version & 0xFFF) << 16);
+ clock_reg = uuid.time_low | ((uint64_t) high << 32);
+
+ clock_reg -= (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
+ tv.tv_sec = clock_reg / 10000000;
+ tv.tv_usec = (clock_reg % 10000000) / 10;
+
+ if (ret_tv)
+ *ret_tv = tv;
+
+ return tv.tv_sec;
+}
+
+int uuid_type(const uuid_t uu)
+{
+ struct uuid uuid;
+
+ uuid_unpack(uu, &uuid);
+ return ((uuid.time_hi_and_version >> 12) & 0xF);
+}
+
+int uuid_variant(const uuid_t uu)
+{
+ struct uuid uuid;
+ int var;
+
+ uuid_unpack(uu, &uuid);
+ var = uuid.clock_seq;
+
+ if ((var & 0x8000) == 0)
+ return UUID_VARIANT_NCS;
+ if ((var & 0x4000) == 0)
+ return UUID_VARIANT_DCE;
+ if ((var & 0x2000) == 0)
+ return UUID_VARIANT_MICROSOFT;
+ return UUID_VARIANT_OTHER;
+}
+
+#ifdef DEBUG
+static const char *variant_string(int variant)
+{
+ switch (variant) {
+ case UUID_VARIANT_NCS:
+ return "NCS";
+ case UUID_VARIANT_DCE:
+ return "DCE";
+ case UUID_VARIANT_MICROSOFT:
+ return "Microsoft";
+ default:
+ return "Other";
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ uuid_t buf;
+ time_t time_reg;
+ struct timeval tv;
+ int type, variant;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s uuid\n", argv[0]);
+ exit(1);
+ }
+ if (uuid_parse(argv[1], buf)) {
+ fprintf(stderr, "Invalid UUID: %s\n", argv[1]);
+ exit(1);
+ }
+ variant = uuid_variant(buf);
+ type = uuid_type(buf);
+ time_reg = uuid_time(buf, &tv);
+
+ printf("UUID variant is %d (%s)\n", variant, variant_string(variant));
+ if (variant != UUID_VARIANT_DCE) {
+ printf("Warning: This program only knows how to interpret "
+ "DCE UUIDs.\n\tThe rest of the output is likely "
+ "to be incorrect!!\n");
+ }
+ printf("UUID type is %d", type);
+ switch (type) {
+ case 1:
+ printf(" (time based)\n");
+ break;
+ case 2:
+ printf(" (DCE)\n");
+ break;
+ case 3:
+ printf(" (name-based)\n");
+ break;
+ case 4:
+ printf(" (random)\n");
+ break;
+ default:
+ printf("\n");
+ }
+ if (type != 1) {
+ printf("Warning: not a time-based UUID, so UUID time "
+ "decoding will likely not work!\n");
+ }
+ printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec,
+ ctime(&time_reg));
+
+ return 0;
+}
+#endif
diff --git a/cpukit/libmisc/uuid/uuidd.h b/cpukit/libmisc/uuid/uuidd.h
new file mode 100644
index 0000000000..528acdc9d0
--- /dev/null
+++ b/cpukit/libmisc/uuid/uuidd.h
@@ -0,0 +1,53 @@
+/*
+ * Definitions used by the uuidd daemon
+ *
+ * Copyright (C) 2007 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifndef _UUID_UUIDD_H
+#define _UUID_UUIDD_H
+
+#define UUIDD_SOCKET_PATH "/var/lib/libuuid/request"
+#define UUIDD_PIDFILE_PATH "/var/lib/libuuid/uuidd.pid"
+#define UUIDD_PATH "/usr/sbin/uuidd"
+
+#define UUIDD_OP_GETPID 0
+#define UUIDD_OP_GET_MAXOP 1
+#define UUIDD_OP_TIME_UUID 2
+#define UUIDD_OP_RANDOM_UUID 3
+#define UUIDD_OP_BULK_TIME_UUID 4
+#define UUIDD_OP_BULK_RANDOM_UUID 5
+#define UUIDD_MAX_OP UUIDD_OP_BULK_RANDOM_UUID
+
+extern void uuid__generate_time(uuid_t out, int *num);
+extern void uuid__generate_random(uuid_t out, int *num);
+
+#endif /* _UUID_UUID_H */