summaryrefslogtreecommitdiff
path: root/release/src/router/busybox/coreutils
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2015-01-03 12:04:58 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2015-01-03 12:04:58 +0100
commit008d0be72b2f160382c6e880765e96b64a050c65 (patch)
tree36f48a98a3815a408e2ce1693dd182af90f80305 /release/src/router/busybox/coreutils
parent611becfb8726c60cb060368541ad98191d4532f5 (diff)
downloadtomato-008d0be72b2f160382c6e880765e96b64a050c65.tar.gz
tomato-008d0be72b2f160382c6e880765e96b64a050c65.tar.bz2
imported original firmware WRT54GL_v4.30.11_11_US
Diffstat (limited to 'release/src/router/busybox/coreutils')
-rwxr-xr-xrelease/src/router/busybox/coreutils/Config.in602
-rw-r--r--release/src/router/busybox/coreutils/Makefile30
-rwxr-xr-xrelease/src/router/busybox/coreutils/Makefile.in92
-rw-r--r--release/src/router/busybox/coreutils/basename.c62
-rw-r--r--release/src/router/busybox/coreutils/cal.c392
-rw-r--r--release/src/router/busybox/coreutils/cat.c67
-rw-r--r--release/src/router/busybox/coreutils/chgrp.c85
-rw-r--r--release/src/router/busybox/coreutils/chmod.c112
-rw-r--r--release/src/router/busybox/coreutils/chown.c117
-rw-r--r--release/src/router/busybox/coreutils/chroot.c53
-rw-r--r--release/src/router/busybox/coreutils/cmp.c152
-rw-r--r--release/src/router/busybox/coreutils/cp.c112
-rw-r--r--release/src/router/busybox/coreutils/cut.c344
-rw-r--r--release/src/router/busybox/coreutils/date.c275
-rw-r--r--release/src/router/busybox/coreutils/dd.c203
-rw-r--r--release/src/router/busybox/coreutils/df.c170
-rw-r--r--release/src/router/busybox/coreutils/dirname.c39
-rw-r--r--release/src/router/busybox/coreutils/dos2unix.c196
-rw-r--r--release/src/router/busybox/coreutils/du.c265
-rw-r--r--release/src/router/busybox/coreutils/echo.c165
-rw-r--r--release/src/router/busybox/coreutils/env.c144
-rw-r--r--release/src/router/busybox/coreutils/expr.c529
-rw-r--r--release/src/router/busybox/coreutils/false.c32
-rw-r--r--release/src/router/busybox/coreutils/fold.c194
-rw-r--r--release/src/router/busybox/coreutils/head.c138
-rw-r--r--release/src/router/busybox/coreutils/hostid.c38
-rw-r--r--release/src/router/busybox/coreutils/id.c110
-rw-r--r--release/src/router/busybox/coreutils/length.c19
-rw-r--r--release/src/router/busybox/coreutils/libcoreutils/Makefile30
-rwxr-xr-xrelease/src/router/busybox/coreutils/libcoreutils/Makefile.in32
-rw-r--r--release/src/router/busybox/coreutils/libcoreutils/coreutils.h12
-rw-r--r--release/src/router/busybox/coreutils/libcoreutils/cp_mv_stat.c45
-rw-r--r--release/src/router/busybox/coreutils/libcoreutils/getopt_mk_fifo_nod.c45
-rw-r--r--release/src/router/busybox/coreutils/libcoreutils/xgetoptfile_sort_uniq.c38
-rw-r--r--release/src/router/busybox/coreutils/ln.c105
-rw-r--r--release/src/router/busybox/coreutils/logname.c55
-rw-r--r--release/src/router/busybox/coreutils/ls.c1097
-rw-r--r--release/src/router/busybox/coreutils/md5sum.c1102
-rw-r--r--release/src/router/busybox/coreutils/mkdir.c75
-rw-r--r--release/src/router/busybox/coreutils/mkfifo.c51
-rw-r--r--release/src/router/busybox/coreutils/mknod.c63
-rw-r--r--release/src/router/busybox/coreutils/mv.c143
-rw-r--r--release/src/router/busybox/coreutils/od.c231
-rw-r--r--release/src/router/busybox/coreutils/printf.c452
-rw-r--r--release/src/router/busybox/coreutils/pwd.c37
-rw-r--r--release/src/router/busybox/coreutils/realpath.c54
-rw-r--r--release/src/router/busybox/coreutils/rm.c66
-rw-r--r--release/src/router/busybox/coreutils/rmdir.c73
-rw-r--r--release/src/router/busybox/coreutils/sha1sum.c492
-rw-r--r--release/src/router/busybox/coreutils/sleep.c86
-rw-r--r--release/src/router/busybox/coreutils/sort.c100
-rw-r--r--release/src/router/busybox/coreutils/stty.c1313
-rw-r--r--release/src/router/busybox/coreutils/sync.c36
-rw-r--r--release/src/router/busybox/coreutils/tail.c339
-rw-r--r--release/src/router/busybox/coreutils/tee.c115
-rw-r--r--release/src/router/busybox/coreutils/test.c545
-rw-r--r--release/src/router/busybox/coreutils/touch.c76
-rw-r--r--release/src/router/busybox/coreutils/tr.c248
-rw-r--r--release/src/router/busybox/coreutils/true.c32
-rw-r--r--release/src/router/busybox/coreutils/tty.c58
-rw-r--r--release/src/router/busybox/coreutils/uname.c118
-rw-r--r--release/src/router/busybox/coreutils/uniq.c112
-rw-r--r--release/src/router/busybox/coreutils/usleep.c41
-rw-r--r--release/src/router/busybox/coreutils/uudecode.c353
-rw-r--r--release/src/router/busybox/coreutils/uuencode.c149
-rw-r--r--release/src/router/busybox/coreutils/watch.c110
-rw-r--r--release/src/router/busybox/coreutils/wc.c227
-rw-r--r--release/src/router/busybox/coreutils/who.c83
-rw-r--r--release/src/router/busybox/coreutils/whoami.c44
-rw-r--r--release/src/router/busybox/coreutils/yes.c56
70 files changed, 13276 insertions, 0 deletions
diff --git a/release/src/router/busybox/coreutils/Config.in b/release/src/router/busybox/coreutils/Config.in
new file mode 100755
index 00000000..3f1e714e
--- /dev/null
+++ b/release/src/router/busybox/coreutils/Config.in
@@ -0,0 +1,602 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Coreutils"
+
+config CONFIG_BASENAME
+ bool "basename"
+ default n
+ help
+ basename is used to strip the directory and suffix from filenames,
+ leaving just the filename itself. Enable this option if you wish
+ to enable the 'basename' utility.
+
+config CONFIG_CAL
+ bool "cal"
+ default n
+ help
+ cal is used to display a montly calender.
+
+config CONFIG_CAT
+ bool "cat"
+ default n
+ help
+ cat is used to concatenate files and print them to the standard
+ output. Enable this option if you wish to enable the 'cat' utility.
+
+config CONFIG_CHGRP
+ bool "chgrp"
+ default n
+ help
+ chgrp is used to change the group owership of files.
+
+config CONFIG_CHMOD
+ bool "chmod"
+ default n
+ help
+ chmod is used to change the access permission of files.
+
+config CONFIG_CHOWN
+ bool "chown"
+ default n
+ help
+ chown is used too change the user and/or group ownership
+ of files.
+
+config CONFIG_CHROOT
+ bool "chroot"
+ default n
+ help
+ chroot is used to change the root directory and run a command.
+ The default command is `/bin/sh'.
+
+config CONFIG_CMP
+ bool "cmp"
+ default n
+ help
+ cmp is used to compare two files and returns the result
+ to standard output.
+
+config CONFIG_CP
+ bool "cp"
+ default n
+ help
+ cp is used to copy files and directories.
+
+config CONFIG_CUT
+ bool "cut"
+ default n
+ help
+ cut is used to print selected parts of lines from
+ each file to stdout.
+
+if CONFIG_WATCH
+ config CONFIG_DATE
+ default y
+ comment "date (forced enabled for use with watch)"
+endif
+
+if !CONFIG_WATCH
+ config CONFIG_DATE
+ bool "date"
+ default n
+ help
+ date is used to set the system date or display the
+ current time in the given format.
+endif
+
+config CONFIG_FEATURE_DATE_ISOFMT
+ bool " Enable ISO date format output (-I)"
+ default y
+ depends on CONFIG_DATE
+ help
+ Enable option (-I) to output an ISO-8601 compliant
+ date/time string.
+
+config CONFIG_DD
+ bool "dd"
+ default n
+ help
+ dd copies a file (from standard input to standard output,
+ by default) using specific input and output blocksizes,
+ while optionally performing conversions on it.
+
+config CONFIG_DF
+ bool "df"
+ default n
+ help
+ df reports the amount of disk space used and available
+ on filesystems.
+
+config CONFIG_DIRNAME
+ bool "dirname"
+ default n
+ help
+ dirname is used to strip a non directory suffix from
+ a file name.
+
+config CONFIG_DOS2UNIX
+ bool "dos2unix/unix2dos"
+ default n
+ help
+ dos2unix is uses to convert a text file from DOS format to
+ UNIX format, and vice versa.
+
+config CONFIG_UNIX2DOS
+ bool
+ default y
+ depends on CONFIG_DOS2UNIX
+
+config CONFIG_DU
+ bool "du (default blocksize of 512 bytes)"
+ default n
+ help
+ du is used to report the amount of disk space used
+ for specified files.
+
+config CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
+ bool " Use a default blocksize of 1024 bytes (1K)"
+ default y
+ depends on CONFIG_DU
+ help
+ Use a blocksize of (1K) instead of the default 512b.
+
+config CONFIG_ECHO
+ bool "echo (basic SUSv3 version taking no options"
+ default n
+ help
+ echo is used to print a specified string to stdout.
+
+config CONFIG_FEATURE_FANCY_ECHO
+ bool " Enable echo options (-n and -e)"
+ default y
+ depends on CONFIG_ECHO
+ help
+ This adds options (-n and -e) to echo.
+
+config CONFIG_ENV
+ bool "env"
+ default n
+ help
+ env is used to set an environment variable and run
+ a command, without options it displays the current
+ environment.
+
+config CONFIG_EXPR
+ bool "expr"
+ default n
+ help
+ expr is used to calculate numbers and print the result
+ to standard output.
+
+if CONFIG_HUSH || CONFIG_LASH || CONFIG_MSH
+ config CONFIG_FALSE
+ default y
+ comment "false (forced enabled for use with shell)"
+endif
+
+if !CONFIG_HUSH && !CONFIG_LASH && !CONFIG_MSH
+ config CONFIG_FALSE
+ bool "false"
+ default n
+ help
+ false returns an exit code of FALSE (1).
+endif
+
+config CONFIG_FOLD
+ bool "fold"
+ default n
+ help
+ Wrap text to fit a specific width.
+
+config CONFIG_HEAD
+ bool "head"
+ default n
+ help
+ head is used to print the first specified number of lines
+ from files.
+
+config CONFIG_FEATURE_FANCY_HEAD
+ bool " Enable head options (-c, -q, and -v)"
+ default n
+ depends on CONFIG_HEAD
+ help
+ This enables the head options (-c, -q, and -v).
+
+config CONFIG_HOSTID
+ bool "hostid"
+ default n
+ help
+ hostid prints the numeric identifier (in hexadecimal) for
+ the current host.
+
+config CONFIG_ID
+ bool "id"
+ default n
+ help
+ id displays the current user and group ID names.
+
+config CONFIG_LENGTH
+ bool "length"
+ default n
+ help
+ length is used to print out the length of a specified string.
+
+config CONFIG_LN
+ bool "ln"
+ default n
+ help
+ ln is used to create hard or soft links between files.
+
+config CONFIG_LOGNAME
+ bool "logname"
+ default n
+ help
+ logname is used to print the current user's login name.
+
+config CONFIG_LS
+ bool "ls"
+ default n
+ help
+ ls is used to list the contents of directories.
+
+config CONFIG_FEATURE_LS_FILETYPES
+ bool " Enable filetyping options (-p and -F)"
+ default y
+ depends on CONFIG_LS
+ help
+ Enable the ls options (-p and -F).
+
+config CONFIG_FEATURE_LS_FOLLOWLINKS
+ bool " Enable symlinks dereferencing (-L)"
+ default y
+ depends on CONFIG_LS
+ help
+ Enable the ls option (-L).
+
+config CONFIG_FEATURE_LS_RECURSIVE
+ bool " Enable recursion (-R)"
+ default y
+ depends on CONFIG_LS
+ help
+ Enable the ls option (-R).
+
+config CONFIG_FEATURE_LS_SORTFILES
+ bool " Sort the file names"
+ default y
+ depends on CONFIG_LS
+ help
+ Allow ls to sort file names alphabetically.
+
+config CONFIG_FEATURE_LS_TIMESTAMPS
+ bool " Show file timestamps"
+ default y
+ depends on CONFIG_LS
+ help
+ Allow ls to display timestamps for files.
+
+config CONFIG_FEATURE_LS_USERNAME
+ bool " Show username/groupnames"
+ default y
+ depends on CONFIG_LS
+ help
+ Allow ls to display username/groupname for files.
+
+config CONFIG_FEATURE_LS_COLOR
+ bool " Use color to identify file types"
+ default y
+ depends on CONFIG_LS
+ help
+ Allow ls to use color when displaying files.
+
+config CONFIG_MD5SUM
+ bool "md5sum"
+ default n
+ help
+ md5sum is used to print or check MD5 checksums.
+
+config CONFIG_MKDIR
+ bool "mkdir"
+ default n
+ help
+ mkdir is used to create directories with the specified names.
+
+config CONFIG_MKFIFO
+ bool "mkfifo"
+ default n
+ help
+ mkfifo is used to create FIFOs (named pipes).
+ The `mknod' program can also create FIFOs.
+
+config CONFIG_MKNOD
+ bool "mknod"
+ default n
+ help
+ mknod is used to create FIFOs or block/character special
+ files with the specified names.
+
+config CONFIG_MV
+ bool "mv"
+ default n
+ help
+ mv is used to move or rename files or directories.
+
+config CONFIG_OD
+ bool "od"
+ default n
+ help
+ od is used to dump binary files in octal and other formats.
+
+config CONFIG_PRINTF
+ bool "printf"
+ default n
+ help
+ printf is used to format and print specified strings.
+ It's similar to `echo' except it has more options.
+
+config CONFIG_PWD
+ bool "pwd"
+ default n
+ help
+ pwd is used to print the current directory.
+
+config CONFIG_REALPATH
+ bool "realpath"
+ default n
+ help
+ Return the canonicalized absolute pathname.
+ This isnt provided by GNU shellutils, but where else does it belong.
+
+config CONFIG_RM
+ bool "rm"
+ default n
+ help
+ rm is used to remove files or directories.
+
+config CONFIG_RMDIR
+ bool "rmdir"
+ default n
+ help
+ rmdir is used to remove empty directories.
+
+config CONFIG_SHA1SUM
+ bool "sha1sum"
+ default n
+ help
+ Compute and check SHA1 message digest
+
+config CONFIG_FEATURE_SHA1SUM_CHECK
+ bool " Enale -c and -w options"
+ default n
+ help
+ Enabling the -c and -w options allow files to be checked
+ against pre-calculated hash values.
+
+config CONFIG_SLEEP
+ bool "sleep (single integer arg with no suffix)"
+ default n
+ help
+ sleep is used to pause for a specified number of seconds,
+
+config CONFIG_FEATURE_FANCY_SLEEP
+ bool " Enable multiple integer args and optional time suffixes"
+ default n
+ depends on CONFIG_SLEEP
+ help
+ Allow sleep to pause for specified minutes, hours, and days.
+
+config CONFIG_SORT
+ bool "sort"
+ default n
+ help
+ sort is used to sort lines of text in specified files.
+
+config CONFIG_FEATURE_SORT_REVERSE
+ bool " Enable reverse sort"
+ default y
+ depends on CONFIG_SORT
+ help
+ Enable the `-r' option that allows sort to sort lines of
+ text in reverse.
+
+config CONFIG_FEATURE_SORT_UNIQUE
+ bool " Enable unique sort"
+ default y
+ depends on CONFIG_SORT
+ help
+ Enable the `-u' option that allows sort to only sort lines
+ that are uniq.
+
+config CONFIG_STTY
+ bool "stty"
+ default n
+ help
+ stty is used to change and print terminal line settings.
+
+config CONFIG_SYNC
+ bool "sync"
+ default n
+ help
+ sync is used to flush filesystem buffers.
+
+config CONFIG_TAIL
+ bool "tail"
+ default n
+ help
+ tail is used to print the last specified number of lines
+ from files.
+
+config CONFIG_FEATURE_FANCY_TAIL
+ bool " Enable extra tail options (-c, -q, -s, and -v)"
+ default y
+ depends on CONFIG_TAIL
+ help
+ Enable tail options (-c, -q, -s, and -v).
+
+config CONFIG_TEE
+ bool "tee"
+ default n
+ help
+ tee is used to read from standard input and write
+ to standard output and files.
+
+config CONFIG_FEATURE_TEE_USE_BLOCK_IO
+ bool " Enable block i/o (larger/faster) instead of byte i/o."
+ default n
+ depends on CONFIG_TEE
+ help
+ Enable this option for a faster tee, at expense of size.
+
+if CONFIG_ASH || CONFIG_HUSH || CONFIG_LASH || CONFIG_MSH
+ config CONFIG_TEST
+ default y
+ comment "test (forced enabled for use with shell)"
+endif
+
+if !CONFIG_ASH && !CONFIG_HUSH && !CONFIG_LASH && !CONFIG_MSH
+ config CONFIG_TEST
+ bool "test"
+ default n
+ help
+ test is used to check file types and compare values,
+ returning an appropriate exit code. The shells (ash
+ and bash have test builtin).
+endif
+
+config CONFIG_TOUCH
+ bool "touch"
+ default n
+ help
+ touch is used to create or change the access and/or
+ modification timestamp of specified files.
+
+config CONFIG_TR
+ bool "tr"
+ default n
+ help
+ tr is used to squeeze, and/or delete characters from standard
+ input, writing to standard output.
+
+if CONFIG_HUSH || CONFIG_LASH || CONFIG_MSH
+ config CONFIG_TRUE
+ default y
+ comment "true (forced enabled for use with shell)"
+endif
+
+if !CONFIG_HUSH && !CONFIG_LASH && !CONFIG_MSH
+ config CONFIG_TRUE
+ bool "true"
+ default n
+ help
+ true returns an exit code of TRUE (0).
+
+endif
+
+config CONFIG_TTY
+ bool "tty"
+ default n
+ help
+ tty is used to print the name of the current terminal to
+ standard output.
+
+config CONFIG_UNAME
+ bool "uname"
+ default n
+ help
+ uname is used to print system information.
+
+config CONFIG_UNIQ
+ bool "uniq"
+ default n
+ help
+ uniq is used to remove duplicate lines from a sorted file.
+
+config CONFIG_USLEEP
+ bool "usleep"
+ default n
+ help
+ usleep is used to pause for a specified number of microseconds.
+
+config CONFIG_UUDECODE
+ bool "uudecode"
+ default n
+ help
+ uudecode is used to decode a uuencoded file.
+
+config CONFIG_UUENCODE
+ bool "uuencode"
+ default n
+ help
+ uuencode is used to uuencode a file.
+
+config CONFIG_WATCH
+ bool "watch"
+ default n
+ help
+ watch is used to execute a program periodically, showing
+ output to the screen.
+
+config CONFIG_WC
+ bool "wc"
+ default n
+ help
+ wc is used to print the number of bytes, words, and lines,
+ in specified files.
+
+config CONFIG_WHO
+ bool "who"
+ default n
+ help
+ who is used to show who is logged on.
+
+config CONFIG_WHOAMI
+ bool "whoami"
+ default n
+ help
+ whoami is used to print the username of the current
+ user id (same as id -un).
+
+config CONFIG_YES
+ bool "yes"
+ default n
+ help
+ yes is used to repeatedly output a specific string, or
+ the default string `y'.
+
+comment "Common options for cp and mv"
+ depends on CONFIG_CP || CONFIG_MV
+
+config CONFIG_FEATURE_PRESERVE_HARDLINKS
+ bool " Preserve hard links"
+ default n
+ depends on CONFIG_CP || CONFIG_MV
+ help
+ Allow cp and mv to preserve hard links.
+
+comment "Common options for ls and more"
+ depends on CONFIG_LS || CONFIG_MORE
+
+config CONFIG_FEATURE_AUTOWIDTH
+ bool " Calculate terminal & column widths"
+ default y
+ depends on CONFIG_LS || CONFIG_MORE
+ help
+ This option allows utilities such as 'ls' and 'more' to determine the
+ width of the screen, which can allow them to display additional text
+ or avoid wrapping text onto the next line. If you leave this
+ disabled, your utilities will be especially primitive and will be
+ unable to determine the current screen width.
+
+comment "Common options for df, du, ls"
+ depends on CONFIG_DF || CONFIG_DU || CONFIG_LS
+
+config CONFIG_FEATURE_HUMAN_READABLE
+ bool " Support for human readable output (example 13k, 23M, 235G)"
+ default n
+ depends on CONFIG_DF || CONFIG_DU || CONFIG_LS
+ help
+ Allow df, du, and ls to have human readable output.
+
+endmenu
diff --git a/release/src/router/busybox/coreutils/Makefile b/release/src/router/busybox/coreutils/Makefile
new file mode 100644
index 00000000..a5cdf624
--- /dev/null
+++ b/release/src/router/busybox/coreutils/Makefile
@@ -0,0 +1,30 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+TOPDIR:= ../
+SHELLUTILS_DIR:=./
+include $(TOPDIR).config
+include $(TOPDIR)Rules.mak
+include Makefile.in
+all: $(libraries-y)
+-include $(TOPDIR).depend
+
+clean:
+ rm -f *.o *.a $(AR_TARGET)
+
diff --git a/release/src/router/busybox/coreutils/Makefile.in b/release/src/router/busybox/coreutils/Makefile.in
new file mode 100755
index 00000000..95eda1ac
--- /dev/null
+++ b/release/src/router/busybox/coreutils/Makefile.in
@@ -0,0 +1,92 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+COREUTILS_AR:=coreutils.a
+ifndef $(COREUTILS_DIR)
+COREUTILS_DIR:=$(TOPDIR)coreutils/
+endif
+
+COREUTILS-y:=
+COREUTILS-$(CONFIG_BASENAME) += basename.o
+COREUTILS-$(CONFIG_CAL) += cal.o
+COREUTILS-$(CONFIG_CAT) += cat.o
+COREUTILS-$(CONFIG_CHGRP) += chgrp.o
+COREUTILS-$(CONFIG_CHMOD) += chmod.o
+COREUTILS-$(CONFIG_CHOWN) += chown.o
+COREUTILS-$(CONFIG_CHROOT) += chroot.o
+COREUTILS-$(CONFIG_CMP) += cmp.o
+COREUTILS-$(CONFIG_CP) += cp.o
+COREUTILS-$(CONFIG_CUT) += cut.o
+COREUTILS-$(CONFIG_DATE) += date.o
+COREUTILS-$(CONFIG_DD) += dd.o
+COREUTILS-$(CONFIG_DF) += df.o
+COREUTILS-$(CONFIG_DIRNAME) += dirname.o
+COREUTILS-$(CONFIG_DOS2UNIX) += dos2unix.o
+COREUTILS-$(CONFIG_DU) += du.o
+COREUTILS-$(CONFIG_ECHO) += echo.o
+COREUTILS-$(CONFIG_ENV) += env.o
+COREUTILS-$(CONFIG_EXPR) += expr.o
+COREUTILS-$(CONFIG_FALSE) += false.o
+COREUTILS-$(CONFIG_FOLD) += fold.o
+COREUTILS-$(CONFIG_HEAD) += head.o
+COREUTILS-$(CONFIG_HOSTID) += hostid.o
+COREUTILS-$(CONFIG_ID) += id.o
+COREUTILS-$(CONFIG_LENGTH) += length.o
+COREUTILS-$(CONFIG_LN) += ln.o
+COREUTILS-$(CONFIG_LOGNAME) += logname.o
+COREUTILS-$(CONFIG_LS) += ls.o
+COREUTILS-$(CONFIG_MD5SUM) += md5sum.o
+COREUTILS-$(CONFIG_MKDIR) += mkdir.o
+COREUTILS-$(CONFIG_MKFIFO) += mkfifo.o
+COREUTILS-$(CONFIG_MKNOD) += mknod.o
+COREUTILS-$(CONFIG_MV) += mv.o
+COREUTILS-$(CONFIG_OD) += od.o
+COREUTILS-$(CONFIG_PRINTF) += printf.o
+COREUTILS-$(CONFIG_PWD) += pwd.o
+COREUTILS-$(CONFIG_REALPATH) += realpath.o
+COREUTILS-$(CONFIG_RM) += rm.o
+COREUTILS-$(CONFIG_RMDIR) += rmdir.o
+COREUTILS-$(CONFIG_SHA1SUM) += sha1sum.o
+COREUTILS-$(CONFIG_SLEEP) += sleep.o
+COREUTILS-$(CONFIG_SORT) += sort.o
+COREUTILS-$(CONFIG_STTY) += stty.o
+COREUTILS-$(CONFIG_SYNC) += sync.o
+COREUTILS-$(CONFIG_TAIL) += tail.o
+COREUTILS-$(CONFIG_TEE) += tee.o
+COREUTILS-$(CONFIG_TEST) += test.o
+COREUTILS-$(CONFIG_TOUCH) += touch.o
+COREUTILS-$(CONFIG_TR) += tr.o
+COREUTILS-$(CONFIG_TRUE) += true.o
+COREUTILS-$(CONFIG_TTY) += tty.o
+COREUTILS-$(CONFIG_UNAME) += uname.o
+COREUTILS-$(CONFIG_UNIQ) += uniq.o
+COREUTILS-$(CONFIG_USLEEP) += usleep.o
+COREUTILS-$(CONFIG_UUDECODE) += uudecode.o
+COREUTILS-$(CONFIG_UUENCODE) += uuencode.o
+COREUTILS-$(CONFIG_WATCH) += watch.o
+COREUTILS-$(CONFIG_WC) += wc.o
+COREUTILS-$(CONFIG_WHO) += who.o
+COREUTILS-$(CONFIG_WHOAMI) += whoami.o
+COREUTILS-$(CONFIG_YES) += yes.o
+
+libraries-y+=$(COREUTILS_DIR)$(COREUTILS_AR)
+
+$(COREUTILS_DIR)$(COREUTILS_AR): $(patsubst %,$(COREUTILS_DIR)%, $(COREUTILS-y))
+ $(AR) -ro $@ $(patsubst %,$(COREUTILS_DIR)%, $(COREUTILS-y))
+
diff --git a/release/src/router/busybox/coreutils/basename.c b/release/src/router/busybox/coreutils/basename.c
new file mode 100644
index 00000000..7fcdb836
--- /dev/null
+++ b/release/src/router/busybox/coreutils/basename.c
@@ -0,0 +1,62 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini basename implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */
+
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Changes:
+ * 1) Now checks for too many args. Need at least one and at most two.
+ * 2) Don't check for options, as per SUSv3.
+ * 3) Save some space by using strcmp(). Calling strncmp() here was silly.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "busybox.h"
+
+extern int basename_main(int argc, char **argv)
+{
+ size_t m, n;
+ char *s;
+
+ if (((unsigned int)(argc-2)) >= 2) {
+ bb_show_usage();
+ }
+
+ s = bb_get_last_path_component(*++argv);
+
+ if (*++argv) {
+ n = strlen(*argv);
+ m = strlen(s);
+ if ((m > n) && ((strcmp)(s+m-n, *argv) == 0)) {
+ s[m-n] = '\0';
+ }
+ }
+
+ puts(s);
+
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}
diff --git a/release/src/router/busybox/coreutils/cal.c b/release/src/router/busybox/coreutils/cal.c
new file mode 100644
index 00000000..ed480dd7
--- /dev/null
+++ b/release/src/router/busybox/coreutils/cal.c
@@ -0,0 +1,392 @@
+/* NOTE:
+ *
+ * Apparently, all "Steven J. Merrifield" did was grab the util-linux cal applet,
+ * spend maybe 5 minutes integrating it into busybox, slapped a copyright on it,
+ * and submitted it. I certainly saw no evidence of any attempt at size reduction.
+ * Not only do I consider his copyright below meaningless, I also consider his
+ * actions shameful.
+ *
+ * Manuel Novoa III (mjn3@codepoet.org)
+ */
+
+/*
+ * Calendar implementation for busybox
+ *
+ * Copyright (C) 2001 by Steven J. Merrifield <steve@labyrinth.net.au>
+ *
+ * See original copyright at the end of this file
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/* BB_AUDIT SUSv3 compliant with -j and -y extensions (from util-linux). */
+/* BB_AUDIT BUG: The output of 'cal -j 1752' is incorrect. The upstream
+ * BB_AUDIT BUG: version in util-linux seems to be broken as well. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cal.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Major size reduction... over 50% (>1.5k) on i386.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "busybox.h"
+
+#ifdef CONFIG_LOCALE_SUPPORT
+#include <locale.h>
+#endif
+
+#define THURSDAY 4 /* for reformation */
+#define SATURDAY 6 /* 1 Jan 1 was a Saturday */
+
+#define FIRST_MISSING_DAY 639787 /* 3 Sep 1752 */
+#define NUMBER_MISSING_DAYS 11 /* 11 day correction */
+
+#define MAXDAYS 42 /* max slots in a month array */
+#define SPACE -1 /* used in day array */
+
+static const char days_in_month[] = {
+ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static const char sep1752[] = {
+ 1, 2, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30
+};
+
+static int julian;
+
+/* leap year -- account for gregorian reformation in 1752 */
+#define leap_year(yr) \
+ ((yr) <= 1752 ? !((yr) % 4) : \
+ (!((yr) % 4) && ((yr) % 100)) || !((yr) % 400))
+
+static int is_leap_year(int year)
+{
+ return leap_year(year);
+}
+#undef leap_year
+#define leap_year(yr) is_leap_year(yr)
+
+/* number of centuries since 1700, not inclusive */
+#define centuries_since_1700(yr) \
+ ((yr) > 1700 ? (yr) / 100 - 17 : 0)
+
+/* number of centuries since 1700 whose modulo of 400 is 0 */
+#define quad_centuries_since_1700(yr) \
+ ((yr) > 1600 ? ((yr) - 1600) / 400 : 0)
+
+/* number of leap years between year 1 and this year, not inclusive */
+#define leap_years_since_year_1(yr) \
+ ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))
+
+static void center __P((char *, int, int));
+static void day_array __P((int, int, int *));
+static void trim_trailing_spaces_and_print __P((char *));
+
+static void blank_string(char *buf, size_t buflen);
+static char *build_row(char *p, int *dp);
+
+#define DAY_LEN 3 /* 3 spaces per day */
+#define J_DAY_LEN (DAY_LEN + 1)
+#define WEEK_LEN 20 /* 7 * 3 - one space at the end */
+#define J_WEEK_LEN (WEEK_LEN + 7)
+#define HEAD_SEP 2 /* spaces between day headings */
+
+int cal_main(int argc, char **argv)
+{
+ struct tm *local_time;
+ struct tm zero_tm;
+ time_t now;
+ int month, year, flags, i;
+ char *month_names[12];
+ char day_headings[28]; /* 28 for julian, 21 for nonjulian */
+ char buf[40];
+
+#ifdef CONFIG_LOCALE_SUPPORT
+ setlocale(LC_TIME, "");
+#endif
+
+ flags = bb_getopt_ulflags(argc, argv, "jy");
+
+ julian = flags & 1;
+
+ argv += optind;
+
+ month = 0;
+
+ if ((argc -= optind) > 2) {
+ bb_show_usage();
+ }
+
+ if (!argc) {
+ time(&now);
+ local_time = localtime(&now);
+ year = local_time->tm_year + 1900;
+ if (!(flags & 2)) {
+ month = local_time->tm_mon + 1;
+ }
+ } else {
+ if (argc == 2) {
+ month = bb_xgetularg10_bnd(*argv++, 1, 12);
+ }
+ year = bb_xgetularg10_bnd(*argv, 1, 9999);
+ }
+
+ blank_string(day_headings, sizeof(day_headings) - 7 + 7*julian);
+
+ i = 0;
+ do {
+ zero_tm.tm_mon = i;
+ strftime(buf, sizeof(buf), "%B", &zero_tm);
+ month_names[i] = bb_xstrdup(buf);
+
+ if (i < 7) {
+ zero_tm.tm_wday = i;
+ strftime(buf, sizeof(buf), "%a", &zero_tm);
+ strncpy(day_headings + i * (3+julian) + julian, buf, 2);
+ }
+ } while (++i < 12);
+
+ if (month) {
+ int row, len, days[MAXDAYS];
+ int *dp = days;
+ char lineout[30];
+
+ day_array(month, year, dp);
+ len = sprintf(lineout, "%s %d", month_names[month - 1], year);
+ bb_printf("%*s%s\n%s\n",
+ ((7*julian + WEEK_LEN) - len) / 2, "",
+ lineout, day_headings);
+ for (row = 0; row < 6; row++) {
+ build_row(lineout, dp)[0] = '\0';
+ dp += 7;
+ trim_trailing_spaces_and_print(lineout);
+ }
+ } else {
+ int row, which_cal, week_len, days[12][MAXDAYS];
+ int *dp;
+ char lineout[80];
+
+ sprintf(lineout, "%d", year);
+ center(lineout,
+ (WEEK_LEN * 3 + HEAD_SEP * 2)
+ + julian * (J_WEEK_LEN * 2 + HEAD_SEP
+ - (WEEK_LEN * 3 + HEAD_SEP * 2)),
+ 0);
+ puts("\n"); /* two \n's */
+ for (i = 0; i < 12; i++) {
+ day_array(i + 1, year, days[i]);
+ }
+ blank_string(lineout, sizeof(lineout));
+ week_len = WEEK_LEN + julian * (J_WEEK_LEN - WEEK_LEN);
+ for (month = 0; month < 12; month += 3-julian) {
+ center(month_names[month], week_len, HEAD_SEP);
+ if (!julian) {
+ center(month_names[month + 1], week_len, HEAD_SEP);
+ }
+ center(month_names[month + 2 - julian], week_len, 0);
+ bb_printf("\n%s%*s%s", day_headings, HEAD_SEP, "", day_headings);
+ if (!julian) {
+ bb_printf("%*s%s", HEAD_SEP, "", day_headings);
+ }
+ putchar('\n');
+ for (row = 0; row < (6*7); row += 7) {
+ for (which_cal = 0; which_cal < 3-julian; which_cal++) {
+ dp = days[month + which_cal] + row;
+ build_row(lineout + which_cal * (week_len + 2), dp);
+ }
+ /* blank_string took care of nul termination. */
+ trim_trailing_spaces_and_print(lineout);
+ }
+ }
+ }
+
+ bb_fflush_stdout_and_exit(0);
+}
+
+/*
+ * day_array --
+ * Fill in an array of 42 integers with a calendar. Assume for a moment
+ * that you took the (maximum) 6 rows in a calendar and stretched them
+ * out end to end. You would have 42 numbers or spaces. This routine
+ * builds that array for any month from Jan. 1 through Dec. 9999.
+ */
+static void day_array(int month, int year, int *days)
+{
+ long temp;
+ int i;
+ int j_offset;
+ int day, dw, dm;
+
+ memset(days, SPACE, MAXDAYS * sizeof(int));
+
+ if ((month == 9) && (year == 1752)) {
+ j_offset = julian * 244;
+ i = 0;
+ do {
+ days[i+2] = sep1752[i] + j_offset;
+ } while (++i < sizeof(sep1752));
+
+ return;
+ }
+
+ /* day_in_year
+ * return the 1 based day number within the year
+ */
+ day = 1;
+ if ((month > 2) && leap_year(year)) {
+ ++day;
+ }
+
+ i = month;
+ while (i) {
+ day += days_in_month[--i];
+ }
+
+ /* day_in_week
+ * return the 0 based day number for any date from 1 Jan. 1 to
+ * 31 Dec. 9999. Assumes the Gregorian reformation eliminates
+ * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all
+ * missing days.
+ */
+ dw = THURSDAY;
+ temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
+ + day;
+ if (temp < FIRST_MISSING_DAY) {
+ dw = ((temp - 1 + SATURDAY) % 7);
+ } else if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) {
+ dw = (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
+ }
+
+ if (!julian) {
+ day = 1;
+ }
+
+ dm = days_in_month[month];
+ if ((month == 2) && leap_year(year)) {
+ ++dm;
+ }
+
+ while (dm) {
+ days[dw++] = day++;
+ --dm;
+ }
+}
+
+static void trim_trailing_spaces_and_print(char *s)
+{
+ char *p = s;
+
+ while (*p) {
+ ++p;
+ }
+ while (p > s) {
+ --p;
+ if (!(isspace)(*p)) { /* We want the function... not the inline. */
+ p[1] = '\0';
+ break;
+ }
+ }
+
+ puts(s);
+}
+
+static void center(char *str, int len, int separate)
+{
+ int n = strlen(str);
+ len -= n;
+ bb_printf("%*s%*s", (len/2) + n, str, (len/2) + (len % 2) + separate, "");
+}
+
+static void blank_string(char *buf, size_t buflen)
+{
+ memset(buf, ' ', buflen);
+ buf[buflen-1] = '\0';
+}
+
+static char *build_row(char *p, int *dp)
+{
+ int col, val, day;
+
+ memset(p, ' ', (julian + DAY_LEN) * 7);
+
+ col = 0;
+ do {
+ if ((day = *dp++) != SPACE) {
+ if (julian) {
+ *++p;
+ if (day >= 100) {
+ *p = '0';
+ p[-1] = (day / 100) + '0';
+ day %= 100;
+ }
+ }
+ if ((val = day / 10) > 0) {
+ *p = val + '0';
+ }
+ *++p = day % 10 + '0';
+ p += 2;
+ } else {
+ p += DAY_LEN + julian;
+ }
+ } while (++col < 7);
+
+ return p;
+}
+
+/*
+ * 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
+ * Kim Letkeman.
+ *
+ * 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.
+ */
+
+
diff --git a/release/src/router/busybox/coreutils/cat.c b/release/src/router/busybox/coreutils/cat.c
new file mode 100644
index 00000000..86527576
--- /dev/null
+++ b/release/src/router/busybox/coreutils/cat.c
@@ -0,0 +1,67 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * cat implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * This is a new implementation of 'cat' which aims to be SUSv3 compliant.
+ *
+ * Changes from the previous implementation include:
+ * 1) Multiple '-' args are accepted as required by SUSv3. The previous
+ * implementation would close stdin and segfault on a subsequent '-'.
+ * 2) The '-u' options is required by SUSv3. Note that the specified
+ * behavior for '-u' is done by default, so all we need do is accept
+ * the option.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "busybox.h"
+
+extern int cat_main(int argc, char **argv)
+{
+ FILE *f;
+ int retval = EXIT_SUCCESS;
+
+ bb_getopt_ulflags(argc, argv, "u");
+
+ argv += optind;
+ if (!*argv) {
+ *--argv = "-";
+ }
+
+ do {
+ if ((f = bb_wfopen_input(*argv)) != NULL) {
+ int r = bb_copyfd(fileno(f), STDOUT_FILENO, 0);
+ bb_fclose_nonstdin(f);
+ if (r >= 0) {
+ continue;
+ }
+ }
+ retval = EXIT_FAILURE;
+ } while (*++argv);
+
+ return retval;
+}
diff --git a/release/src/router/busybox/coreutils/chgrp.c b/release/src/router/busybox/coreutils/chgrp.c
new file mode 100644
index 00000000..2f3fa419
--- /dev/null
+++ b/release/src/router/busybox/coreutils/chgrp.c
@@ -0,0 +1,85 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chgrp implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */
+/* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */
+/* BB_AUDIT Note: gnu chgrp does not support -H, -L, or -P. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chgrp.html */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+/* Don't use lchown glibc older then 2.1.x */
+#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1)
+#define lchown chown
+#endif
+
+static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
+{
+ if (lchown(fileName, statbuf->st_uid, *((long *) junk)) == 0) {
+ return (TRUE);
+ }
+ bb_perror_msg("%s", fileName); /* Avoid multibyte problems. */
+ return (FALSE);
+}
+
+int chgrp_main(int argc, char **argv)
+{
+ long gid;
+ int recursiveFlag;
+ int retval = EXIT_SUCCESS;
+ char *p;
+
+ recursiveFlag = bb_getopt_ulflags(argc, argv, "R");
+
+ if (argc - optind < 2) {
+ bb_show_usage();
+ }
+
+ argv += optind;
+
+ /* Find the selected group */
+ gid = strtoul(*argv, &p, 10); /* maybe it's already numeric */
+ if (*p || (p == *argv)) { /* trailing chars or nonnumeric */
+ gid = my_getgrnam(*argv);
+ }
+ ++argv;
+
+ /* Ok, ready to do the deed now */
+ do {
+ if (! recursive_action (*argv, recursiveFlag, FALSE, FALSE,
+ fileAction, fileAction, &gid)) {
+ retval = EXIT_FAILURE;
+ }
+ } while (*++argv);
+
+ return retval;
+}
+
+/*
+Local Variables:
+c-file-style: "linux"
+c-basic-offset: 4
+tab-width: 4
+End:
+*/
diff --git a/release/src/router/busybox/coreutils/chmod.c b/release/src/router/busybox/coreutils/chmod.c
new file mode 100644
index 00000000..390cc6d2
--- /dev/null
+++ b/release/src/router/busybox/coreutils/chmod.c
@@ -0,0 +1,112 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chmod implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ *
+ * Reworked by (C) 2002 Vladimir Oleynik <dzo@simtreas.ru>
+ * to correctly parse '-rwxgoa'
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU defects - unsupported options -c, -f, -v, and long options. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "busybox.h"
+
+static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
+{
+ if (!bb_parse_mode((char *)junk, &(statbuf->st_mode)))
+ bb_error_msg_and_die( "invalid mode: %s", (char *)junk);
+ if (chmod(fileName, statbuf->st_mode) == 0)
+ return (TRUE);
+ bb_perror_msg("%s", fileName); /* Avoid multibyte problems. */
+ return (FALSE);
+}
+
+int chmod_main(int argc, char **argv)
+{
+ int retval = EXIT_SUCCESS;
+ int recursiveFlag = FALSE;
+ int count;
+ char *smode;
+ char **p;
+ char *p0;
+ char opt = '-';
+
+ ++argv;
+ count = 0;
+
+ for (p = argv ; *p ; p++) {
+ p0 = p[0];
+ if (p0[0] == opt) {
+ if ((p0[1] == '-') && !p0[2]) {
+ opt = 0; /* Disable further option processing. */
+ continue;
+ }
+ if (p0[1] == 'R') {
+ char *s = p0 + 2;
+ while (*s == 'R') {
+ ++s;
+ }
+ if (*s) {
+ bb_show_usage();
+ }
+ recursiveFlag = TRUE;
+ continue;
+ }
+ if (count) {
+ bb_show_usage();
+ }
+ }
+ argv[count] = p0;
+ ++count;
+ }
+
+ argv[count] = NULL;
+
+ if (count < 2) {
+ bb_show_usage();
+ }
+
+ smode = *argv;
+ ++argv;
+
+ /* Ok, ready to do the deed now */
+ do {
+ if (! recursive_action (*argv, recursiveFlag, FALSE, FALSE,
+ fileAction, fileAction, smode)) {
+ retval = EXIT_FAILURE;
+ }
+ } while (*++argv);
+
+ return retval;
+}
+
+/*
+Local Variables:
+c-file-style: "linux"
+c-basic-offset: 4
+tab-width: 4
+End:
+*/
diff --git a/release/src/router/busybox/coreutils/chown.c b/release/src/router/busybox/coreutils/chown.c
new file mode 100644
index 00000000..7b9ea917
--- /dev/null
+++ b/release/src/router/busybox/coreutils/chown.c
@@ -0,0 +1,117 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chown implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */
+/* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */
+/* BB_AUDIT Note: gnu chown does not support -H, -L, or -P. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "busybox.h"
+
+/* Don't use lchown for glibc older then 2.1.x */
+#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1)
+#define lchown chown
+#endif
+
+static long uid;
+static long gid;
+
+static int (*chown_func)(const char *, uid_t, gid_t) = chown;
+
+static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
+{
+ if (chown_func(fileName, uid, (gid == -1) ? statbuf->st_gid : gid) == 0) {
+ return (TRUE);
+ }
+ bb_perror_msg("%s", fileName); /* Avoid multibyte problems. */
+ return (FALSE);
+}
+
+#define FLAG_R 1
+#define FLAG_h 2
+
+static unsigned long get_ug_id(const char *s, long (*my_getxxnam)(const char *))
+{
+ unsigned long r;
+ char *p;
+
+ r = strtoul(s, &p, 10);
+ if (*p || (s == p)) {
+ r = my_getxxnam(s);
+ }
+
+ return r;
+}
+
+int chown_main(int argc, char **argv)
+{
+ int flags;
+ int retval = EXIT_SUCCESS;
+ char *groupName;
+
+ flags = bb_getopt_ulflags(argc, argv, "Rh");
+
+ if (flags & FLAG_h) chown_func = lchown;
+
+ if (argc - optind < 2) {
+ bb_show_usage();
+ }
+
+ argv += optind;
+
+ /* First, check if there is a group name here */
+ if ((groupName = strchr(*argv, '.')) == NULL) {
+ groupName = strchr(*argv, ':');
+ }
+
+ gid = -1;
+ if (groupName) {
+ *groupName++ = '\0';
+ gid = get_ug_id(groupName, my_getgrnam);
+ }
+
+ /* Now check for the username */
+ uid = get_ug_id(*argv, my_getpwnam);
+
+ ++argv;
+
+ /* Ok, ready to do the deed now */
+ do {
+ if (! recursive_action (*argv, (flags & FLAG_R), FALSE, FALSE,
+ fileAction, fileAction, NULL)) {
+ retval = EXIT_FAILURE;
+ }
+ } while (*++argv);
+
+ return retval;
+}
+
+/*
+Local Variables:
+c-file-style: "linux"
+c-basic-offset: 4
+tab-width: 4
+End:
+*/
diff --git a/release/src/router/busybox/coreutils/chroot.c b/release/src/router/busybox/coreutils/chroot.c
new file mode 100644
index 00000000..5562e58c
--- /dev/null
+++ b/release/src/router/busybox/coreutils/chroot.c
@@ -0,0 +1,53 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chroot implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include "busybox.h"
+
+int chroot_main(int argc, char **argv)
+{
+ if (argc < 2) {
+ bb_show_usage();
+ }
+
+ ++argv;
+ if (chroot(*argv) || (chdir("/"))) {
+ bb_perror_msg_and_die("cannot change root directory to %s", *argv);
+ }
+
+ ++argv;
+ if (argc == 2) {
+ argv -= 2;
+ if (!(*argv = getenv("SHELL"))) {
+ *argv = (char *) "/bin/sh";
+ }
+ argv[1] = (char *) "-i";
+ }
+
+ execvp(*argv, argv);
+ bb_perror_msg_and_die("cannot execute %s", *argv);
+}
diff --git a/release/src/router/busybox/coreutils/cmp.c b/release/src/router/busybox/coreutils/cmp.c
new file mode 100644
index 00000000..43dbc842
--- /dev/null
+++ b/release/src/router/busybox/coreutils/cmp.c
@@ -0,0 +1,152 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini cmp implementation for busybox
+ *
+ * Copyright (C) 2000,2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Original version majorly reworked for SUSv3 compliance, bug fixes, and
+ * size optimizations. Changes include:
+ * 1) Now correctly distingusishes between errors and actual file differences.
+ * 2) Proper handling of '-' args.
+ * 3) Actual error checking of i/o.
+ * 4) Accept SUSv3 -l option. Note that we use the slightly nicer gnu format
+ * in the '-l' case.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+static FILE *cmp_xfopen_input(const char *filename)
+{
+ FILE *fp;
+
+ if ((fp = bb_wfopen_input(filename)) != NULL) {
+ return fp;
+ }
+
+ exit(bb_default_error_retval); /* We already output an error message. */
+}
+
+static const char fmt_eof[] = "cmp: EOF on %s\n";
+static const char fmt_differ[] = "%s %s differ: char %d, line %d\n";
+#if 0
+static const char fmt_l_opt[] = "%.0s%.0s%d %o %o\n"; /* SUSv3 format */
+#else
+static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n"; /* nicer gnu format */
+#endif
+
+static const char opt_chars[] = "sl";
+
+enum {
+ OPT_s = 1,
+ OPT_l = 2
+};
+
+int cmp_main(int argc, char **argv)
+{
+ FILE *fp1, *fp2, *outfile = stdout;
+ const char *filename1, *filename2;
+ const char *fmt;
+ int c1, c2, char_pos, line_pos;
+ int opt_flags;
+ int exit_val = 0;
+
+ bb_default_error_retval = 2; /* 1 is returned if files are different. */
+
+ opt_flags = bb_getopt_ulflags(argc, argv, opt_chars);
+
+ if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > 1)) {
+ bb_show_usage();
+ }
+
+ fp1 = cmp_xfopen_input(filename1 = *(argv += optind));
+
+ filename2 = "-";
+ if (*++argv) {
+ filename2 = *argv;
+ }
+ fp2 = cmp_xfopen_input(filename2);
+
+ if (fp1 == fp2) { /* Paranioa check... stdin == stdin? */
+ /* Note that we don't bother reading stdin. Neither does gnu wc.
+ * But perhaps we should, so that other apps down the chain don't
+ * get the input. Consider 'echo hello | (cmp - - && cat -)'.
+ */
+ return 0;
+ }
+
+ fmt = fmt_differ;
+ if (opt_flags == OPT_l) {
+ fmt = fmt_l_opt;
+ }
+
+ char_pos = 0;
+ line_pos = 1;
+ do {
+ c1 = getc(fp1);
+ c2 = getc(fp2);
+ ++char_pos;
+ if (c1 != c2) { /* Remember -- a read error may have occurred. */
+ exit_val = 1; /* But assume the files are different for now. */
+ if (c2 == EOF) {
+ /* We know that fp1 isn't at EOF or in an error state. But to
+ * save space below, things are setup to expect an EOF in fp1
+ * if an EOF occurred. So, swap things around.
+ */
+ fp1 = fp2;
+ filename1 = filename2;
+ c1 = c2;
+ }
+ if (c1 == EOF) {
+ bb_xferror(fp1, filename1);
+ fmt = fmt_eof; /* Well, no error, so it must really be EOF. */
+ outfile = stderr;
+ /* There may have been output to stdout (option -l), so
+ * make sure we fflush before writing to stderr. */
+ bb_xfflush_stdout();
+ }
+ if (opt_flags != OPT_s) {
+ if (opt_flags == OPT_l) {
+ line_pos = c1; /* line_pos is unused in the -l case. */
+ }
+ bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2);
+ if (opt_flags) { /* This must be -l since not -s. */
+ /* If we encountered and EOF, the while check will catch it. */
+ continue;
+ }
+ }
+ break;
+ }
+ if (c1 == '\n') {
+ ++line_pos;
+ }
+ } while (c1 != EOF);
+
+ bb_xferror(fp1, filename1);
+ bb_xferror(fp2, filename2);
+
+ bb_fflush_stdout_and_exit(exit_val);
+}
diff --git a/release/src/router/busybox/coreutils/cp.c b/release/src/router/busybox/coreutils/cp.c
new file mode 100644
index 00000000..c5dd31ec
--- /dev/null
+++ b/release/src/router/busybox/coreutils/cp.c
@@ -0,0 +1,112 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini cp implementation for busybox
+ *
+ * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 defects - unsupported options -H, -L, and -P. */
+/* BB_AUDIT GNU defects - only extension options supported are -a and -d. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Size reduction.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utime.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+static const char cp_opts[] = "pdRfia"; /* WARNING!! ORDER IS IMPORTANT!! */
+
+extern int cp_main(int argc, char **argv)
+{
+ struct stat source_stat;
+ struct stat dest_stat;
+ const char *last;
+ const char *dest;
+ int s_flags;
+ int d_flags;
+ int flags;
+ int status = 0;
+
+ /* Since these are enums, #if tests will not work. So use assert()s. */
+ assert(FILEUTILS_PRESERVE_STATUS == 1);
+ assert(FILEUTILS_DEREFERENCE == 2);
+ assert(FILEUTILS_RECUR == 4);
+ assert(FILEUTILS_FORCE == 8);
+ assert(FILEUTILS_INTERACTIVE == 16);
+
+ flags = bb_getopt_ulflags(argc, argv, cp_opts);
+
+ if (flags & 32) {
+ flags |= (FILEUTILS_PRESERVE_STATUS | FILEUTILS_RECUR | FILEUTILS_DEREFERENCE);
+ }
+
+ flags ^= FILEUTILS_DEREFERENCE; /* The sense of this flag was reversed. */
+
+ if (optind + 2 > argc) {
+ bb_show_usage();
+ }
+
+ last = argv[argc - 1];
+ argv += optind;
+
+ /* If there are only two arguments and... */
+ if (optind + 2 == argc) {
+ s_flags = cp_mv_stat2(*argv, &source_stat,
+ (flags & FILEUTILS_DEREFERENCE) ? stat : lstat);
+ if ((s_flags < 0) || ((d_flags = cp_mv_stat(last, &dest_stat)) < 0)) {
+ exit(EXIT_FAILURE);
+ }
+ /* ...if neither is a directory or... */
+ if ( !((s_flags | d_flags) & 2) ||
+ /* ...recursing, the 1st is a directory, and the 2nd doesn't exist... */
+ /* ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags) */
+ /* Simplify the above since FILEUTILS_RECUR >> 1 == 2. */
+ ((((flags & FILEUTILS_RECUR) >> 1) & s_flags) && !d_flags)
+ ) {
+ /* ...do a simple copy. */
+ dest = last;
+ goto DO_COPY; /* Note: optind+2==argc implies argv[1]==last below. */
+ }
+ }
+
+ do {
+ dest = concat_path_file(last, bb_get_last_path_component(*argv));
+ DO_COPY:
+ if (copy_file(*argv, dest, flags) < 0) {
+ status = 1;
+ }
+ if (*++argv == last) {
+ break;
+ }
+ free((void *) dest);
+ } while (1);
+
+ exit(status);
+}
diff --git a/release/src/router/busybox/coreutils/cut.c b/release/src/router/busybox/coreutils/cut.c
new file mode 100644
index 00000000..34ec3690
--- /dev/null
+++ b/release/src/router/busybox/coreutils/cut.c
@@ -0,0 +1,344 @@
+/* vi: set sw=8 ts=8: */
+/*
+ * cut.c - minimalist version of cut
+ *
+ * Copyright (C) 1999,2000,2001 by Lineo, inc.
+ * Written by Mark Whitley <markw@lineo.com>, <markw@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include "busybox.h"
+
+
+/* option vars */
+static const char optstring[] = "b:c:f:d:sn";
+#define OPT_BYTE_FLGS 1
+#define OPT_CHAR_FLGS 2
+#define OPT_FIELDS_FLGS 4
+#define OPT_DELIM_FLGS 8
+#define OPT_SUPRESS_FLGS 16
+static char part; /* (b)yte, (c)har, (f)ields */
+static unsigned int supress_non_delimited_lines;
+static char delim = '\t'; /* delimiter, default is tab */
+
+struct cut_list {
+ int startpos;
+ int endpos;
+};
+
+static const int BOL = 0;
+static const int EOL = INT_MAX;
+static const int NON_RANGE = -1;
+
+static struct cut_list *cut_lists = NULL; /* growable array holding a series of lists */
+static unsigned int nlists = 0; /* number of elements in above list */
+
+
+static int cmpfunc(const void *a, const void *b)
+{
+ struct cut_list *la = (struct cut_list *)a;
+ struct cut_list *lb = (struct cut_list *)b;
+
+ if (la->startpos > lb->startpos)
+ return 1;
+ if (la->startpos < lb->startpos)
+ return -1;
+ return 0;
+}
+
+
+/*
+ * parse_lists() - parses a list and puts values into startpos and endpos.
+ * valid list formats: N, N-, N-M, -M
+ * more than one list can be seperated by commas
+ */
+static void parse_lists(char *lists)
+{
+ char *ltok = NULL;
+ char *ntok = NULL;
+ char *junk;
+ int s = 0, e = 0;
+
+ /* take apart the lists, one by one (they are seperated with commas */
+ while ((ltok = strsep(&lists, ",")) != NULL) {
+
+ /* it's actually legal to pass an empty list */
+ if (strlen(ltok) == 0)
+ continue;
+
+ /* get the start pos */
+ ntok = strsep(&ltok, "-");
+ if (ntok == NULL) {
+ fprintf(stderr, "Help ntok is null for starting position! What do I do?\n");
+ } else if (strlen(ntok) == 0) {
+ s = BOL;
+ } else {
+ s = strtoul(ntok, &junk, 10);
+ if(*junk != '\0' || s < 0)
+ bb_error_msg_and_die("invalid byte or field list");
+
+ /* account for the fact that arrays are zero based, while the user
+ * expects the first char on the line to be char # 1 */
+ if (s != 0)
+ s--;
+ }
+
+ /* get the end pos */
+ ntok = strsep(&ltok, "-");
+ if (ntok == NULL) {
+ e = NON_RANGE;
+ } else if (strlen(ntok) == 0) {
+ e = EOL;
+ } else {
+ e = strtoul(ntok, &junk, 10);
+ if(*junk != '\0' || e < 0)
+ bb_error_msg_and_die("invalid byte or field list");
+ /* if the user specified and end position of 0, that means "til the
+ * end of the line */
+ if (e == 0)
+ e = INT_MAX;
+ e--; /* again, arrays are zero based, lines are 1 based */
+ if (e == s)
+ e = NON_RANGE;
+ }
+
+ /* if there's something left to tokenize, the user past an invalid list */
+ if (ltok)
+ bb_error_msg_and_die("invalid byte or field list");
+
+ /* add the new list */
+ cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
+ cut_lists[nlists-1].startpos = s;
+ cut_lists[nlists-1].endpos = e;
+ }
+
+ /* make sure we got some cut positions out of all that */
+ if (nlists == 0)
+ bb_error_msg_and_die("missing list of positions");
+
+ /* now that the lists are parsed, we need to sort them to make life easier
+ * on us when it comes time to print the chars / fields / lines */
+ qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
+
+}
+
+
+static void cut_line_by_chars(const char *line)
+{
+ int c, l;
+ /* set up a list so we can keep track of what's been printed */
+ char *printed = xcalloc(strlen(line), sizeof(char));
+
+ /* print the chars specified in each cut list */
+ for (c = 0; c < nlists; c++) {
+ l = cut_lists[c].startpos;
+ while (l < strlen(line)) {
+ if (!printed[l]) {
+ putchar(line[l]);
+ printed[l] = 'X';
+ }
+ l++;
+ if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos)
+ break;
+ }
+ }
+ putchar('\n'); /* cuz we were handed a chomped line */
+ free(printed);
+}
+
+
+static void cut_line_by_fields(char *line)
+{
+ int c, f;
+ int ndelim = -1; /* zero-based / one-based problem */
+ int nfields_printed = 0;
+ char *field = NULL;
+ char d[2] = { delim, 0 };
+ char *printed;
+
+ /* test the easy case first: does this line contain any delimiters? */
+ if (strchr(line, delim) == NULL) {
+ if (!supress_non_delimited_lines)
+ puts(line);
+ return;
+ }
+
+ /* set up a list so we can keep track of what's been printed */
+ printed = xcalloc(strlen(line), sizeof(char));
+
+ /* process each list on this line, for as long as we've got a line to process */
+ for (c = 0; c < nlists && line; c++) {
+ f = cut_lists[c].startpos;
+ do {
+
+ /* find the field we're looking for */
+ while (line && ndelim < f) {
+ field = strsep(&line, d);
+ ndelim++;
+ }
+
+ /* we found it, and it hasn't been printed yet */
+ if (field && ndelim == f && !printed[ndelim]) {
+ /* if this isn't our first time through, we need to print the
+ * delimiter after the last field that was printed */
+ if (nfields_printed > 0)
+ putchar(delim);
+ fputs(field, stdout);
+ printed[ndelim] = 'X';
+ nfields_printed++;
+ }
+
+ f++;
+
+ /* keep going as long as we have a line to work with, this is a
+ * list, and we're not at the end of that list */
+ } while (line && cut_lists[c].endpos != NON_RANGE && f <= cut_lists[c].endpos);
+ }
+
+ /* if we printed anything at all, we need to finish it with a newline cuz
+ * we were handed a chomped line */
+ putchar('\n');
+
+ free(printed);
+}
+
+
+static void cut_file_by_lines(const char *line, unsigned int linenum)
+{
+ static int c = 0;
+ static int l = -1;
+
+ /* I can't initialize this above cuz the "initializer isn't
+ * constant" *sigh* */
+ if (l == -1)
+ l = cut_lists[c].startpos;
+
+ /* get out if we have no more lists to process or if the lines are lower
+ * than what we're interested in */
+ if (c >= nlists || linenum < l)
+ return;
+
+ /* if the line we're looking for is lower than the one we were passed, it
+ * means we displayed it already, so move on */
+ while (l < linenum) {
+ l++;
+ /* move on to the next list if we're at the end of this one */
+ if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos) {
+ c++;
+ /* get out if there's no more lists to process */
+ if (c >= nlists)
+ return;
+ l = cut_lists[c].startpos;
+ /* get out if the current line is lower than the one we just became
+ * interested in */
+ if (linenum < l)
+ return;
+ }
+ }
+
+ /* If we made it here, it means we've found the line we're looking for, so print it */
+ puts(line);
+}
+
+
+/*
+ * snippy-snip
+ */
+static void cut_file(FILE *file)
+{
+ char *line = NULL;
+ unsigned int linenum = 0; /* keep these zero-based to be consistent */
+
+ /* go through every line in the file */
+ while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
+
+ /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */
+ if ((part & (OPT_CHAR_FLGS | OPT_BYTE_FLGS)))
+ cut_line_by_chars(line);
+
+ /* cut based on fields */
+ else {
+ if (delim == '\n')
+ cut_file_by_lines(line, linenum);
+ else
+ cut_line_by_fields(line);
+ }
+
+ linenum++;
+ free(line);
+ }
+}
+
+
+extern int cut_main(int argc, char **argv)
+{
+ unsigned long opt;
+ char *sopt, *sdopt;
+
+ bb_opt_complementaly = "b~bcf:c~bcf:f~bcf";
+ opt = bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &sdopt);
+ part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS);
+ if(part == 0)
+ bb_error_msg_and_die("you must specify a list of bytes, characters, or fields");
+ if(opt & 0x80000000UL)
+ bb_error_msg_and_die("only one type of list may be specified");
+ parse_lists(sopt);
+ if((opt & (OPT_DELIM_FLGS))) {
+ if (strlen(sdopt) > 1) {
+ bb_error_msg_and_die("the delimiter must be a single character");
+ }
+ delim = sdopt[0];
+ }
+ supress_non_delimited_lines = opt & OPT_SUPRESS_FLGS;
+
+ /* non-field (char or byte) cutting has some special handling */
+ if (part != OPT_FIELDS_FLGS) {
+ if (supress_non_delimited_lines) {
+ bb_error_msg_and_die("suppressing non-delimited lines makes sense"
+ " only when operating on fields");
+ }
+ if (delim != '\t') {
+ bb_error_msg_and_die("a delimiter may be specified only when operating on fields");
+ }
+ }
+
+ /* argv[(optind)..(argc-1)] should be names of file to process. If no
+ * files were specified or '-' was specified, take input from stdin.
+ * Otherwise, we process all the files specified. */
+ if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) {
+ cut_file(stdin);
+ }
+ else {
+ int i;
+ FILE *file;
+ for (i = optind; i < argc; i++) {
+ file = bb_wfopen(argv[i], "r");
+ if(file) {
+ cut_file(file);
+ fclose(file);
+ }
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/coreutils/date.c b/release/src/router/busybox/coreutils/date.c
new file mode 100644
index 00000000..7d14ec32
--- /dev/null
+++ b/release/src/router/busybox/coreutils/date.c
@@ -0,0 +1,275 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini date implementation for busybox
+ *
+ * by Matthew Grant <grantma@anathoth.gen.nz>
+ *
+ * iso-format handling added by Robert Griebl <griebl@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include "busybox.h"
+
+
+/* This 'date' command supports only 2 time setting formats,
+ all the GNU strftime stuff (its in libc, lets use it),
+ setting time using UTC and displaying int, as well as
+ an RFC 822 complient date output for shell scripting
+ mail commands */
+
+/* Input parsing code is always bulky - used heavy duty libc stuff as
+ much as possible, missed out a lot of bounds checking */
+
+/* Default input handling to save suprising some people */
+
+static struct tm *date_conv_time(struct tm *tm_time, const char *t_string)
+{
+ int nr;
+
+ nr = sscanf(t_string, "%2d%2d%2d%2d%d", &(tm_time->tm_mon),
+ &(tm_time->tm_mday), &(tm_time->tm_hour), &(tm_time->tm_min),
+ &(tm_time->tm_year));
+
+ if (nr < 4 || nr > 5) {
+ bb_error_msg_and_die(bb_msg_invalid_date, t_string);
+ }
+
+ /* correct for century - minor Y2K problem here? */
+ if (tm_time->tm_year >= 1900) {
+ tm_time->tm_year -= 1900;
+ }
+ /* adjust date */
+ tm_time->tm_mon -= 1;
+
+ return (tm_time);
+
+}
+
+
+/* The new stuff for LRP */
+
+static struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string)
+{
+ struct tm t;
+
+ /* Parse input and assign appropriately to tm_time */
+
+ if (t =
+ *tm_time, sscanf(t_string, "%d:%d:%d", &t.tm_hour, &t.tm_min,
+ &t.tm_sec) == 3) {
+ /* no adjustments needed */
+ } else if (t =
+ *tm_time, sscanf(t_string, "%d:%d", &t.tm_hour,
+ &t.tm_min) == 2) {
+ /* no adjustments needed */
+ } else if (t =
+ *tm_time, sscanf(t_string, "%d.%d-%d:%d:%d", &t.tm_mon,
+ &t.tm_mday, &t.tm_hour, &t.tm_min,
+ &t.tm_sec) == 5) {
+ /* Adjust dates from 1-12 to 0-11 */
+ t.tm_mon -= 1;
+ } else if (t =
+ *tm_time, sscanf(t_string, "%d.%d-%d:%d", &t.tm_mon,
+ &t.tm_mday, &t.tm_hour, &t.tm_min) == 4) {
+ /* Adjust dates from 1-12 to 0-11 */
+ t.tm_mon -= 1;
+ } else if (t =
+ *tm_time, sscanf(t_string, "%d.%d.%d-%d:%d:%d", &t.tm_year,
+ &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min,
+ &t.tm_sec) == 6) {
+ t.tm_year -= 1900; /* Adjust years */
+ t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
+ } else if (t =
+ *tm_time, sscanf(t_string, "%d.%d.%d-%d:%d", &t.tm_year,
+ &t.tm_mon, &t.tm_mday, &t.tm_hour,
+ &t.tm_min) == 5) {
+ t.tm_year -= 1900; /* Adjust years */
+ t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */
+ } else {
+ bb_error_msg_and_die(bb_msg_invalid_date, t_string);
+ }
+ *tm_time = t;
+ return (tm_time);
+}
+
+
+int date_main(int argc, char **argv)
+{
+ char *date_str = NULL;
+ char *date_fmt = NULL;
+ char *t_buff;
+ int set_time;
+ int rfc822;
+ int utc;
+ int use_arg = 0;
+ time_t tm;
+ unsigned long opt;
+ struct tm tm_time;
+
+#ifdef CONFIG_FEATURE_DATE_ISOFMT
+ int ifmt = 0;
+ char *isofmt_arg;
+
+# define GETOPT_ISOFMT "I::"
+#else
+# define GETOPT_ISOFMT
+#endif
+ bb_opt_complementaly = "d~ds:s~ds";
+ opt = bb_getopt_ulflags(argc, argv, "Rs:ud:" GETOPT_ISOFMT,
+ &date_str, &date_str
+#ifdef CONFIG_FEATURE_DATE_ISOFMT
+ , &isofmt_arg
+#endif
+ );
+ rfc822 = opt & 1;
+ set_time = opt & 2;
+ utc = opt & 4;
+ if(utc) {
+ if (putenv("TZ=UTC0") != 0)
+ bb_error_msg_and_die(bb_msg_memory_exhausted);
+ }
+ use_arg = opt & 8;
+ if(opt & 0x80000000UL)
+ bb_show_usage();
+#ifdef CONFIG_FEATURE_DATE_ISOFMT
+ if(opt & 16) {
+ if (!isofmt_arg)
+ ifmt = 1;
+ else {
+ int ifmt_len = bb_strlen(isofmt_arg);
+
+ if ((ifmt_len <= 4)
+ && (strncmp(isofmt_arg, "date", ifmt_len) == 0)) {
+ ifmt = 1;
+ } else if ((ifmt_len <= 5)
+ && (strncmp(isofmt_arg, "hours", ifmt_len) == 0)) {
+ ifmt = 2;
+ } else if ((ifmt_len <= 7)
+ && (strncmp(isofmt_arg, "minutes", ifmt_len) == 0)) {
+ ifmt = 3;
+ } else if ((ifmt_len <= 7)
+ && (strncmp(isofmt_arg, "seconds", ifmt_len) == 0)) {
+ ifmt = 4;
+ }
+ }
+ if (!ifmt) {
+ bb_show_usage();
+ }
+ }
+#endif
+
+ if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) {
+ date_fmt = &argv[optind][1]; /* Skip over the '+' */
+ } else if (date_str == NULL) {
+ set_time = 1;
+ date_str = argv[optind];
+ }
+
+ /* Now we have parsed all the information except the date format
+ which depends on whether the clock is being set or read */
+
+ time(&tm);
+ memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
+ /* Zero out fields - take her back to midnight! */
+ if (date_str != NULL) {
+ tm_time.tm_sec = 0;
+ tm_time.tm_min = 0;
+ tm_time.tm_hour = 0;
+ }
+
+ /* Process any date input to UNIX time since 1 Jan 1970 */
+ if (date_str != NULL) {
+
+ if (strchr(date_str, ':') != NULL) {
+ date_conv_ftime(&tm_time, date_str);
+ } else {
+ date_conv_time(&tm_time, date_str);
+ }
+
+ /* Correct any day of week and day of year etc. fields */
+ tm_time.tm_isdst = -1; /* Be sure to recheck dst. */
+ tm = mktime(&tm_time);
+ if (tm < 0) {
+ bb_error_msg_and_die(bb_msg_invalid_date, date_str);
+ }
+ if (utc && (putenv("TZ=UTC0") != 0)) {
+ bb_error_msg_and_die(bb_msg_memory_exhausted);
+ }
+
+ /* if setting time, set it */
+ if (set_time && (stime(&tm) < 0)) {
+ bb_perror_msg("cannot set date");
+ }
+ }
+
+ /* Display output */
+
+ /* Deal with format string */
+ if (date_fmt == NULL) {
+#ifdef CONFIG_FEATURE_DATE_ISOFMT
+ switch (ifmt) {
+ case 4:
+ date_fmt = utc ? "%Y-%m-%dT%H:%M:%SZ" : "%Y-%m-%dT%H:%M:%S%z";
+ break;
+ case 3:
+ date_fmt = utc ? "%Y-%m-%dT%H:%MZ" : "%Y-%m-%dT%H:%M%z";
+ break;
+ case 2:
+ date_fmt = utc ? "%Y-%m-%dT%HZ" : "%Y-%m-%dT%H%z";
+ break;
+ case 1:
+ date_fmt = "%Y-%m-%d";
+ break;
+ case 0:
+ default:
+#endif
+ date_fmt =
+ (rfc822
+ ? (utc ? "%a, %e %b %Y %H:%M:%S GMT" :
+ "%a, %e %b %Y %H:%M:%S %z") : "%a %b %e %H:%M:%S %Z %Y");
+
+#ifdef CONFIG_FEATURE_DATE_ISOFMT
+ break;
+ }
+#endif
+ } else if (*date_fmt == '\0') {
+ /* Imitate what GNU 'date' does with NO format string! */
+ printf("\n");
+ return EXIT_SUCCESS;
+ }
+
+ /* Handle special conversions */
+
+ if (strncmp(date_fmt, "%f", 2) == 0) {
+ date_fmt = "%Y.%m.%d-%H:%M:%S";
+ }
+
+ /* Print OUTPUT (after ALL that!) */
+ t_buff = xmalloc(201);
+ strftime(t_buff, 200, date_fmt, &tm_time);
+ puts(t_buff);
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/coreutils/dd.c b/release/src/router/busybox/coreutils/dd.c
new file mode 100644
index 00000000..cd97b24e
--- /dev/null
+++ b/release/src/router/busybox/coreutils/dd.c
@@ -0,0 +1,203 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini dd implementation for busybox
+ *
+ *
+ * Copyright (C) 2000,2001 Matt Kraai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include "busybox.h"
+
+
+static const struct suffix_mult dd_suffixes[] = {
+ { "c", 1 },
+ { "w", 2 },
+ { "b", 512 },
+ { "kD", 1000 },
+ { "k", 1024 },
+ { "MD", 1000000 },
+ { "M", 1048576 },
+ { "GD", 1000000000 },
+ { "G", 1073741824 },
+ { NULL, 0 }
+};
+
+int dd_main(int argc, char **argv)
+{
+ size_t out_full = 0;
+ size_t out_part = 0;
+ size_t in_full = 0;
+ size_t in_part = 0;
+ size_t count = -1;
+ size_t bs = 512;
+ ssize_t n;
+ off_t seek = 0;
+ off_t skip = 0;
+ int sync_flag = FALSE;
+ int noerror = FALSE;
+ int trunc = TRUE;
+ int oflag;
+ int ifd;
+ int ofd;
+ int i;
+ const char *infile = NULL;
+ const char *outfile = NULL;
+ char *buf;
+
+ for (i = 1; i < argc; i++) {
+ if (strncmp("bs=", argv[i], 3) == 0)
+ bs = bb_xparse_number(argv[i]+3, dd_suffixes);
+ else if (strncmp("count=", argv[i], 6) == 0)
+ count = bb_xparse_number(argv[i]+6, dd_suffixes);
+ else if (strncmp("seek=", argv[i], 5) == 0)
+ seek = bb_xparse_number(argv[i]+5, dd_suffixes);
+ else if (strncmp("skip=", argv[i], 5) == 0)
+ skip = bb_xparse_number(argv[i]+5, dd_suffixes);
+ else if (strncmp("if=", argv[i], 3) == 0)
+ infile = argv[i]+3;
+ else if (strncmp("of=", argv[i], 3) == 0)
+ outfile = argv[i]+3;
+ else if (strncmp("conv=", argv[i], 5) == 0) {
+ buf = argv[i]+5;
+ while (1) {
+ if (strncmp("notrunc", buf, 7) == 0) {
+ trunc = FALSE;
+ buf += 7;
+ } else if (strncmp("sync", buf, 4) == 0) {
+ sync_flag = TRUE;
+ buf += 4;
+ } else if (strncmp("noerror", buf, 7) == 0) {
+ noerror = TRUE;
+ buf += 7;
+ } else {
+ bb_error_msg_and_die("invalid conversion `%s'", argv[i]+5);
+ }
+ if (buf[0] == '\0')
+ break;
+ if (buf[0] == ',')
+ buf++;
+ }
+ } else
+ bb_show_usage();
+ }
+
+ buf = xmalloc(bs);
+
+ if (infile != NULL) {
+ ifd = bb_xopen(infile, O_RDONLY);
+ } else {
+ ifd = STDIN_FILENO;
+ infile = bb_msg_standard_input;
+ }
+
+ if (outfile != NULL) {
+ oflag = O_WRONLY | O_CREAT;
+
+ if (!seek && trunc) {
+ oflag |= O_TRUNC;
+ }
+
+ if ((ofd = open(outfile, oflag, 0666)) < 0) {
+ bb_perror_msg_and_die("%s", outfile);
+ }
+
+ if (seek && trunc) {
+ if (ftruncate(ofd, seek * bs) < 0) {
+ struct stat st;
+
+ if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) ||
+ S_ISDIR (st.st_mode)) {
+ bb_perror_msg_and_die("%s", outfile);
+ }
+ }
+ }
+ } else {
+ ofd = STDOUT_FILENO;
+ outfile = bb_msg_standard_output;
+ }
+
+ if (skip) {
+ if (lseek(ifd, skip * bs, SEEK_CUR) < 0) {
+ bb_perror_msg_and_die("%s", infile);
+ }
+ }
+
+ if (seek) {
+ if (lseek(ofd, seek * bs, SEEK_CUR) < 0) {
+ bb_perror_msg_and_die("%s", outfile);
+ }
+ }
+
+ while (in_full + in_part != count) {
+ if (noerror) {
+ /* Pre-zero the buffer when doing the noerror thing */
+ memset(buf, '\0', bs);
+ }
+ n = safe_read(ifd, buf, bs);
+ if (n < 0) {
+ if (noerror) {
+ n = bs;
+ bb_perror_msg("%s", infile);
+ } else {
+ bb_perror_msg_and_die("%s", infile);
+ }
+ }
+ if (n == 0) {
+ break;
+ }
+ if (n == bs) {
+ in_full++;
+ } else {
+ in_part++;
+ }
+ if (sync_flag) {
+ memset(buf + n, '\0', bs - n);
+ n = bs;
+ }
+ n = bb_full_write(ofd, buf, n);
+ if (n < 0) {
+ bb_perror_msg_and_die("%s", outfile);
+ }
+ if (n == bs) {
+ out_full++;
+ } else {
+ out_part++;
+ }
+ }
+
+ if (close (ifd) < 0) {
+ bb_perror_msg_and_die("%s", infile);
+ }
+
+ if (close (ofd) < 0) {
+ bb_perror_msg_and_die("%s", outfile);
+ }
+
+ fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n",
+ (long)in_full, (long)in_part,
+ (long)out_full, (long)out_part);
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/coreutils/df.c b/release/src/router/busybox/coreutils/df.c
new file mode 100644
index 00000000..9c0d13f6
--- /dev/null
+++ b/release/src/router/busybox/coreutils/df.c
@@ -0,0 +1,170 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini df implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ * based on original code by (I think) Bruce Perens <bruce@pixar.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 _NOT_ compliant -- options -P and -t missing. Also blocksize. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/df.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Size reduction. Removed floating point dependency. Added error checking
+ * on output. Output stats on 0-sized filesystems if specificly listed on
+ * the command line. Properly round *-blocks, Used, and Available quantities.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <mntent.h>
+#include <sys/vfs.h>
+#include "busybox.h"
+
+#ifndef CONFIG_FEATURE_HUMAN_READABLE
+static long kscale(long b, long bs)
+{
+ return ( b * (long long) bs + KILOBYTE/2 ) / KILOBYTE;
+}
+#endif
+
+extern int df_main(int argc, char **argv)
+{
+ long blocks_used;
+ long blocks_percent_used;
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+ unsigned long df_disp_hr = KILOBYTE;
+#endif
+ int status = EXIT_SUCCESS;
+ unsigned long opt;
+ FILE *mount_table;
+ struct mntent *mount_entry;
+ struct statfs s;
+ static const char hdr_1k[] = "1k-blocks"; /* default display is kilobytes */
+ const char *disp_units_hdr = hdr_1k;
+
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+ bb_opt_complementaly = "h-km:k-hm:m-hk";
+ opt = bb_getopt_ulflags(argc, argv, "hmk");
+ if(opt & 1) {
+ df_disp_hr = 0;
+ disp_units_hdr = " Size";
+ }
+ if(opt & 2) {
+ df_disp_hr = MEGABYTE;
+ disp_units_hdr = "1M-blocks";
+ }
+#else
+ opt = bb_getopt_ulflags(argc, argv, "k");
+#endif
+
+ bb_printf("Filesystem%11s%-15sUsed Available Use%% Mounted on\n",
+ "", disp_units_hdr);
+
+ mount_table = NULL;
+ argv += optind;
+ if (optind >= argc) {
+ if (!(mount_table = setmntent(bb_path_mtab_file, "r"))) {
+ bb_perror_msg_and_die(bb_path_mtab_file);
+ }
+ }
+
+ do {
+ const char *device;
+ const char *mount_point;
+
+ if (mount_table) {
+ if (!(mount_entry = getmntent(mount_table))) {
+ endmntent(mount_table);
+ break;
+ }
+ } else {
+ if (!(mount_point = *argv++)) {
+ break;
+ }
+ if (!(mount_entry = find_mount_point(mount_point, bb_path_mtab_file))) {
+ bb_error_msg("%s: can't find mount point.", mount_point);
+ SET_ERROR:
+ status = EXIT_FAILURE;
+ continue;
+ }
+ }
+
+ device = mount_entry->mnt_fsname;
+ mount_point = mount_entry->mnt_dir;
+
+ if (statfs(mount_point, &s) != 0) {
+ bb_perror_msg("%s", mount_point);
+ goto SET_ERROR;
+ }
+
+ if ((s.f_blocks > 0) || !mount_table){
+ blocks_used = s.f_blocks - s.f_bfree;
+ blocks_percent_used = 0;
+ if (blocks_used + s.f_bavail) {
+ blocks_percent_used = (((long long) blocks_used) * 100
+ + (blocks_used + s.f_bavail)/2
+ ) / (blocks_used + s.f_bavail);
+ }
+
+ if (strcmp(device, "rootfs") == 0) {
+ continue;
+ } else if (strcmp(device, "/dev/root") == 0) {
+ /* Adjusts device to be the real root device,
+ * or leaves device alone if it can't find it */
+ if ((device = find_real_root_device_name(device)) == NULL) {
+ goto SET_ERROR;
+ }
+ }
+
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+ bb_printf("%-21s%9s ", device,
+ make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr));
+
+ bb_printf("%9s ",
+ make_human_readable_str( (s.f_blocks - s.f_bfree),
+ s.f_bsize, df_disp_hr));
+
+ bb_printf("%9s %3ld%% %s\n",
+ make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr),
+ blocks_percent_used, mount_point);
+#else
+ bb_printf("%-21s%9ld %9ld %9ld %3ld%% %s\n",
+ device,
+ kscale(s.f_blocks, s.f_bsize),
+ kscale(s.f_blocks-s.f_bfree, s.f_bsize),
+ kscale(s.f_bavail, s.f_bsize),
+ blocks_percent_used, mount_point);
+#endif
+ }
+
+ } while (1);
+
+ bb_fflush_stdout_and_exit(status);
+}
+
+/*
+Local Variables:
+c-file-style: "linux"
+c-basic-offset: 4
+tab-width: 4
+End:
+*/
diff --git a/release/src/router/busybox/coreutils/dirname.c b/release/src/router/busybox/coreutils/dirname.c
new file mode 100644
index 00000000..d0c42b60
--- /dev/null
+++ b/release/src/router/busybox/coreutils/dirname.c
@@ -0,0 +1,39 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini dirname implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/dirname.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+extern int dirname_main(int argc, char **argv)
+{
+ if (argc != 2) {
+ bb_show_usage();
+ }
+
+ puts(dirname(argv[1]));
+
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}
diff --git a/release/src/router/busybox/coreutils/dos2unix.c b/release/src/router/busybox/coreutils/dos2unix.c
new file mode 100644
index 00000000..c28e6a8b
--- /dev/null
+++ b/release/src/router/busybox/coreutils/dos2unix.c
@@ -0,0 +1,196 @@
+/*
+ * dos2unix for BusyBox
+ *
+ * dos2unix '\n' convertor 0.5.0
+ * based on Unix2Dos 0.9.0 by Peter Hanecak (made 19.2.1997)
+ * Copyright 1997,.. by Peter Hanecak <hanecak@megaloman.sk>.
+ * All rights reserved.
+ *
+ * dos2unix filters reading input from stdin and writing output to stdout.
+ * Without arguments it reverts the format (e.i. if source is in UNIX format,
+ * output is in DOS format and vice versa).
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * See the COPYING file for license information.
+ */
+
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include "busybox.h"
+
+#define CT_AUTO 0
+#define CT_UNIX2DOS 1
+#define CT_DOS2UNIX 2
+
+/* We are making a lame pseudo-random string generator here. in
+ * convert(), each pass through the while loop will add more and more
+ * stuff into value, which is _supposed_ to wrap. We don't care about
+ * it being accurate. We care about it being messy, since we then mod
+ * it by the sizeof(letters) and then use that as an index into letters
+ * to pick a random letter to add to out temporary file. */
+typedef unsigned long int bb_uint64_t;
+
+static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+// if fn is NULL then input is stdin and output is stdout
+static int convert(char *fn, int ConvType)
+{
+ int c, fd;
+ struct timeval tv;
+ char tempFn[BUFSIZ];
+ static bb_uint64_t value=0;
+ FILE *in = stdin, *out = stdout;
+
+ if (fn != NULL) {
+ in = bb_xfopen(fn, "rw");
+ safe_strncpy(tempFn, fn, sizeof(tempFn));
+ c = strlen(tempFn);
+ tempFn[c] = '.';
+ while(1) {
+ if (c >=BUFSIZ)
+ bb_error_msg_and_die("unique name not found");
+ /* Get some semi random stuff to try and make a
+ * random filename based (and in the same dir as)
+ * the input file... */
+ gettimeofday (&tv, NULL);
+ value += ((bb_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
+ tempFn[++c] = letters[value % 62];
+ tempFn[c+1] = '\0';
+ value /= 62;
+
+ if ((fd = open(tempFn, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0 ) {
+ continue;
+ }
+ out = fdopen(fd, "w+");
+ if (!out) {
+ close(fd);
+ remove(tempFn);
+ continue;
+ }
+ break;
+ }
+ }
+
+ while ((c = fgetc(in)) != EOF) {
+ if (c == '\r') {
+ if ((ConvType == CT_UNIX2DOS) && (fn != NULL)) {
+ // file is alredy in DOS format so it is not necessery to touch it
+ remove(tempFn);
+ if (fclose(in) < 0 || fclose(out) < 0) {
+ bb_perror_nomsg();
+ return -2;
+ }
+ return 0;
+ }
+ if (!ConvType)
+ ConvType = CT_DOS2UNIX;
+ break;
+ }
+ if (c == '\n') {
+ if ((ConvType == CT_DOS2UNIX) && (fn != NULL)) {
+ // file is alredy in UNIX format so it is not necessery to touch it
+ remove(tempFn);
+ if ((fclose(in) < 0) || (fclose(out) < 0)) {
+ bb_perror_nomsg();
+ return -2;
+ }
+ return 0;
+ }
+ if (!ConvType) {
+ ConvType = CT_UNIX2DOS;
+ }
+ if (ConvType == CT_UNIX2DOS) {
+ fputc('\r', out);
+ }
+ fputc('\n', out);
+ break;
+ }
+ fputc(c, out);
+ }
+ if (c != EOF)
+ while ((c = fgetc(in)) != EOF) {
+ if (c == '\r')
+ continue;
+ if (c == '\n') {
+ if (ConvType == CT_UNIX2DOS)
+ fputc('\r', out);
+ fputc('\n', out);
+ continue;
+ }
+ fputc(c, out);
+ }
+
+ if (fn != NULL) {
+ if (fclose(in) < 0 || fclose(out) < 0) {
+ bb_perror_nomsg();
+ remove(tempFn);
+ return -2;
+ }
+
+ /* Assume they are both on the same filesystem (which
+ * should be true since we put them into the same directory
+ * so we _should_ be ok, but you never know... */
+ if (rename(tempFn, fn) < 0) {
+ bb_perror_msg("unable to rename '%s' as '%s'", tempFn, fn);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int dos2unix_main(int argc, char *argv[])
+{
+ int ConvType = CT_AUTO;
+ int o;
+
+ //See if we are supposed to be doing dos2unix or unix2dos
+ if (argv[0][0]=='d') {
+ ConvType = CT_DOS2UNIX;
+ }
+ if (argv[0][0]=='u') {
+ ConvType = CT_UNIX2DOS;
+ }
+
+ // process parameters
+ while ((o = getopt(argc, argv, "du")) != EOF) {
+ switch (o) {
+ case 'd':
+ ConvType = CT_UNIX2DOS;
+ break;
+ case 'u':
+ ConvType = CT_DOS2UNIX;
+ break;
+ default:
+ bb_show_usage();
+ }
+ }
+
+ if (optind < argc) {
+ while(optind < argc)
+ if ((o = convert(argv[optind++], ConvType)) < 0)
+ break;
+ }
+ else
+ o = convert(NULL, ConvType);
+
+ return o;
+}
+
diff --git a/release/src/router/busybox/coreutils/du.c b/release/src/router/busybox/coreutils/du.c
new file mode 100644
index 00000000..a9f6c28b
--- /dev/null
+++ b/release/src/router/busybox/coreutils/du.c
@@ -0,0 +1,265 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini du implementation for busybox
+ *
+ * Copyright (C) 1999,2000,2001 by Lineo, inc. and John Beppu
+ * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
+ * Copyright (C) 2002 Edward Betts <edward@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant (unless default blocksize set to 1k) */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/du.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Mostly rewritten for SUSv3 compliance and to fix bugs/defects.
+ * 1) Added support for SUSv3 -a, -H, -L, gnu -c, and (busybox) -d options.
+ * The -d option allows setting of max depth (similar to gnu --max-depth).
+ * 2) Fixed incorrect size calculations for links and directories, especially
+ * when errors occurred. Calculates sizes should now match gnu du output.
+ * 3) Added error checking of output.
+ * 4) Fixed busybox bug #1284 involving long overflow with human_readable.
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include "busybox.h"
+
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+# ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
+static unsigned long disp_hr = KILOBYTE;
+# else
+static unsigned long disp_hr = 512;
+# endif
+#elif defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
+static unsigned int disp_k = 1;
+#else
+static unsigned int disp_k; /* bss inits to 0 */
+#endif
+
+static int max_print_depth = INT_MAX;
+static int count_hardlinks = INT_MAX;
+
+static int status
+#if EXIT_SUCCESS == 0
+ = EXIT_SUCCESS
+#endif
+ ;
+static int print_files;
+static int slink_depth;
+static int du_depth;
+static int one_file_system;
+static dev_t dir_dev;
+
+
+static void print(long size, char *filename)
+{
+ /* TODO - May not want to defer error checking here. */
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+ bb_printf("%s\t%s\n", make_human_readable_str(size, 512, disp_hr),
+ filename);
+#else
+ bb_printf("%ld\t%s\n", size >> disp_k, filename);
+#endif
+}
+
+/* tiny recursive du */
+static long du(char *filename)
+{
+ struct stat statbuf;
+ long sum;
+
+ if ((lstat(filename, &statbuf)) != 0) {
+ bb_perror_msg("%s", filename);
+ status = EXIT_FAILURE;
+ return 0;
+ }
+
+ if (one_file_system) {
+ if (du_depth == 0) {
+ dir_dev = statbuf.st_dev;
+ } else if (dir_dev != statbuf.st_dev) {
+ return 0;
+ }
+ }
+
+ sum = statbuf.st_blocks;
+
+ if (S_ISLNK(statbuf.st_mode)) {
+ if (slink_depth > du_depth) { /* -H or -L */
+ if ((stat(filename, &statbuf)) != 0) {
+ bb_perror_msg("%s", filename);
+ status = EXIT_FAILURE;
+ return 0;
+ }
+ sum = statbuf.st_blocks;
+ if (slink_depth == 1) {
+ slink_depth = INT_MAX; /* Convert -H to -L. */
+ }
+ }
+ }
+
+ if (statbuf.st_nlink > count_hardlinks) {
+ /* Add files/directories with links only once */
+ if (is_in_ino_dev_hashtable(&statbuf, NULL)) {
+ return 0;
+ }
+ add_to_ino_dev_hashtable(&statbuf, NULL);
+ }
+
+ if (S_ISDIR(statbuf.st_mode)) {
+ DIR *dir;
+ struct dirent *entry;
+ char *newfile;
+
+ dir = opendir(filename);
+ if (!dir) {
+ bb_perror_msg("%s", filename);
+ status = EXIT_FAILURE;
+ return sum;
+ }
+
+ newfile = last_char_is(filename, '/');
+ if (newfile)
+ *newfile = '\0';
+
+ while ((entry = readdir(dir))) {
+ char *name = entry->d_name;
+
+ newfile = concat_subpath_file(filename, name);
+ if(newfile == NULL)
+ continue;
+ ++du_depth;
+ sum += du(newfile);
+ --du_depth;
+ free(newfile);
+ }
+ closedir(dir);
+ } else if (du_depth > print_files) {
+ return sum;
+ }
+ if (du_depth <= max_print_depth) {
+ print(sum, filename);
+ }
+ return sum;
+}
+
+int du_main(int argc, char **argv)
+{
+ long total;
+ int slink_depth_save;
+ int print_final_total;
+ char *smax_print_depth;
+ unsigned long opt;
+
+#ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
+ if (getenv("POSIXLY_CORRECT")) { /* TODO - a new libbb function? */
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+ disp_hr = 512;
+#else
+ disp_k = 0;
+#endif
+ }
+#endif
+
+ /* Note: SUSv3 specifies that -a and -s options can not be used together
+ * in strictly conforming applications. However, it also says that some
+ * du implementations may produce output when -a and -s are used together.
+ * gnu du exits with an error code in this case. We choose to simply
+ * ignore -a. This is consistent with -s being equivalent to -d 0.
+ */
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+ bb_opt_complementaly = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s";
+ opt = bb_getopt_ulflags(argc, argv, "aHkLsx" "d:" "lc" "hm", &smax_print_depth);
+ if((opt & (1 << 9))) {
+ /* -h opt */
+ disp_hr = 0;
+ }
+ if((opt & (1 << 10))) {
+ /* -m opt */
+ disp_hr = MEGABYTE;
+ }
+ if((opt & (1 << 2))) {
+ /* -k opt */
+ disp_hr = KILOBYTE;
+ }
+#else
+ bb_opt_complementaly = "H-L:L-H:s-d:d-s";
+ opt = bb_getopt_ulflags(argc, argv, "aHkLsx" "d:" "lc", &smax_print_depth);
+#if !defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
+ if((opt & (1 << 2))) {
+ /* -k opt */
+ disp_k = 1;
+ }
+#endif
+#endif
+ if((opt & (1 << 0))) {
+ /* -a opt */
+ print_files = INT_MAX;
+ }
+ if((opt & (1 << 1))) {
+ /* -H opt */
+ slink_depth = 1;
+ }
+ if((opt & (1 << 3))) {
+ /* -L opt */
+ slink_depth = INT_MAX;
+ }
+ if((opt & (1 << 4))) {
+ /* -s opt */
+ max_print_depth = 0;
+ }
+ one_file_system = opt & (1 << 5); /* -x opt */
+ if((opt & (1 << 6))) {
+ /* -d opt */
+ max_print_depth = bb_xgetularg10_bnd(smax_print_depth, 0, INT_MAX);
+ }
+ if((opt & (1 << 7))) {
+ /* -l opt */
+ count_hardlinks = 1;
+ }
+ print_final_total = opt & (1 << 8); /* -c opt */
+
+ /* go through remaining args (if any) */
+ argv += optind;
+ if (optind >= argc) {
+ *--argv = ".";
+ if (slink_depth == 1) {
+ slink_depth = 0;
+ }
+ }
+
+ slink_depth_save = slink_depth;
+ total = 0;
+ do {
+ total += du(*argv);
+ slink_depth = slink_depth_save;
+ } while (*++argv);
+#ifdef CONFIG_FEATURE_CLEAN_UP
+ reset_ino_dev_hashtable();
+#endif
+
+ if (print_final_total) {
+ print(total, "total");
+ }
+
+ bb_fflush_stdout_and_exit(status);
+}
diff --git a/release/src/router/busybox/coreutils/echo.c b/release/src/router/busybox/coreutils/echo.c
new file mode 100644
index 00000000..b600a1fb
--- /dev/null
+++ b/release/src/router/busybox/coreutils/echo.c
@@ -0,0 +1,165 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * echo implementation for busybox
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Original copyright notice is retained at the end of this file.
+ */
+
+/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Because of behavioral differences, implemented configureable SUSv3
+ * or 'fancy' gnu-ish behaviors. Also, reduced size and fixed bugs.
+ * 1) In handling '\c' escape, the previous version only suppressed the
+ * trailing newline. SUSv3 specifies _no_ output after '\c'.
+ * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}.
+ * The previous version version did not allow 4-digit octals.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+extern int echo_main(int argc, char** argv)
+{
+#ifndef CONFIG_FEATURE_FANCY_ECHO
+#define eflag '\\'
+ ++argv;
+#else
+ const char *p;
+ int nflag = 1;
+ int eflag = 0;
+
+ while (*++argv && (**argv == '-')) {
+ /* If it appears that we are handling options, then make sure
+ * that all of the options specified are actually valid.
+ * Otherwise, the string should just be echoed.
+ */
+
+ if (!*(p = *argv + 1)) { /* A single '-', so echo it. */
+ goto just_echo;
+ }
+
+ do {
+ if (strrchr("neE", *p) == 0) {
+ goto just_echo;
+ }
+ } while (*++p);
+
+ /* All of the options in this arg are valid, so handle them. */
+ p = *argv + 1;
+ do {
+ if (*p == 'n') {
+ nflag = 0;
+ } else if (*p == 'e') {
+ eflag = '\\';
+ } else {
+ eflag = 0;
+ }
+ } while (*++p);
+ }
+
+just_echo:
+#endif
+ while (*argv) {
+ register int c;
+
+ while ((c = *(*argv)++)) {
+ if (c == eflag) { /* Check for escape seq. */
+ if (**argv == 'c') {
+ /* '\c' means cancel newline and
+ * ignore all subsequent chars. */
+ goto DONE;
+ }
+#ifndef CONFIG_FEATURE_FANCY_ECHO
+ /* SUSv3 specifies that octal escapes must begin with '0'. */
+ if (((unsigned int)(**argv - '1')) >= 7)
+#endif
+ {
+ /* Since SUSv3 mandates a first digit of 0, 4-digit octals
+ * of the form \0### are accepted. */
+ if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) {
+ (*argv)++;
+ }
+ /* bb_process_escape_sequence can handle nul correctly */
+ c = bb_process_escape_sequence((const char **) argv);
+ }
+ }
+ putchar(c);
+ }
+
+ if (*++argv) {
+ putchar(' ');
+ }
+ }
+
+#ifdef CONFIG_FEATURE_FANCY_ECHO
+ if (nflag) {
+ putchar('\n');
+ }
+#else
+ putchar('\n');
+#endif
+
+DONE:
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}
+
+/*-
+ * 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. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
+ *
+ * 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.
+ *
+ * @(#)echo.c 8.1 (Berkeley) 5/31/93
+ */
diff --git a/release/src/router/busybox/coreutils/env.c b/release/src/router/busybox/coreutils/env.c
new file mode 100644
index 00000000..d8a76e36
--- /dev/null
+++ b/release/src/router/busybox/coreutils/env.c
@@ -0,0 +1,144 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * env implementation for busybox
+ *
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Original copyright notice is retained at the end of this file.
+ *
+ * Modified for BusyBox by Erik Andersen <andersen@codepoet.org>
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/env.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Fixed bug involving exit return codes if execvp fails. Also added
+ * output error checking.
+ */
+
+/*
+ * Modified by Vladimir Oleynik <andersen@codepoet.org> (C) 2003
+ * - corretion "-" option usage
+ * - multiple "-u unsetenv" support
+ * - GNU long option support
+ * - save errno after exec failed before bb_perror_msg()
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "busybox.h"
+
+
+static const struct option env_long_options[] = {
+ { "ignore-environment", 0, NULL, 'i' },
+ { "unset", 1, NULL, 'u' },
+ { 0, 0, 0, 0 }
+};
+
+extern int env_main(int argc, char** argv)
+{
+ char **ep, *p;
+ char *cleanenv[1] = { NULL };
+ unsigned long opt;
+ llist_t *unset_env;
+ extern char **environ;
+
+ bb_opt_complementaly = "u*";
+ bb_applet_long_options = env_long_options;
+
+ opt = bb_getopt_ulflags(argc, argv, "+iu:", &unset_env);
+
+ argv += optind;
+ if (*argv && (argv[0][0] == '-') && !argv[0][1]) {
+ opt |= 1;
+ ++argv;
+ }
+
+ if(opt & 1)
+ environ = cleanenv;
+ else if(opt & 2) {
+ while(unset_env) {
+ unsetenv(unset_env->data);
+ unset_env = unset_env->link;
+ }
+ }
+
+ while (*argv && ((p = strchr(*argv, '=')) != NULL)) {
+ if (putenv(*argv) < 0) {
+ bb_perror_msg_and_die("putenv");
+ }
+ ++argv;
+ }
+
+ if (*argv) {
+ int er;
+
+ execvp(*argv, argv);
+ er = errno;
+ bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
+ return (er == ENOENT) ? 127 : 126; /* SUSv3-mandated exit codes. */
+ }
+
+ for (ep = environ; *ep; ep++) {
+ puts(*ep);
+ }
+
+ bb_fflush_stdout_and_exit(0);
+}
+
+/*
+ * Copyright (c) 1988, 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. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
+ *
+ * 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.
+ */
+
+
diff --git a/release/src/router/busybox/coreutils/expr.c b/release/src/router/busybox/coreutils/expr.c
new file mode 100644
index 00000000..ecba825d
--- /dev/null
+++ b/release/src/router/busybox/coreutils/expr.c
@@ -0,0 +1,529 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini expr implementation for busybox
+ *
+ * based on GNU expr Mike Parker.
+ * Copyright (C) 86, 1991-1997, 1999 Free Software Foundation, Inc.
+ *
+ * Busybox modifications
+ * Copyright (c) 2000 Edward Betts <edward@debian.org>.
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2 of the license, or
+ * (at your option) any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose. see the gnu
+ * general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; if not, write to the free software
+ * foundation, inc., 59 temple place, suite 330, boston, ma 02111-1307 usa
+ *
+ */
+
+/* This program evaluates expressions. Each token (operator, operand,
+ * parenthesis) of the expression must be a seperate argument. The
+ * parser used is a reasonably general one, though any incarnation of
+ * it is language-specific. It is especially nice for expressions.
+ *
+ * No parse tree is needed; a new node is evaluated immediately.
+ * One function can handle multiple operators all of equal precedence,
+ * provided they all associate ((x op x) op x). */
+
+/* no getopt needed */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <regex.h>
+#include <sys/types.h>
+#include "busybox.h"
+
+
+/* The kinds of value we can have. */
+enum valtype {
+ integer,
+ string
+};
+typedef enum valtype TYPE;
+
+/* A value is.... */
+struct valinfo {
+ TYPE type; /* Which kind. */
+ union { /* The value itself. */
+ int i;
+ char *s;
+ } u;
+};
+typedef struct valinfo VALUE;
+
+/* The arguments given to the program, minus the program name. */
+static char **args;
+
+static VALUE *docolon (VALUE *sv, VALUE *pv);
+static VALUE *eval (void);
+static VALUE *int_value (int i);
+static VALUE *str_value (char *s);
+static int nextarg (char *str);
+static int null (VALUE *v);
+static int toarith (VALUE *v);
+static void freev (VALUE *v);
+static void tostring (VALUE *v);
+
+int expr_main (int argc, char **argv)
+{
+ VALUE *v;
+
+ if (argc == 1) {
+ bb_error_msg_and_die("too few arguments");
+ }
+
+ args = argv + 1;
+
+ v = eval ();
+ if (*args)
+ bb_error_msg_and_die ("syntax error");
+
+ if (v->type == integer)
+ printf ("%d\n", v->u.i);
+ else
+ puts (v->u.s);
+
+ exit (null (v));
+}
+
+/* Return a VALUE for I. */
+
+static VALUE *int_value (int i)
+{
+ VALUE *v;
+
+ v = xmalloc (sizeof(VALUE));
+ v->type = integer;
+ v->u.i = i;
+ return v;
+}
+
+/* Return a VALUE for S. */
+
+static VALUE *str_value (char *s)
+{
+ VALUE *v;
+
+ v = xmalloc (sizeof(VALUE));
+ v->type = string;
+ v->u.s = strdup (s);
+ return v;
+}
+
+/* Free VALUE V, including structure components. */
+
+static void freev (VALUE *v)
+{
+ if (v->type == string)
+ free (v->u.s);
+ free (v);
+}
+
+/* Return nonzero if V is a null-string or zero-number. */
+
+static int null (VALUE *v)
+{
+ switch (v->type) {
+ case integer:
+ return v->u.i == 0;
+ case string:
+ return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
+ default:
+ abort ();
+ }
+}
+
+/* Coerce V to a string value (can't fail). */
+
+static void tostring (VALUE *v)
+{
+ if (v->type == integer) {
+ bb_xasprintf (&(v->u.s), "%d", v->u.i);
+ v->type = string;
+ }
+}
+
+/* Coerce V to an integer value. Return 1 on success, 0 on failure. */
+
+static int toarith (VALUE *v)
+{
+ int i;
+
+ switch (v->type) {
+ case integer:
+ return 1;
+ case string:
+ i = 0;
+ /* Don't interpret the empty string as an integer. */
+ if (v->u.s == 0)
+ return 0;
+ i = atoi(v->u.s);
+ free (v->u.s);
+ v->u.i = i;
+ v->type = integer;
+ return 1;
+ default:
+ abort ();
+ }
+}
+
+/* Return nonzero if the next token matches STR exactly.
+ STR must not be NULL. */
+
+static int
+nextarg (char *str)
+{
+ if (*args == NULL)
+ return 0;
+ return strcmp (*args, str) == 0;
+}
+
+/* The comparison operator handling functions. */
+
+#define cmpf(name, rel) \
+static int name (VALUE *l, VALUE *r) \
+{ \
+ if (l->type == string || r->type == string) { \
+ tostring (l); \
+ tostring (r); \
+ return strcmp (l->u.s, r->u.s) rel 0; \
+ } \
+ else \
+ return l->u.i rel r->u.i; \
+}
+ cmpf (less_than, <)
+ cmpf (less_equal, <=)
+ cmpf (equal, ==)
+ cmpf (not_equal, !=)
+ cmpf (greater_equal, >=)
+ cmpf (greater_than, >)
+
+#undef cmpf
+
+/* The arithmetic operator handling functions. */
+
+#define arithf(name, op) \
+static \
+int name (VALUE *l, VALUE *r) \
+{ \
+ if (!toarith (l) || !toarith (r)) \
+ bb_error_msg_and_die ("non-numeric argument"); \
+ return l->u.i op r->u.i; \
+}
+
+#define arithdivf(name, op) \
+static int name (VALUE *l, VALUE *r) \
+{ \
+ if (!toarith (l) || !toarith (r)) \
+ bb_error_msg_and_die ( "non-numeric argument"); \
+ if (r->u.i == 0) \
+ bb_error_msg_and_die ( "division by zero"); \
+ return l->u.i op r->u.i; \
+}
+
+ arithf (plus, +)
+ arithf (minus, -)
+ arithf (multiply, *)
+ arithdivf (divide, /)
+ arithdivf (mod, %)
+
+#undef arithf
+#undef arithdivf
+
+/* Do the : operator.
+ SV is the VALUE for the lhs (the string),
+ PV is the VALUE for the rhs (the pattern). */
+
+static VALUE *docolon (VALUE *sv, VALUE *pv)
+{
+ VALUE *v;
+ const char *errmsg;
+ struct re_pattern_buffer re_buffer;
+ struct re_registers re_regs;
+ int len;
+
+ tostring (sv);
+ tostring (pv);
+
+ if (pv->u.s[0] == '^') {
+ fprintf (stderr, "\
+warning: unportable BRE: `%s': using `^' as the first character\n\
+of a basic regular expression is not portable; it is being ignored",
+ pv->u.s);
+ }
+
+ len = strlen (pv->u.s);
+ memset (&re_buffer, 0, sizeof (re_buffer));
+ memset (&re_regs, 0, sizeof (re_regs));
+ re_buffer.allocated = 2 * len;
+ re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated);
+ re_buffer.translate = 0;
+ re_syntax_options = RE_SYNTAX_POSIX_BASIC;
+ errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
+ if (errmsg) {
+ bb_error_msg_and_die("%s", errmsg);
+ }
+
+ len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
+ if (len >= 0) {
+ /* Were \(...\) used? */
+ if (re_buffer.re_nsub > 0) { /* was (re_regs.start[1] >= 0) */
+ sv->u.s[re_regs.end[1]] = '\0';
+ v = str_value (sv->u.s + re_regs.start[1]);
+ }
+ else
+ v = int_value (len);
+ }
+ else {
+ /* Match failed -- return the right kind of null. */
+ if (re_buffer.re_nsub > 0)
+ v = str_value ("");
+ else
+ v = int_value (0);
+ }
+ free (re_buffer.buffer);
+ return v;
+}
+
+/* Handle bare operands and ( expr ) syntax. */
+
+static VALUE *eval7 (void)
+{
+ VALUE *v;
+
+ if (!*args)
+ bb_error_msg_and_die ( "syntax error");
+
+ if (nextarg ("(")) {
+ args++;
+ v = eval ();
+ if (!nextarg (")"))
+ bb_error_msg_and_die ( "syntax error");
+ args++;
+ return v;
+ }
+
+ if (nextarg (")"))
+ bb_error_msg_and_die ( "syntax error");
+
+ return str_value (*args++);
+}
+
+/* Handle match, substr, index, length, and quote keywords. */
+
+static VALUE *eval6 (void)
+{
+ VALUE *l, *r, *v, *i1, *i2;
+
+ if (nextarg ("quote")) {
+ args++;
+ if (!*args)
+ bb_error_msg_and_die ( "syntax error");
+ return str_value (*args++);
+ }
+ else if (nextarg ("length")) {
+ args++;
+ r = eval6 ();
+ tostring (r);
+ v = int_value (strlen (r->u.s));
+ freev (r);
+ return v;
+ }
+ else if (nextarg ("match")) {
+ args++;
+ l = eval6 ();
+ r = eval6 ();
+ v = docolon (l, r);
+ freev (l);
+ freev (r);
+ return v;
+ }
+ else if (nextarg ("index")) {
+ args++;
+ l = eval6 ();
+ r = eval6 ();
+ tostring (l);
+ tostring (r);
+ v = int_value (strcspn (l->u.s, r->u.s) + 1);
+ if (v->u.i == (int) strlen (l->u.s) + 1)
+ v->u.i = 0;
+ freev (l);
+ freev (r);
+ return v;
+ }
+ else if (nextarg ("substr")) {
+ args++;
+ l = eval6 ();
+ i1 = eval6 ();
+ i2 = eval6 ();
+ tostring (l);
+ if (!toarith (i1) || !toarith (i2)
+ || i1->u.i > (int) strlen (l->u.s)
+ || i1->u.i <= 0 || i2->u.i <= 0)
+ v = str_value ("");
+ else {
+ v = xmalloc (sizeof(VALUE));
+ v->type = string;
+ v->u.s = bb_xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
+ }
+ freev (l);
+ freev (i1);
+ freev (i2);
+ return v;
+ }
+ else
+ return eval7 ();
+}
+
+/* Handle : operator (pattern matching).
+ Calls docolon to do the real work. */
+
+static VALUE *eval5 (void)
+{
+ VALUE *l, *r, *v;
+
+ l = eval6 ();
+ while (nextarg (":")) {
+ args++;
+ r = eval6 ();
+ v = docolon (l, r);
+ freev (l);
+ freev (r);
+ l = v;
+ }
+ return l;
+}
+
+/* Handle *, /, % operators. */
+
+static VALUE *eval4 (void)
+{
+ VALUE *l, *r;
+ int (*fxn) (VALUE *, VALUE *), val;
+
+ l = eval5 ();
+ while (1) {
+ if (nextarg ("*"))
+ fxn = multiply;
+ else if (nextarg ("/"))
+ fxn = divide;
+ else if (nextarg ("%"))
+ fxn = mod;
+ else
+ return l;
+ args++;
+ r = eval5 ();
+ val = (*fxn) (l, r);
+ freev (l);
+ freev (r);
+ l = int_value (val);
+ }
+}
+
+/* Handle +, - operators. */
+
+static VALUE *eval3 (void)
+{
+ VALUE *l, *r;
+ int (*fxn) (VALUE *, VALUE *), val;
+
+ l = eval4 ();
+ while (1) {
+ if (nextarg ("+"))
+ fxn = plus;
+ else if (nextarg ("-"))
+ fxn = minus;
+ else
+ return l;
+ args++;
+ r = eval4 ();
+ val = (*fxn) (l, r);
+ freev (l);
+ freev (r);
+ l = int_value (val);
+ }
+}
+
+/* Handle comparisons. */
+
+static VALUE *eval2 (void)
+{
+ VALUE *l, *r;
+ int (*fxn) (VALUE *, VALUE *), val;
+
+ l = eval3 ();
+ while (1) {
+ if (nextarg ("<"))
+ fxn = less_than;
+ else if (nextarg ("<="))
+ fxn = less_equal;
+ else if (nextarg ("=") || nextarg ("=="))
+ fxn = equal;
+ else if (nextarg ("!="))
+ fxn = not_equal;
+ else if (nextarg (">="))
+ fxn = greater_equal;
+ else if (nextarg (">"))
+ fxn = greater_than;
+ else
+ return l;
+ args++;
+ r = eval3 ();
+ toarith (l);
+ toarith (r);
+ val = (*fxn) (l, r);
+ freev (l);
+ freev (r);
+ l = int_value (val);
+ }
+}
+
+/* Handle &. */
+
+static VALUE *eval1 (void)
+{
+ VALUE *l, *r;
+
+ l = eval2 ();
+ while (nextarg ("&")) {
+ args++;
+ r = eval2 ();
+ if (null (l) || null (r)) {
+ freev (l);
+ freev (r);
+ l = int_value (0);
+ }
+ else
+ freev (r);
+ }
+ return l;
+}
+
+/* Handle |. */
+
+static VALUE *eval (void)
+{
+ VALUE *l, *r;
+
+ l = eval1 ();
+ while (nextarg ("|")) {
+ args++;
+ r = eval1 ();
+ if (null (l)) {
+ freev (l);
+ l = r;
+ }
+ else
+ freev (r);
+ }
+ return l;
+}
diff --git a/release/src/router/busybox/coreutils/false.c b/release/src/router/busybox/coreutils/false.c
new file mode 100644
index 00000000..a07b99d9
--- /dev/null
+++ b/release/src/router/busybox/coreutils/false.c
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini false implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/false.html */
+
+#include <stdlib.h>
+#include "busybox.h"
+
+extern int false_main(int argc, char **argv)
+{
+ return EXIT_FAILURE;
+}
diff --git a/release/src/router/busybox/coreutils/fold.c b/release/src/router/busybox/coreutils/fold.c
new file mode 100644
index 00000000..df511075
--- /dev/null
+++ b/release/src/router/busybox/coreutils/fold.c
@@ -0,0 +1,194 @@
+/* fold -- wrap each input line to fit in specified width.
+
+ Written by David MacKenzie, djm@gnu.ai.mit.edu.
+ Copyright (C) 91, 1995-2002 Free Software Foundation, Inc.
+
+ Modified for busybox based on coreutils v 5.0
+ Copyright (C) 2003 Glenn McGrath <bug1@optushome.com.au>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/types.h>
+
+#include "busybox.h"
+
+/* If nonzero, count bytes, not column positions. */
+static int count_bytes;
+
+/* Assuming the current column is COLUMN, return the column that
+ printing C will move the cursor to.
+ The first column is 0. */
+
+static int adjust_column(int column, char c)
+{
+ if (!count_bytes) {
+ if (c == '\b') {
+ if (column > 0)
+ column--;
+ } else if (c == '\r')
+ column = 0;
+ else if (c == '\t')
+ column = column + 8 - column % 8;
+ else /* if (isprint (c)) */
+ column++;
+ } else
+ column++;
+ return column;
+}
+
+extern int fold_main(int argc, char **argv)
+{
+ /* If nonzero, try to break on whitespace. */
+ int break_spaces;
+
+ /* If nonzero, at least one of the files we read was standard input. */
+ int have_read_stdin;
+
+ int width = 80;
+ int i;
+ int optc;
+ int errs = 0;
+
+ break_spaces = count_bytes = have_read_stdin = 0;
+
+ /* Turn any numeric options into -w options. */
+ for (i = 1; i < argc; i++) {
+ char const *a = argv[i];
+
+ if (a[0] == '-') {
+ if (a[1] == '-' && !a[2])
+ break;
+ if (isdigit(a[1])) {
+ char *s = xmalloc(strlen(a) + 2);
+
+ s[0] = '-';
+ s[1] = 'w';
+ strcpy(s + 2, a + 1);
+ argv[i] = s;
+ }
+ }
+ }
+
+ while ((optc = getopt(argc, argv, "bsw:")) > 0) {
+ switch (optc) {
+ case 'b': /* Count bytes rather than columns. */
+ count_bytes = 1;
+ break;
+ case 's': /* Break at word boundaries. */
+ break_spaces = 1;
+ break;
+ case 'w': { /* Line width. */
+ width = bb_xgetlarg(optarg, 10, 1, 10000);
+ break;
+ }
+ default:
+ bb_show_usage();
+ }
+ }
+
+ argv += optind;
+ if (!*argv) {
+ *--argv = "-";
+ }
+
+ do {
+ FILE *istream = bb_wfopen_input(*argv);
+ if (istream != NULL) {
+ int c;
+ int column = 0; /* Screen column where next char will go. */
+ int offset_out = 0; /* Index in `line_out' for next char. */
+ static char *line_out = NULL;
+ static int allocated_out = 0;
+
+ while ((c = getc(istream)) != EOF) {
+ if (offset_out + 1 >= allocated_out) {
+ allocated_out += 1024;
+ line_out = xrealloc(line_out, allocated_out);
+ }
+
+ if (c == '\n') {
+ line_out[offset_out++] = c;
+ fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
+ column = offset_out = 0;
+ continue;
+ }
+
+rescan:
+ column = adjust_column(column, c);
+
+ if (column > width) {
+ /* This character would make the line too long.
+ Print the line plus a newline, and make this character
+ start the next line. */
+ if (break_spaces) {
+ /* Look for the last blank. */
+ int logical_end;
+
+ for (logical_end = offset_out - 1; logical_end >= 0; logical_end--) {
+ if (isblank(line_out[logical_end])) {
+ break;
+ }
+ }
+ if (logical_end >= 0) {
+ /* Found a blank. Don't output the part after it. */
+ logical_end++;
+ fwrite(line_out, sizeof(char), (size_t) logical_end, stdout);
+ putchar('\n');
+ /* Move the remainder to the beginning of the next line.
+ The areas being copied here might overlap. */
+ memmove(line_out, line_out + logical_end, offset_out - logical_end);
+ offset_out -= logical_end;
+ for (column = i = 0; i < offset_out; i++) {
+ column = adjust_column(column, line_out[i]);
+ }
+ goto rescan;
+ }
+ } else {
+ if (offset_out == 0) {
+ line_out[offset_out++] = c;
+ continue;
+ }
+ }
+ line_out[offset_out++] = '\n';
+ fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
+ column = offset_out = 0;
+ goto rescan;
+ }
+
+ line_out[offset_out++] = c;
+ }
+
+ if (offset_out) {
+ fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
+ }
+
+ if (ferror(istream) || bb_fclose_nonstdin(istream)) {
+ bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
+ errs |= EXIT_FAILURE;
+ }
+ } else {
+ errs |= EXIT_FAILURE;
+ }
+ } while (*++argv);
+
+ bb_fflush_stdout_and_exit(errs);
+}
diff --git a/release/src/router/busybox/coreutils/head.c b/release/src/router/busybox/coreutils/head.c
new file mode 100644
index 00000000..dab4de11
--- /dev/null
+++ b/release/src/router/busybox/coreutils/head.c
@@ -0,0 +1,138 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * head implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "busybox.h"
+
+static const char head_opts[] =
+ "n:"
+#ifdef CONFIG_FEATURE_FANCY_HEAD
+ "c:qv"
+#endif
+ ;
+
+static const char header_fmt_str[] = "\n==> %s <==\n";
+
+int head_main(int argc, char **argv)
+{
+ unsigned long count = 10;
+ unsigned long i;
+#ifdef CONFIG_FEATURE_FANCY_HEAD
+ int count_bytes = 0;
+ int header_threshhold = 1;
+#endif
+
+ FILE *fp;
+ const char *fmt;
+ char *p;
+ int opt;
+ int c;
+ int retval = EXIT_SUCCESS;
+
+ /* Allow legacy syntax of an initial numeric option without -n. */
+ if ((argc > 1) && (argv[1][0] == '-')
+ /* && (isdigit)(argv[1][1]) */
+ && (((unsigned int)(argv[1][1] - '0')) <= 9)
+ ) {
+ --argc;
+ ++argv;
+ p = (*argv) + 1;
+ goto GET_COUNT;
+ }
+
+ while ((opt = getopt(argc, argv, head_opts)) > 0) {
+ switch(opt) {
+#ifdef CONFIG_FEATURE_FANCY_HEAD
+ case 'q':
+ header_threshhold = INT_MAX;
+ break;
+ case 'v':
+ header_threshhold = -1;
+ break;
+ case 'c':
+ count_bytes = 1;
+ /* fall through */
+#endif
+ case 'n':
+ p = optarg;
+ GET_COUNT:
+ count = bb_xgetularg10(p);
+ break;
+ default:
+ bb_show_usage();
+ }
+ }
+
+ argv += optind;
+ if (!*argv) {
+ *--argv = "-";
+ }
+
+ fmt = header_fmt_str + 1;
+#ifdef CONFIG_FEATURE_FANCY_HEAD
+ if (argc - optind <= header_threshhold) {
+ header_threshhold = 0;
+ }
+#else
+ if (argc <= optind + 1) {
+ fmt += 11;
+ }
+ /* Now define some things here to avoid #ifdefs in the code below.
+ * These should optimize out of the if conditions below. */
+#define header_threshhold 1
+#define count_bytes 0
+#endif
+
+ do {
+ if ((fp = bb_wfopen_input(*argv)) != NULL) {
+ if (fp == stdin) {
+ *argv = (char *) bb_msg_standard_input;
+ }
+ if (header_threshhold) {
+ bb_printf(fmt, *argv);
+ }
+ i = count;
+ while (i && ((c = getc(fp)) != EOF)) {
+ if (count_bytes || (c == '\n')) {
+ --i;
+ }
+ putchar(c);
+ }
+ if (bb_fclose_nonstdin(fp)) {
+ bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
+ retval = EXIT_FAILURE;
+ }
+ bb_xferror_stdout();
+ }
+ fmt = header_fmt_str;
+ } while (*++argv);
+
+ bb_fflush_stdout_and_exit(retval);
+}
diff --git a/release/src/router/busybox/coreutils/hostid.c b/release/src/router/busybox/coreutils/hostid.c
new file mode 100644
index 00000000..917dc223
--- /dev/null
+++ b/release/src/router/busybox/coreutils/hostid.c
@@ -0,0 +1,38 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini hostid implementation for busybox
+ *
+ * Copyright (C) 2000 Edward Betts <edward@debian.org>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+extern int hostid_main(int argc, char **argv)
+{
+ if (argc > 1) {
+ bb_show_usage();
+ }
+
+ bb_printf("%lx\n", gethostid());
+
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}
diff --git a/release/src/router/busybox/coreutils/id.c b/release/src/router/busybox/coreutils/id.c
new file mode 100644
index 00000000..971e7cda
--- /dev/null
+++ b/release/src/router/busybox/coreutils/id.c
@@ -0,0 +1,110 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini id implementation for busybox
+ *
+ * Copyright (C) 2000 by Randolph Chung <tausq@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <sys/types.h>
+#ifdef CONFIG_SELINUX
+#include <proc_secure.h>
+#include <flask_util.h>
+#endif
+
+#define JUST_USER 1
+#define JUST_GROUP 2
+#define PRINT_REAL 4
+#define NAME_NOT_NUMBER 8
+
+extern int id_main(int argc, char **argv)
+{
+ char user[9], group[9];
+ long pwnam, grnam;
+ int uid, gid;
+ int flags;
+#ifdef CONFIG_SELINUX
+ int is_flask_enabled_flag = is_flask_enabled();
+#endif
+
+ flags = bb_getopt_ulflags(argc, argv, "ugrn");
+
+ if (((flags & (JUST_USER | JUST_GROUP)) == (JUST_USER | JUST_GROUP))
+ || (argc > optind + 1)
+ ) {
+ bb_show_usage();
+ }
+
+ if (argv[optind] == NULL) {
+ if (flags & PRINT_REAL) {
+ uid = getuid();
+ gid = getgid();
+ } else {
+ uid = geteuid();
+ gid = getegid();
+ }
+ my_getpwuid(user, uid);
+ } else {
+ safe_strncpy(user, argv[optind], sizeof(user));
+ gid = my_getpwnamegid(user);
+ }
+ my_getgrgid(group, gid);
+
+ pwnam=my_getpwnam(user);
+ grnam=my_getgrnam(group);
+
+ if (flags & (JUST_GROUP | JUST_USER)) {
+ char *s = group;
+ if (flags & JUST_USER) {
+ s = user;
+ grnam = pwnam;
+ }
+ if (flags & NAME_NOT_NUMBER) {
+ puts(s);
+ } else {
+ printf("%ld\n", grnam);
+ }
+ } else {
+#ifdef CONFIG_SELINUX
+ printf("uid=%ld(%s) gid=%ld(%s)", pwnam, user, grnam, group);
+ if(is_flask_enabled_flag)
+ {
+ security_id_t mysid = getsecsid();
+ char context[80];
+ int len = sizeof(context);
+ context[0] = '\0';
+ if(security_sid_to_context(mysid, context, &len))
+ strcpy(context, "unknown");
+ printf(" context=%s\n", context);
+ }
+ else
+ printf("\n");
+#else
+ printf("uid=%ld(%s) gid=%ld(%s)\n", pwnam, user, grnam, group);
+#endif
+
+ }
+
+ bb_fflush_stdout_and_exit(0);
+}
diff --git a/release/src/router/busybox/coreutils/length.c b/release/src/router/busybox/coreutils/length.c
new file mode 100644
index 00000000..bce43ab3
--- /dev/null
+++ b/release/src/router/busybox/coreutils/length.c
@@ -0,0 +1,19 @@
+/* vi: set sw=4 ts=4: */
+
+/* BB_AUDIT SUSv3 N/A -- Apparently a busybox (obsolete?) extension. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "busybox.h"
+
+extern int length_main(int argc, char **argv)
+{
+ if ((argc != 2) || (**(++argv) == '-')) {
+ bb_show_usage();
+ }
+
+ bb_printf("%lu\n", (unsigned long)strlen(*argv));
+
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}
diff --git a/release/src/router/busybox/coreutils/libcoreutils/Makefile b/release/src/router/busybox/coreutils/libcoreutils/Makefile
new file mode 100644
index 00000000..b3a4e79b
--- /dev/null
+++ b/release/src/router/busybox/coreutils/libcoreutils/Makefile
@@ -0,0 +1,30 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+TOPDIR:= ../../
+LIBCOREUTILS_DIR:=./
+include $(TOPDIR).config
+include $(TOPDIR)Rules.mak
+include Makefile.in
+all: $(libraries-y)
+-include $(TOPDIR).depend
+
+clean:
+ rm -f *.o *.a $(AR_TARGET)
+
diff --git a/release/src/router/busybox/coreutils/libcoreutils/Makefile.in b/release/src/router/busybox/coreutils/libcoreutils/Makefile.in
new file mode 100755
index 00000000..a7481d40
--- /dev/null
+++ b/release/src/router/busybox/coreutils/libcoreutils/Makefile.in
@@ -0,0 +1,32 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+LIBCOREUTILS_AR:=libcoreutils.a
+ifndef $(LIBCOREUTILS_DIR)
+LIBCOREUTILS_DIR:=$(TOPDIR)coreutils/libcoreutils/
+endif
+
+LIBCOREUTILS_SRC:= cp_mv_stat.c getopt_mk_fifo_nod.c xgetoptfile_sort_uniq.c
+
+LIBCOREUTILS_OBJS=$(patsubst %.c,$(LIBCOREUTILS_DIR)%.o, $(LIBCOREUTILS_SRC))
+
+libraries-y+=$(LIBCOREUTILS_DIR)$(LIBCOREUTILS_AR)
+
+$(LIBCOREUTILS_DIR)$(LIBCOREUTILS_AR): $(LIBCOREUTILS_OBJS)
+ $(AR) -ro $@ $(LIBCOREUTILS_OBJS)
diff --git a/release/src/router/busybox/coreutils/libcoreutils/coreutils.h b/release/src/router/busybox/coreutils/libcoreutils/coreutils.h
new file mode 100644
index 00000000..eabca820
--- /dev/null
+++ b/release/src/router/busybox/coreutils/libcoreutils/coreutils.h
@@ -0,0 +1,12 @@
+#ifndef COREUTILS_H
+#define COREUTILS_H 1
+
+typedef int (*stat_func)(const char *fn, struct stat *ps);
+
+extern int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf);
+extern int cp_mv_stat(const char *fn, struct stat *fn_stat);
+
+extern mode_t getopt_mk_fifo_nod(int argc, char **argv);
+extern FILE *xgetoptfile_sort_uniq(char **argv, const char *mode);
+
+#endif
diff --git a/release/src/router/busybox/coreutils/libcoreutils/cp_mv_stat.c b/release/src/router/busybox/coreutils/libcoreutils/cp_mv_stat.c
new file mode 100644
index 00000000..5a70b022
--- /dev/null
+++ b/release/src/router/busybox/coreutils/libcoreutils/cp_mv_stat.c
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * coreutils utility routine
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <errno.h>
+#include <sys/stat.h>
+#include "libbb.h"
+#include "coreutils.h"
+
+extern int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf)
+{
+ if (sf(fn, fn_stat) < 0) {
+ if (errno != ENOENT) {
+ bb_perror_msg("unable to stat `%s'", fn);
+ return -1;
+ }
+ return 0;
+ } else if (S_ISDIR(fn_stat->st_mode)) {
+ return 3;
+ }
+ return 1;
+}
+
+extern int cp_mv_stat(const char *fn, struct stat *fn_stat)
+{
+ return cp_mv_stat2(fn, fn_stat, stat);
+}
diff --git a/release/src/router/busybox/coreutils/libcoreutils/getopt_mk_fifo_nod.c b/release/src/router/busybox/coreutils/libcoreutils/getopt_mk_fifo_nod.c
new file mode 100644
index 00000000..0872bdcf
--- /dev/null
+++ b/release/src/router/busybox/coreutils/libcoreutils/getopt_mk_fifo_nod.c
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * coreutils utility routine
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "libbb.h"
+#include "coreutils.h"
+
+extern mode_t getopt_mk_fifo_nod(int argc, char **argv)
+{
+ mode_t mode = 0666;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "m:")) > 0) {
+ if (opt == 'm') {
+ mode = 0666;
+ if (bb_parse_mode(optarg, &mode)) {
+ umask(0);
+ continue;
+ }
+ }
+ bb_show_usage();
+ }
+ return mode;
+}
diff --git a/release/src/router/busybox/coreutils/libcoreutils/xgetoptfile_sort_uniq.c b/release/src/router/busybox/coreutils/libcoreutils/xgetoptfile_sort_uniq.c
new file mode 100644
index 00000000..a63daf97
--- /dev/null
+++ b/release/src/router/busybox/coreutils/libcoreutils/xgetoptfile_sort_uniq.c
@@ -0,0 +1,38 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * coreutils utility routine
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include "libbb.h"
+#include "coreutils.h"
+
+extern FILE *xgetoptfile_sort_uniq(char **argv, const char *mode)
+{
+ const char *n;
+
+ if ((n = *argv) != NULL) {
+ if ((*n != '-') || n[1]) {
+ return bb_xfopen(n, mode);
+ }
+ }
+ return (*mode == 'r') ? stdin : stdout;
+}
diff --git a/release/src/router/busybox/coreutils/ln.c b/release/src/router/busybox/coreutils/ln.c
new file mode 100644
index 00000000..5217634f
--- /dev/null
+++ b/release/src/router/busybox/coreutils/ln.c
@@ -0,0 +1,105 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini ln implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU options missing: -b, -d, -F, -i, -S, and -v. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Fixed bug involving -n option. Essentially, -n was always in effect.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+#define LN_SYMLINK 1
+#define LN_FORCE 2
+#define LN_NODEREFERENCE 4
+
+extern int ln_main(int argc, char **argv)
+{
+ int status = EXIT_SUCCESS;
+ int flag;
+ char *last;
+ char *src_name;
+ const char *src;
+ int (*link_func)(const char *, const char *);
+
+ flag = bb_getopt_ulflags(argc, argv, "sfn");
+
+ if (argc == optind) {
+ bb_show_usage();
+ }
+
+ last = argv[argc - 1];
+ argv += optind;
+
+ if (argc == optind + 1) {
+ *--argv = last;
+ last = bb_get_last_path_component(bb_xstrdup(last));
+ }
+
+ do {
+ src_name = 0;
+ src = last;
+
+ if (is_directory(src,
+ (flag & LN_NODEREFERENCE) ^ LN_NODEREFERENCE,
+ NULL)) {
+ src_name = bb_xstrdup(*argv);
+ src = concat_path_file(src, bb_get_last_path_component(src_name));
+ free(src_name);
+ src_name = (char *)src;
+ }
+
+ if (flag & LN_FORCE) {
+ unlink(src);
+ }
+
+ link_func = link;
+ if (flag & LN_SYMLINK) {
+ link_func = symlink;
+ }
+
+ if (link_func(*argv, src) != 0) {
+ bb_perror_msg(src);
+ status = EXIT_FAILURE;;
+ }
+
+ free(src_name);
+
+ } while ((++argv)[1]);
+
+ return status;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/release/src/router/busybox/coreutils/logname.c b/release/src/router/busybox/coreutils/logname.c
new file mode 100644
index 00000000..9cedff02
--- /dev/null
+++ b/release/src/router/busybox/coreutils/logname.c
@@ -0,0 +1,55 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini logname implementation for busybox
+ *
+ * Copyright (C) 2000 Edward Betts <edward@debian.org>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/logname.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * SUSv3 specifies the string used is that returned from getlogin().
+ * The previous implementation used getpwuid() for geteuid(), which
+ * is _not_ the same. Erik apparently made this change almost 3 years
+ * ago to avoid failing when no utmp was available. However, the
+ * correct course of action wrt SUSv3 for a failing getlogin() is
+ * a dianostic message and an error return.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+extern int logname_main(int argc, char **argv)
+{
+ const char *p;
+
+ if (argc > 1) {
+ bb_show_usage();
+ }
+
+ if ((p = getlogin()) != NULL) {
+ puts(p);
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+ }
+
+ bb_perror_msg_and_die("getlogin");
+}
diff --git a/release/src/router/busybox/coreutils/ls.c b/release/src/router/busybox/coreutils/ls.c
new file mode 100644
index 00000000..a7f036b6
--- /dev/null
+++ b/release/src/router/busybox/coreutils/ls.c
@@ -0,0 +1,1097 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tiny-ls.c version 0.1.0: A minimalist 'ls'
+ * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * To achieve a small memory footprint, this version of 'ls' doesn't do any
+ * file sorting, and only has the most essential command line switches
+ * (i.e., the ones I couldn't live without :-) All features which involve
+ * linking in substantial chunks of libc can be disabled.
+ *
+ * Although I don't really want to add new features to this program to
+ * keep it small, I *am* interested to receive bug fixes and ways to make
+ * it more portable.
+ *
+ * KNOWN BUGS:
+ * 1. ls -l of a directory doesn't give "total <blocks>" header
+ * 2. ls of a symlink to a directory doesn't list directory contents
+ * 3. hidden files can make column width too large
+ *
+ * NON-OPTIMAL BEHAVIOUR:
+ * 1. autowidth reads directories twice
+ * 2. if you do a short directory listing without filetype characters
+ * appended, there's no need to stat each one
+ * PORTABILITY:
+ * 1. requires lstat (BSD) - how do you do it without?
+ */
+
+enum {
+ TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */
+ COLUMN_GAP = 2, /* includes the file type char */
+};
+
+/************************************************************************/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+#ifdef CONFIG_SELINUX
+#include <fs_secure.h>
+#include <flask_util.h>
+#include <ss.h>
+#endif
+
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+#include <time.h>
+#endif
+
+#ifndef MAJOR
+#define MAJOR(dev) (((dev)>>8)&0xff)
+#define MINOR(dev) ((dev)&0xff)
+#endif
+
+/* what is the overall style of the listing */
+#define STYLE_AUTO (0)
+#define STYLE_COLUMNS (1U<<21) /* fill columns */
+#define STYLE_LONG (2U<<21) /* one record per line, extended info */
+#define STYLE_SINGLE (3U<<21) /* one record per line */
+
+#define STYLE_MASK STYLE_SINGLE
+#define STYLE_ONE_RECORD_FLAG STYLE_LONG
+
+/* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */
+/* what file information will be listed */
+#define LIST_INO (1U<<0)
+#define LIST_BLOCKS (1U<<1)
+#define LIST_MODEBITS (1U<<2)
+#define LIST_NLINKS (1U<<3)
+#define LIST_ID_NAME (1U<<4)
+#define LIST_ID_NUMERIC (1U<<5)
+#define LIST_CONTEXT (1U<<6)
+#define LIST_SIZE (1U<<7)
+#define LIST_DEV (1U<<8)
+#define LIST_DATE_TIME (1U<<9)
+#define LIST_FULLTIME (1U<<10)
+#define LIST_FILENAME (1U<<11)
+#define LIST_SYMLINK (1U<<12)
+#define LIST_FILETYPE (1U<<13)
+#define LIST_EXEC (1U<<14)
+
+#define LIST_MASK ((LIST_EXEC << 1) - 1)
+
+/* what files will be displayed */
+/* TODO -- We may be able to make DISP_NORMAL 0 to save a bit slot. */
+#define DISP_NORMAL (1U<<14) /* show normal filenames */
+#define DISP_DIRNAME (1U<<15) /* 2 or more items? label directories */
+#define DISP_HIDDEN (1U<<16) /* show filenames starting with . */
+#define DISP_DOT (1U<<17) /* show . and .. */
+#define DISP_NOLIST (1U<<18) /* show directory as itself, not contents */
+#define DISP_RECURSIVE (1U<<19) /* show directory and everything below it */
+#define DISP_ROWS (1U<<20) /* print across rows */
+
+#define DISP_MASK (((DISP_ROWS << 1) - 1) & ~(DISP_NORMAL - 1))
+
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+/* how will the files be sorted */
+#define SORT_ORDER_FORWARD 0 /* sort in reverse order */
+#define SORT_ORDER_REVERSE (1U<<27) /* sort in reverse order */
+
+#define SORT_NAME 0 /* sort by file name */
+#define SORT_SIZE (1U<<28) /* sort by file size */
+#define SORT_ATIME (2U<<28) /* sort by last access time */
+#define SORT_CTIME (3U<<28) /* sort by last change time */
+#define SORT_MTIME (4U<<28) /* sort by last modification time */
+#define SORT_VERSION (5U<<28) /* sort by version */
+#define SORT_EXT (6U<<28) /* sort by file name extension */
+#define SORT_DIR (7U<<28) /* sort by file or directory */
+
+#define SORT_MASK (7U<<28)
+#endif
+
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+/* which of the three times will be used */
+#define TIME_MOD 0
+#define TIME_CHANGE (1U<<23)
+#define TIME_ACCESS (1U<<24)
+
+#define TIME_MASK (3U<<23)
+#endif
+
+#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
+#define FOLLOW_LINKS (1U<<25)
+#endif
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+#define LS_DISP_HR (1U<<26)
+#endif
+
+#define LIST_SHORT (LIST_FILENAME)
+#define LIST_ISHORT (LIST_INO | LIST_FILENAME)
+#define LIST_LONG (LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
+ LIST_DATE_TIME | LIST_FILENAME | LIST_SYMLINK)
+#define LIST_ILONG (LIST_INO | LIST_LONG)
+
+#define SPLIT_DIR 1
+#define SPLIT_FILE 0
+#define SPLIT_SUBDIR 2
+
+#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
+#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
+
+#if defined(CONFIG_FEATURE_LS_FILETYPES) || defined(CONFIG_FEATURE_LS_COLOR)
+# define APPCHAR(mode) ("\0|\0\0/\0\0\0\0\0@\0=\0\0\0" [TYPEINDEX(mode)])
+#endif
+
+/* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */
+#ifdef CONFIG_FEATURE_LS_COLOR
+static int show_color = 0;
+
+#define COLOR(mode) ("\000\043\043\043\042\000\043\043"\
+ "\000\000\044\000\043\000\000\040" [TYPEINDEX(mode)])
+#define ATTR(mode) ("\00\00\01\00\01\00\01\00"\
+ "\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)])
+#endif
+
+/*
+ * a directory entry and its stat info are stored here
+ */
+struct dnode { /* the basic node */
+ char *name; /* the dir entry name */
+ char *fullname; /* the dir entry name */
+ struct stat dstat; /* the file stat info */
+#ifdef CONFIG_SELINUX
+ security_id_t sid;
+#endif
+ struct dnode *next; /* point at the next node */
+};
+typedef struct dnode dnode_t;
+
+static struct dnode **list_dir(const char *);
+static struct dnode **dnalloc(int);
+static int list_single(struct dnode *);
+
+static unsigned int all_fmt;
+
+#ifdef CONFIG_SELINUX
+static int is_flask_enabled_flag;
+#endif
+
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+static unsigned short terminal_width = TERMINAL_WIDTH;
+static unsigned short tabstops = COLUMN_GAP;
+#else
+#define tabstops COLUMN_GAP
+#define terminal_width TERMINAL_WIDTH
+#endif
+
+static int status = EXIT_SUCCESS;
+
+static struct dnode *my_stat(char *fullname, char *name)
+{
+ struct stat dstat;
+ struct dnode *cur;
+#ifdef CONFIG_SELINUX
+ security_id_t sid;
+#endif
+ int rc;
+
+#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
+ if (all_fmt & FOLLOW_LINKS) {
+#ifdef CONFIG_SELINUX
+ if(is_flask_enabled_flag)
+ rc = stat_secure(fullname, &dstat, &sid);
+ else
+#endif
+ rc = stat(fullname, &dstat);
+ if(rc)
+ {
+ bb_perror_msg("%s", fullname);
+ status = EXIT_FAILURE;
+ return 0;
+ }
+ } else
+#endif
+ {
+#ifdef CONFIG_SELINUX
+ if(is_flask_enabled_flag)
+ rc = lstat_secure(fullname, &dstat, &sid);
+ else
+#endif
+ rc = lstat(fullname, &dstat);
+ if(rc)
+ {
+ bb_perror_msg("%s", fullname);
+ status = EXIT_FAILURE;
+ return 0;
+ }
+ }
+
+ cur = (struct dnode *) xmalloc(sizeof(struct dnode));
+ cur->fullname = fullname;
+ cur->name = name;
+ cur->dstat = dstat;
+#ifdef CONFIG_SELINUX
+ cur->sid = sid;
+#endif
+ return cur;
+}
+
+/*----------------------------------------------------------------------*/
+#ifdef CONFIG_FEATURE_LS_COLOR
+static char fgcolor(mode_t mode)
+{
+ /* Check wheter the file is existing (if so, color it red!) */
+ if (errno == ENOENT) {
+ return '\037';
+ }
+ if (LIST_EXEC && S_ISREG(mode)
+ && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ return COLOR(0xF000); /* File is executable ... */
+ return COLOR(mode);
+}
+
+/*----------------------------------------------------------------------*/
+static char bgcolor(mode_t mode)
+{
+ if (LIST_EXEC && S_ISREG(mode)
+ && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ return ATTR(0xF000); /* File is executable ... */
+ return ATTR(mode);
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+#if defined(CONFIG_FEATURE_LS_FILETYPES) || defined(CONFIG_FEATURE_LS_COLOR)
+static char append_char(mode_t mode)
+{
+ if (!(all_fmt & LIST_FILETYPE))
+ return '\0';
+ if ((all_fmt & LIST_EXEC) && S_ISREG(mode)
+ && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ return '*';
+ return APPCHAR(mode);
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+
+#define countdirs(A,B) count_dirs((A), (B), 1)
+#define countsubdirs(A,B) count_dirs((A), (B), 0)
+
+static int count_dirs(struct dnode **dn, int nfiles, int notsubdirs)
+{
+ int i, dirs;
+
+ if (dn == NULL || nfiles < 1)
+ return (0);
+ dirs = 0;
+ for (i = 0; i < nfiles; i++) {
+ if (S_ISDIR(dn[i]->dstat.st_mode)
+ && (notsubdirs
+ || ((dn[i]->name[0] != '.')
+ || (dn[i]->name[1]
+ && ((dn[i]->name[1] != '.')
+ || dn[i]->name[2])))))
+ dirs++;
+ }
+ return (dirs);
+}
+
+static int countfiles(struct dnode **dnp)
+{
+ int nfiles;
+ struct dnode *cur;
+
+ if (dnp == NULL)
+ return (0);
+ nfiles = 0;
+ for (cur = dnp[0]; cur->next != NULL; cur = cur->next)
+ nfiles++;
+ nfiles++;
+ return (nfiles);
+}
+
+/* get memory to hold an array of pointers */
+static struct dnode **dnalloc(int num)
+{
+ struct dnode **p;
+
+ if (num < 1)
+ return (NULL);
+
+ p = (struct dnode **) xcalloc((size_t) num,
+ (size_t) (sizeof(struct dnode *)));
+ return (p);
+}
+
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+static void dfree(struct dnode **dnp)
+{
+ struct dnode *cur, *next;
+
+ if (dnp == NULL)
+ return;
+
+ cur = dnp[0];
+ while (cur != NULL) {
+ free(cur->fullname); /* free the filename */
+ next = cur->next;
+ free(cur); /* free the dnode */
+ cur = next;
+ }
+ free(dnp); /* free the array holding the dnode pointers */
+}
+#endif
+
+static struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which)
+{
+ int dncnt, i, d;
+ struct dnode **dnp;
+
+ if (dn == NULL || nfiles < 1)
+ return (NULL);
+
+ /* count how many dirs and regular files there are */
+ if (which == SPLIT_SUBDIR)
+ dncnt = countsubdirs(dn, nfiles);
+ else {
+ dncnt = countdirs(dn, nfiles); /* assume we are looking for dirs */
+ if (which == SPLIT_FILE)
+ dncnt = nfiles - dncnt; /* looking for files */
+ }
+
+ /* allocate a file array and a dir array */
+ dnp = dnalloc(dncnt);
+
+ /* copy the entrys into the file or dir array */
+ for (d = i = 0; i < nfiles; i++) {
+ if (S_ISDIR(dn[i]->dstat.st_mode)) {
+ if (which & (SPLIT_DIR|SPLIT_SUBDIR)) {
+ if ((which & SPLIT_DIR)
+ || ((dn[i]->name[0] != '.')
+ || (dn[i]->name[1]
+ && ((dn[i]->name[1] != '.')
+ || dn[i]->name[2])))) {
+ dnp[d++] = dn[i];
+ }
+ }
+ } else if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) {
+ dnp[d++] = dn[i];
+ }
+ }
+ return (dnp);
+}
+
+/*----------------------------------------------------------------------*/
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+static int sortcmp(struct dnode *d1, struct dnode *d2)
+{
+ unsigned int sort_opts = all_fmt & SORT_MASK;
+ int dif;
+
+ dif = 0; /* assume SORT_NAME */
+ if (sort_opts == SORT_SIZE) {
+ dif = (int) (d2->dstat.st_size - d1->dstat.st_size);
+ } else if (sort_opts == SORT_ATIME) {
+ dif = (int) (d2->dstat.st_atime - d1->dstat.st_atime);
+ } else if (sort_opts == SORT_CTIME) {
+ dif = (int) (d2->dstat.st_ctime - d1->dstat.st_ctime);
+ } else if (sort_opts == SORT_MTIME) {
+ dif = (int) (d2->dstat.st_mtime - d1->dstat.st_mtime);
+ } else if (sort_opts == SORT_DIR) {
+ dif = S_ISDIR(d2->dstat.st_mode) - S_ISDIR(d1->dstat.st_mode);
+ /* } else if (sort_opts == SORT_VERSION) { */
+ /* } else if (sort_opts == SORT_EXT) { */
+ }
+
+ if (dif == 0) {
+ /* sort by name- may be a tie_breaker for time or size cmp */
+#ifdef CONFIG_LOCALE_SUPPORT
+ dif = strcoll(d1->name, d2->name);
+#else
+ dif = strcmp(d1->name, d2->name);
+#endif
+ }
+
+ if (all_fmt & SORT_ORDER_REVERSE) {
+ dif = -dif;
+ }
+ return (dif);
+}
+
+/*----------------------------------------------------------------------*/
+static void shellsort(struct dnode **dn, int size)
+{
+ struct dnode *temp;
+ int gap, i, j;
+
+ /* shell short the array */
+ if (dn == NULL || size < 2)
+ return;
+
+ for (gap = size / 2; gap > 0; gap /= 2) {
+ for (i = gap; i < size; i++) {
+ for (j = i - gap; j >= 0; j -= gap) {
+ if (sortcmp(dn[j], dn[j + gap]) <= 0)
+ break;
+ /* they are out of order, swap them */
+ temp = dn[j];
+ dn[j] = dn[j + gap];
+ dn[j + gap] = temp;
+ }
+ }
+ }
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+static void showfiles(struct dnode **dn, int nfiles)
+{
+ int i, ncols, nrows, row, nc;
+ int column = 0;
+ int nexttab = 0;
+ int column_width = 0; /* for STYLE_LONG and STYLE_SINGLE not used */
+
+ if (dn == NULL || nfiles < 1)
+ return;
+
+ if (all_fmt & STYLE_ONE_RECORD_FLAG) {
+ ncols = 1;
+ } else {
+ /* find the longest file name- use that as the column width */
+ for (i = 0; i < nfiles; i++) {
+ int len = strlen(dn[i]->name) +
+#ifdef CONFIG_SELINUX
+ ((all_fmt & LIST_CONTEXT) ? 33 : 0) +
+#endif
+ ((all_fmt & LIST_INO) ? 8 : 0) +
+ ((all_fmt & LIST_BLOCKS) ? 5 : 0);
+ if (column_width < len)
+ column_width = len;
+ }
+ column_width += tabstops;
+ ncols = (int) (terminal_width / column_width);
+ }
+
+ if (ncols > 1) {
+ nrows = nfiles / ncols;
+ if ((nrows * ncols) < nfiles)
+ nrows++; /* round up fractionals */
+ } else {
+ nrows = nfiles;
+ ncols = 1;
+ }
+
+ for (row = 0; row < nrows; row++) {
+ for (nc = 0; nc < ncols; nc++) {
+ /* reach into the array based on the column and row */
+ i = (nc * nrows) + row; /* assume display by column */
+ if (all_fmt & DISP_ROWS)
+ i = (row * ncols) + nc; /* display across row */
+ if (i < nfiles) {
+ if (column > 0) {
+ nexttab -= column;
+ while (nexttab--) {
+ putchar(' ');
+ column++;
+ }
+ }
+ nexttab = column + column_width;
+ column += list_single(dn[i]);
+ }
+ }
+ putchar('\n');
+ column = 0;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+static void showdirs(struct dnode **dn, int ndirs)
+{
+ int i, nfiles;
+ struct dnode **subdnp;
+
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+ int dndirs;
+ struct dnode **dnd;
+#endif
+
+ if (dn == NULL || ndirs < 1)
+ return;
+
+ for (i = 0; i < ndirs; i++) {
+ if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) {
+ printf("\n%s:\n", dn[i]->fullname);
+ }
+ subdnp = list_dir(dn[i]->fullname);
+ nfiles = countfiles(subdnp);
+ if (nfiles > 0) {
+ /* list all files at this level */
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ shellsort(subdnp, nfiles);
+#endif
+ showfiles(subdnp, nfiles);
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+ if (all_fmt & DISP_RECURSIVE) {
+ /* recursive- list the sub-dirs */
+ dnd = splitdnarray(subdnp, nfiles, SPLIT_SUBDIR);
+ dndirs = countsubdirs(subdnp, nfiles);
+ if (dndirs > 0) {
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ shellsort(dnd, dndirs);
+#endif
+ showdirs(dnd, dndirs);
+ free(dnd); /* free the array of dnode pointers to the dirs */
+ }
+ }
+ dfree(subdnp); /* free the dnodes and the fullname mem */
+#endif
+ }
+ }
+}
+
+/*----------------------------------------------------------------------*/
+static struct dnode **list_dir(const char *path)
+{
+ struct dnode *dn, *cur, **dnp;
+ struct dirent *entry;
+ DIR *dir;
+ int i, nfiles;
+
+ if (path == NULL)
+ return (NULL);
+
+ dn = NULL;
+ nfiles = 0;
+ dir = opendir(path);
+ if (dir == NULL) {
+ bb_perror_msg("%s", path);
+ status = EXIT_FAILURE;
+ return (NULL); /* could not open the dir */
+ }
+ while ((entry = readdir(dir)) != NULL) {
+ char *fullname;
+
+ /* are we going to list the file- it may be . or .. or a hidden file */
+ if (entry->d_name[0] == '.') {
+ if ((entry->d_name[1] == 0 || (
+ entry->d_name[1] == '.'
+ && entry->d_name[2] == 0))
+ && !(all_fmt & DISP_DOT))
+ continue;
+ if (!(all_fmt & DISP_HIDDEN))
+ continue;
+ }
+ fullname = concat_path_file(path, entry->d_name);
+ cur = my_stat(fullname, strrchr(fullname, '/') + 1);
+ if (!cur)
+ continue;
+ cur->next = dn;
+ dn = cur;
+ nfiles++;
+ }
+ closedir(dir);
+
+ /* now that we know how many files there are
+ ** allocate memory for an array to hold dnode pointers
+ */
+ if (dn == NULL)
+ return (NULL);
+ dnp = dnalloc(nfiles);
+ for (i = 0, cur = dn; i < nfiles; i++) {
+ dnp[i] = cur; /* save pointer to node in array */
+ cur = cur->next;
+ }
+
+ return (dnp);
+}
+
+/*----------------------------------------------------------------------*/
+static int list_single(struct dnode *dn)
+{
+ int i, column = 0;
+
+#ifdef CONFIG_FEATURE_LS_USERNAME
+ char scratch[16];
+#endif
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+ char *filetime;
+ time_t ttime, age;
+#endif
+#if defined(CONFIG_FEATURE_LS_FILETYPES) || defined (CONFIG_FEATURE_LS_COLOR)
+ struct stat info;
+ char append;
+#endif
+
+ if (dn->fullname == NULL)
+ return (0);
+
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+ ttime = dn->dstat.st_mtime; /* the default time */
+ if (all_fmt & TIME_ACCESS)
+ ttime = dn->dstat.st_atime;
+ if (all_fmt & TIME_CHANGE)
+ ttime = dn->dstat.st_ctime;
+ filetime = ctime(&ttime);
+#endif
+#ifdef CONFIG_FEATURE_LS_FILETYPES
+ append = append_char(dn->dstat.st_mode);
+#endif
+
+ for (i = 0; i <= 31; i++) {
+ switch (all_fmt & (1 << i)) {
+ case LIST_INO:
+ column += printf("%7ld ", (long int) dn->dstat.st_ino);
+ break;
+ case LIST_BLOCKS:
+#if _FILE_OFFSET_BITS == 64
+ column += printf("%4lld ", dn->dstat.st_blocks >> 1);
+#else
+ column += printf("%4ld ", dn->dstat.st_blocks >> 1);
+#endif
+ break;
+ case LIST_MODEBITS:
+ column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
+ break;
+ case LIST_NLINKS:
+ column += printf("%4ld ", (long) dn->dstat.st_nlink);
+ break;
+ case LIST_ID_NAME:
+#ifdef CONFIG_FEATURE_LS_USERNAME
+ my_getpwuid(scratch, dn->dstat.st_uid);
+ printf("%-8.8s ", scratch);
+ my_getgrgid(scratch, dn->dstat.st_gid);
+ printf("%-8.8s", scratch);
+ column += 17;
+ break;
+#endif
+ case LIST_ID_NUMERIC:
+ column += printf("%-8d %-8d", dn->dstat.st_uid, dn->dstat.st_gid);
+ break;
+ case LIST_SIZE:
+ case LIST_DEV:
+ if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) {
+ column += printf("%4d, %3d ", (int) MAJOR(dn->dstat.st_rdev),
+ (int) MINOR(dn->dstat.st_rdev));
+ } else {
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+ if (all_fmt & LS_DISP_HR) {
+ column += printf("%9s ",
+ make_human_readable_str(dn->dstat.st_size, 1, 0));
+ } else
+#endif
+ {
+#if _FILE_OFFSET_BITS == 64
+ column += printf("%9lld ", (long long) dn->dstat.st_size);
+#else
+ column += printf("%9ld ", dn->dstat.st_size);
+#endif
+ }
+ }
+ break;
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+ case LIST_FULLTIME:
+ case LIST_DATE_TIME:
+ if (all_fmt & LIST_FULLTIME) {
+ printf("%24.24s ", filetime);
+ column += 25;
+ break;
+ }
+ age = time(NULL) - ttime;
+ printf("%6.6s ", filetime + 4);
+ if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) {
+ /* hh:mm if less than 6 months old */
+ printf("%5.5s ", filetime + 11);
+ } else {
+ printf(" %4.4s ", filetime + 20);
+ }
+ column += 13;
+ break;
+#endif
+#ifdef CONFIG_SELINUX
+ case LIST_CONTEXT:
+ {
+ char context[64];
+ int len = sizeof(context);
+ if(security_sid_to_context(dn->sid, context, &len))
+ {
+ strcpy(context, "unknown");
+ len = 7;
+ }
+ printf("%-32s ", context);
+ column += MAX(33, len);
+ }
+ break;
+#endif
+ case LIST_FILENAME:
+#ifdef CONFIG_FEATURE_LS_COLOR
+ errno = 0;
+ if (show_color && !lstat(dn->fullname, &info)) {
+ printf("\033[%d;%dm", bgcolor(info.st_mode),
+ fgcolor(info.st_mode));
+ }
+#endif
+ column += printf("%s", dn->name);
+#ifdef CONFIG_FEATURE_LS_COLOR
+ if (show_color) {
+ printf("\033[0m");
+ }
+#endif
+ break;
+ case LIST_SYMLINK:
+ if (S_ISLNK(dn->dstat.st_mode)) {
+ char *lpath = xreadlink(dn->fullname);
+
+ if (lpath) {
+ printf(" -> ");
+#if defined(CONFIG_FEATURE_LS_FILETYPES) || defined (CONFIG_FEATURE_LS_COLOR)
+ if (!stat(dn->fullname, &info)) {
+ append = append_char(info.st_mode);
+ }
+#endif
+#ifdef CONFIG_FEATURE_LS_COLOR
+ if (show_color) {
+ errno = 0;
+ printf("\033[%d;%dm", bgcolor(info.st_mode),
+ fgcolor(info.st_mode));
+ }
+#endif
+ column += printf("%s", lpath) + 4;
+#ifdef CONFIG_FEATURE_LS_COLOR
+ if (show_color) {
+ printf("\033[0m");
+ }
+#endif
+ free(lpath);
+ }
+ }
+ break;
+#ifdef CONFIG_FEATURE_LS_FILETYPES
+ case LIST_FILETYPE:
+ if (append != '\0') {
+ printf("%1c", append);
+ column++;
+ }
+ break;
+#endif
+ }
+ }
+
+ return column;
+}
+
+/*----------------------------------------------------------------------*/
+
+static const char ls_opts[] = "1AaCdgilnsx"
+#ifdef CONFIG_FEATURE_LS_FILETYPES
+ "Fp"
+#endif
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+ "R"
+#endif
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ "rSvX"
+#endif
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+ "ecut"
+#endif
+#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
+ "L"
+#endif
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+ "h"
+#endif
+ "k"
+#ifdef CONFIG_SELINUX
+ "K"
+#endif
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+ "T:w:"
+#endif
+ ;
+
+#define LIST_MASK_TRIGGER LIST_SHORT
+#define STYLE_MASK_TRIGGER STYLE_MASK
+#define SORT_MASK_TRIGGER SORT_MASK
+#define DISP_MASK_TRIGGER DISP_ROWS
+#define TIME_MASK_TRIGGER TIME_MASK
+
+static const unsigned opt_flags[] = {
+ LIST_SHORT | STYLE_SINGLE, /* 1 */
+ DISP_HIDDEN, /* A */
+ DISP_HIDDEN | DISP_DOT, /* a */
+ LIST_SHORT | STYLE_COLUMNS, /* C */
+ DISP_NOLIST, /* d */
+ 0, /* g - ingored */
+ LIST_INO, /* i */
+ LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */
+ LIST_ID_NUMERIC, /* n */
+ LIST_BLOCKS, /* s */
+ DISP_ROWS, /* x */
+#ifdef CONFIG_FEATURE_LS_FILETYPES
+ LIST_FILETYPE | LIST_EXEC, /* F */
+ LIST_FILETYPE, /* p */
+#endif
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+ DISP_RECURSIVE, /* R */
+#endif
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ SORT_ORDER_REVERSE, /* r */
+ SORT_SIZE, /* S */
+ SORT_VERSION, /* v */
+ SORT_EXT, /* v */
+#endif
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+ LIST_FULLTIME, /* e */
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ TIME_CHANGE | SORT_CTIME, /* c */
+#else
+ TIME_CHANGE, /* c */
+#endif
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ TIME_ACCESS | SORT_ATIME, /* u */
+#else
+ TIME_ACCESS, /* u */
+#endif
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ SORT_MTIME, /* t */
+#else
+ 0, /* t - ignored -- is this correct? */
+#endif
+#endif
+#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
+ FOLLOW_LINKS, /* L */
+#endif
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+LS_DISP_HR, /* h */
+#endif
+#ifndef CONFIG_SELINUX
+ 0, /* k - ingored */
+#else
+ LIST_CONTEXT, /* k */
+ LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */
+#endif
+};
+
+
+/*----------------------------------------------------------------------*/
+
+extern int ls_main(int argc, char **argv)
+{
+ struct dnode **dnf, **dnd;
+ int dnfiles, dndirs;
+ struct dnode *dn, *cur, **dnp;
+ int i, nfiles;
+ int opt;
+ int oi, ac;
+ char **av;
+#ifdef CONFIG_SELINUX
+ is_flask_enabled_flag = is_flask_enabled();
+#endif
+
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+ struct winsize win = { 0, 0, 0, 0 };
+#endif
+
+ all_fmt = LIST_SHORT | DISP_NORMAL | STYLE_AUTO
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+ | TIME_MOD
+#endif
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ | SORT_NAME | SORT_ORDER_FORWARD
+#endif
+ ;
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+ ioctl(fileno(stdout), TIOCGWINSZ, &win);
+ if (win.ws_col > 0)
+ terminal_width = win.ws_col - 1;
+#endif
+ nfiles = 0;
+
+#ifdef CONFIG_FEATURE_LS_COLOR
+ if (isatty(fileno(stdout)))
+ show_color = 1;
+#endif
+
+ /* process options */
+ while ((opt = getopt(argc, argv, ls_opts)) > 0) {
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+ if (opt == 'T') {
+ tabstops = atoi(optarg);
+ continue;
+ }
+ if (opt == 'w') {
+ terminal_width = atoi(optarg);
+ continue;
+ }
+ if (opt == ':') {
+ goto print_usage_message;
+ }
+#endif
+ {
+ unsigned int flags;
+ const char *p = strchr(ls_opts, opt);
+ if (!p) { /* shouldn't be necessary */
+ goto print_usage_message;
+ }
+ flags = opt_flags[(int)(p - ls_opts)];
+ if (flags & LIST_MASK_TRIGGER) {
+ all_fmt &= ~LIST_MASK;
+ }
+ if (flags & STYLE_MASK_TRIGGER) {
+ all_fmt &= ~STYLE_MASK;
+ }
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ if (flags & SORT_MASK_TRIGGER) {
+ all_fmt &= ~SORT_MASK;
+ }
+#endif
+ if (flags & DISP_MASK_TRIGGER) {
+ all_fmt &= ~DISP_MASK;
+ }
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+ if (flags & TIME_MASK_TRIGGER) {
+ all_fmt &= ~TIME_MASK;
+ }
+#endif
+ if (flags & LIST_CONTEXT) {
+ all_fmt |= STYLE_SINGLE;
+ }
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+ if (opt == 'l') {
+ all_fmt &= ~LS_DISP_HR;
+ }
+#endif
+ all_fmt |= flags;
+ }
+ }
+
+
+ /* sort out which command line options take precedence */
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+ if (all_fmt & DISP_NOLIST)
+ all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */
+#endif
+#if defined (CONFIG_FEATURE_LS_TIMESTAMPS) && defined (CONFIG_FEATURE_LS_SORTFILES)
+ if (all_fmt & TIME_CHANGE)
+ all_fmt = (all_fmt & ~SORT_MASK) | SORT_CTIME;
+ if (all_fmt & TIME_ACCESS)
+ all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME;
+#endif
+ if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* only for long list */
+ all_fmt &= ~(LIST_ID_NUMERIC|LIST_FULLTIME|LIST_ID_NAME|LIST_ID_NUMERIC);
+#ifdef CONFIG_FEATURE_LS_USERNAME
+ if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC))
+ all_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */
+#endif
+
+ /* choose a display format */
+ if ((all_fmt & STYLE_MASK) == STYLE_AUTO)
+#if STYLE_AUTO != 0
+ all_fmt = (all_fmt & ~STYLE_MASK)
+ | (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE);
+#else
+ all_fmt |= (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE);
+#endif
+
+ /*
+ * when there are no cmd line args we have to supply a default "." arg.
+ * we will create a second argv array, "av" that will hold either
+ * our created "." arg, or the real cmd line args. The av array
+ * just holds the pointers- we don't move the date the pointers
+ * point to.
+ */
+ ac = argc - optind; /* how many cmd line args are left */
+ if (ac < 1) {
+ av = (char **) xcalloc((size_t) 1, (size_t) (sizeof(char *)));
+ av[0] = bb_xstrdup(".");
+ ac = 1;
+ } else {
+ av = (char **) xcalloc((size_t) ac, (size_t) (sizeof(char *)));
+ for (oi = 0; oi < ac; oi++) {
+ av[oi] = argv[optind++]; /* copy pointer to real cmd line arg */
+ }
+ }
+
+ /* now, everything is in the av array */
+ if (ac > 1)
+ all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */
+
+ /* stuff the command line file names into an dnode array */
+ dn = NULL;
+ for (oi = 0; oi < ac; oi++) {
+ char *fullname = bb_xstrdup(av[oi]);
+
+ cur = my_stat(fullname, fullname);
+ if (!cur)
+ continue;
+ cur->next = dn;
+ dn = cur;
+ nfiles++;
+ }
+
+ /* now that we know how many files there are
+ ** allocate memory for an array to hold dnode pointers
+ */
+ dnp = dnalloc(nfiles);
+ for (i = 0, cur = dn; i < nfiles; i++) {
+ dnp[i] = cur; /* save pointer to node in array */
+ cur = cur->next;
+ }
+
+
+ if (all_fmt & DISP_NOLIST) {
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ shellsort(dnp, nfiles);
+#endif
+ if (nfiles > 0)
+ showfiles(dnp, nfiles);
+ } else {
+ dnd = splitdnarray(dnp, nfiles, SPLIT_DIR);
+ dnf = splitdnarray(dnp, nfiles, SPLIT_FILE);
+ dndirs = countdirs(dnp, nfiles);
+ dnfiles = nfiles - dndirs;
+ if (dnfiles > 0) {
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ shellsort(dnf, dnfiles);
+#endif
+ showfiles(dnf, dnfiles);
+ }
+ if (dndirs > 0) {
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+ shellsort(dnd, dndirs);
+#endif
+ showdirs(dnd, dndirs);
+ }
+ }
+ return (status);
+
+ print_usage_message:
+ bb_show_usage();
+}
diff --git a/release/src/router/busybox/coreutils/md5sum.c b/release/src/router/busybox/coreutils/md5sum.c
new file mode 100644
index 00000000..c0294f4c
--- /dev/null
+++ b/release/src/router/busybox/coreutils/md5sum.c
@@ -0,0 +1,1102 @@
+/* md5sum.c - Compute MD5 checksum of files or strings according to the
+ * definition of MD5 in RFC 1321 from April 1992.
+ * Copyright (C) 1995-1999 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu> */
+/* Hacked to work with BusyBox by Alfred M. Szmidt <ams@trillian.itslinux.org> */
+
+/*
+ * June 29, 2001 Manuel Novoa III
+ *
+ * Added MD5SUM_SIZE_VS_SPEED configuration option.
+ *
+ * Current valid values, with data from my system for comparison, are:
+ * (using uClibc and running on linux-2.4.4.tar.bz2)
+ * user times (sec) text size (386)
+ * 0 (fastest) 1.1 6144
+ * 1 1.4 5392
+ * 2 3.0 5088
+ * 3 (smallest) 5.1 4912
+ */
+
+#define MD5SUM_SIZE_VS_SPEED 2
+
+/**********************************************************************/
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <endian.h>
+#include <sys/types.h>
+#if defined HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#include "busybox.h"
+
+/* For some silly reason, this file uses backwards TRUE and FALSE conventions */
+#undef TRUE
+#undef FALSE
+#define FALSE ((int) 1)
+#define TRUE ((int) 0)
+
+//----------------------------------------------------------------------------
+//--------md5.c
+//----------------------------------------------------------------------------
+
+/* md5.c - Functions to compute MD5 message digest of files or memory blocks
+ * according to the definition of MD5 in RFC 1321 from April 1992.
+ */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
+
+//----------------------------------------------------------------------------
+//--------md5.h
+//----------------------------------------------------------------------------
+
+/* md5.h - Declaration of functions and data types used for MD5 sum
+ computing library functions. */
+
+typedef u_int32_t md5_uint32;
+
+/* Structure to save state of computation between the single steps. */
+struct md5_ctx {
+ md5_uint32 A;
+ md5_uint32 B;
+ md5_uint32 C;
+ md5_uint32 D;
+
+ md5_uint32 total[2];
+ md5_uint32 buflen;
+ char buffer[128];
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+ (RFC 1321, 3.3: Step 3) */
+static void md5_init_ctx __P((struct md5_ctx * ctx));
+
+/* Starting with the result of former calls of this function (or the
+ initialization function update the context for the next LEN bytes
+ starting at BUFFER.
+ It is necessary that LEN is a multiple of 64!!! */
+static void md5_process_block __P((const void *buffer, size_t len,
+ struct md5_ctx * ctx));
+
+/* Starting with the result of former calls of this function (or the
+ initialization function update the context for the next LEN bytes
+ starting at BUFFER.
+ It is NOT required that LEN is a multiple of 64. */
+static void md5_process_bytes __P((const void *buffer, size_t len,
+ struct md5_ctx * ctx));
+
+/* Process the remaining bytes in the buffer and put result from CTX
+ in first 16 bytes following RESBUF. The result is always in little
+ endian byte order, so that a byte-wise output yields to the wanted
+ ASCII representation of the message digest.
+
+ IMPORTANT: On some systems it is required that RESBUF is correctly
+ aligned for a 32 bits value. */
+static void *md5_finish_ctx __P((struct md5_ctx * ctx, void *resbuf));
+
+
+
+
+/* Compute MD5 message digest for bytes read from STREAM. The
+ resulting message digest number will be written into the 16 bytes
+ beginning at RESBLOCK. */
+static int md5_stream __P((FILE * stream, void *resblock));
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
+ result is always in little endian byte order, so that a byte-wise
+ output yields to the wanted ASCII representation of the message
+ digest. */
+static void *md5_buffer __P((const char *buffer, size_t len, void *resblock));
+
+//----------------------------------------------------------------------------
+//--------end of md5.h
+//----------------------------------------------------------------------------
+
+/* Handle endian-ness */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define SWAP(n) (n)
+#else
+#define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24))
+#endif
+
+
+
+#if MD5SUM_SIZE_VS_SPEED == 0
+/* This array contains the bytes used to pad the buffer to the next
+ 64-byte boundary. (RFC 1321, 3.1: Step 1) */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
+#endif
+
+/* Initialize structure containing state of computation.
+ (RFC 1321, 3.3: Step 3) */
+void md5_init_ctx(struct md5_ctx *ctx)
+{
+ ctx->A = 0x67452301;
+ ctx->B = 0xefcdab89;
+ ctx->C = 0x98badcfe;
+ ctx->D = 0x10325476;
+
+ ctx->total[0] = ctx->total[1] = 0;
+ ctx->buflen = 0;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+ prolog according to the standard and write the result to RESBUF.
+
+ IMPORTANT: On some systems it is required that RESBUF is correctly
+ aligned for a 32 bits value. */
+static void *md5_finish_ctx(struct md5_ctx *ctx, void *resbuf)
+{
+ /* Take yet unprocessed bytes into account. */
+ md5_uint32 bytes = ctx->buflen;
+ size_t pad;
+
+ /* Now count remaining bytes. */
+ ctx->total[0] += bytes;
+ if (ctx->total[0] < bytes)
+ ++ctx->total[1];
+
+ pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+#if MD5SUM_SIZE_VS_SPEED > 0
+ memset(&ctx->buffer[bytes], 0, pad);
+ ctx->buffer[bytes] = 0x80;
+#else
+ memcpy(&ctx->buffer[bytes], fillbuf, pad);
+#endif
+
+ /* Put the 64-bit file length in *bits* at the end of the buffer. */
+ *(md5_uint32 *) & ctx->buffer[bytes + pad] = SWAP(ctx->total[0] << 3);
+ *(md5_uint32 *) & ctx->buffer[bytes + pad + 4] =
+ SWAP(((ctx->total[1] << 3) | (ctx->total[0] >> 29)));
+
+ /* Process last bytes. */
+ md5_process_block(ctx->buffer, bytes + pad + 8, ctx);
+
+/* Put result from CTX in first 16 bytes following RESBUF. The result is
+ always in little endian byte order, so that a byte-wise output yields
+ to the wanted ASCII representation of the message digest.
+
+ IMPORTANT: On some systems it is required that RESBUF is correctly
+ aligned for a 32 bits value. */
+ ((md5_uint32 *) resbuf)[0] = SWAP(ctx->A);
+ ((md5_uint32 *) resbuf)[1] = SWAP(ctx->B);
+ ((md5_uint32 *) resbuf)[2] = SWAP(ctx->C);
+ ((md5_uint32 *) resbuf)[3] = SWAP(ctx->D);
+
+ return resbuf;
+}
+
+/* Compute MD5 message digest for bytes read from STREAM. The
+ resulting message digest number will be written into the 16 bytes
+ beginning at RESBLOCK. */
+static int md5_stream(FILE * stream, void *resblock)
+{
+ /* Important: BLOCKSIZE must be a multiple of 64. */
+ static const int BLOCKSIZE = 4096;
+ struct md5_ctx ctx;
+ char buffer[BLOCKSIZE + 72];
+ size_t sum;
+
+ /* Initialize the computation context. */
+ md5_init_ctx(&ctx);
+
+ /* Iterate over full file contents. */
+ while (1) {
+ /* We read the file in blocks of BLOCKSIZE bytes. One call of the
+ computation function processes the whole buffer so that with the
+ next round of the loop another block can be read. */
+ size_t n;
+
+ sum = 0;
+
+ /* Read block. Take care for partial reads. */
+ do {
+ n = fread(buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+ sum += n;
+ }
+ while (sum < BLOCKSIZE && n != 0);
+ if (n == 0 && ferror(stream))
+ return 1;
+
+ /* If end of file is reached, end the loop. */
+ if (n == 0)
+ break;
+
+ /* Process buffer with BLOCKSIZE bytes. Note that
+ BLOCKSIZE % 64 == 0
+ */
+ md5_process_block(buffer, BLOCKSIZE, &ctx);
+ }
+
+ /* Add the last bytes if necessary. */
+ if (sum > 0)
+ md5_process_bytes(buffer, sum, &ctx);
+
+ /* Construct result in desired memory. */
+ md5_finish_ctx(&ctx, resblock);
+ return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
+ result is always in little endian byte order, so that a byte-wise
+ output yields to the wanted ASCII representation of the message
+ digest. */
+static void *md5_buffer(const char *buffer, size_t len, void *resblock)
+{
+ struct md5_ctx ctx;
+
+ /* Initialize the computation context. */
+ md5_init_ctx(&ctx);
+
+ /* Process whole buffer but last len % 64 bytes. */
+ md5_process_bytes(buffer, len, &ctx);
+
+ /* Put result in desired memory area. */
+ return md5_finish_ctx(&ctx, resblock);
+}
+
+static void md5_process_bytes(const void *buffer, size_t len,
+ struct md5_ctx *ctx)
+{
+ /* When we already have some bits in our internal buffer concatenate
+ both inputs first. */
+ if (ctx->buflen != 0) {
+ size_t left_over = ctx->buflen;
+ size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+ memcpy(&ctx->buffer[left_over], buffer, add);
+ ctx->buflen += add;
+
+ if (left_over + add > 64) {
+ md5_process_block(ctx->buffer, (left_over + add) & ~63, ctx);
+ /* The regions in the following copy operation cannot overlap. */
+ memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+ (left_over + add) & 63);
+ ctx->buflen = (left_over + add) & 63;
+ }
+
+ buffer = (const char *) buffer + add;
+ len -= add;
+ }
+
+ /* Process available complete blocks. */
+ if (len > 64) {
+ md5_process_block(buffer, len & ~63, ctx);
+ buffer = (const char *) buffer + (len & ~63);
+ len &= 63;
+ }
+
+ /* Move remaining bytes in internal buffer. */
+ if (len > 0) {
+ memcpy(ctx->buffer, buffer, len);
+ ctx->buflen = len;
+ }
+}
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+ and defined in the RFC 1321. The first function is a little bit optimized
+ (as found in Colin Plumbs public domain implementation). */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+ It is assumed that LEN % 64 == 0. */
+static void md5_process_block(const void *buffer, size_t len,
+ struct md5_ctx *ctx)
+{
+ md5_uint32 correct_words[16];
+ const md5_uint32 *words = buffer;
+ size_t nwords = len / sizeof(md5_uint32);
+ const md5_uint32 *endp = words + nwords;
+
+#if MD5SUM_SIZE_VS_SPEED > 0
+ static const md5_uint32 C_array[] = {
+ /* round 1 */
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+ /* round 2 */
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+ /* round 3 */
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ /* round 4 */
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+ };
+
+ static const char P_array[] = {
+#if MD5SUM_SIZE_VS_SPEED > 1
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
+#endif
+ 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
+ 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
+ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
+ };
+
+#if MD5SUM_SIZE_VS_SPEED > 1
+ static const char S_array[] = {
+ 7, 12, 17, 22,
+ 5, 9, 14, 20,
+ 4, 11, 16, 23,
+ 6, 10, 15, 21
+ };
+#endif
+#endif
+
+ md5_uint32 A = ctx->A;
+ md5_uint32 B = ctx->B;
+ md5_uint32 C = ctx->C;
+ md5_uint32 D = ctx->D;
+
+ /* First increment the byte count. RFC 1321 specifies the possible
+ length of the file up to 2^64 bits. Here we only compute the
+ number of bytes. Do a double word increment. */
+ ctx->total[0] += len;
+ if (ctx->total[0] < len)
+ ++ctx->total[1];
+
+ /* Process all bytes in the buffer with 64 bytes in each round of
+ the loop. */
+ while (words < endp) {
+ md5_uint32 *cwp = correct_words;
+ md5_uint32 A_save = A;
+ md5_uint32 B_save = B;
+ md5_uint32 C_save = C;
+ md5_uint32 D_save = D;
+
+#if MD5SUM_SIZE_VS_SPEED > 1
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+ const md5_uint32 *pc;
+ const char *pp;
+ const char *ps;
+ int i;
+ md5_uint32 temp;
+
+ for (i = 0; i < 16; i++) {
+ cwp[i] = SWAP(words[i]);
+ }
+ words += 16;
+
+#if MD5SUM_SIZE_VS_SPEED > 2
+ pc = C_array;
+ pp = P_array;
+ ps = S_array - 4;
+
+ for (i = 0; i < 64; i++) {
+ if ((i & 0x0f) == 0)
+ ps += 4;
+ temp = A;
+ switch (i >> 4) {
+ case 0:
+ temp += FF(B, C, D);
+ break;
+ case 1:
+ temp += FG(B, C, D);
+ break;
+ case 2:
+ temp += FH(B, C, D);
+ break;
+ case 3:
+ temp += FI(B, C, D);
+ }
+ temp += cwp[(int) (*pp++)] + *pc++;
+ CYCLIC(temp, ps[i & 3]);
+ temp += B;
+ A = D;
+ D = C;
+ C = B;
+ B = temp;
+ }
+#else
+ pc = C_array;
+ pp = P_array;
+ ps = S_array;
+
+ for (i = 0; i < 16; i++) {
+ temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+ CYCLIC(temp, ps[i & 3]);
+ temp += B;
+ A = D;
+ D = C;
+ C = B;
+ B = temp;
+ }
+
+ ps += 4;
+ for (i = 0; i < 16; i++) {
+ temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+ CYCLIC(temp, ps[i & 3]);
+ temp += B;
+ A = D;
+ D = C;
+ C = B;
+ B = temp;
+ }
+ ps += 4;
+ for (i = 0; i < 16; i++) {
+ temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+ CYCLIC(temp, ps[i & 3]);
+ temp += B;
+ A = D;
+ D = C;
+ C = B;
+ B = temp;
+ }
+ ps += 4;
+ for (i = 0; i < 16; i++) {
+ temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+ CYCLIC(temp, ps[i & 3]);
+ temp += B;
+ A = D;
+ D = C;
+ C = B;
+ B = temp;
+ }
+
+#endif
+#else
+ /* First round: using the given function, the context and a constant
+ the next context is computed. Because the algorithms processing
+ unit is a 32-bit word and it is determined to work on words in
+ little endian byte order we perhaps have to change the byte order
+ before the computation. To reduce the work for the next steps
+ we store the swapped words in the array CORRECT_WORDS. */
+
+#define OP(a, b, c, d, s, T) \
+ do \
+ { \
+ a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
+ ++words; \
+ CYCLIC (a, s); \
+ a += b; \
+ } \
+ while (0)
+
+ /* It is unfortunate that C does not provide an operator for
+ cyclic rotation. Hope the C compiler is smart enough. */
+ /* gcc 2.95.4 seems to be --aaronl */
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+ /* Before we start, one word to the strange constants.
+ They are defined in RFC 1321 as
+
+ T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+ */
+
+#if MD5SUM_SIZE_VS_SPEED == 1
+ const md5_uint32 *pc;
+ const char *pp;
+ int i;
+#endif
+
+ /* Round 1. */
+#if MD5SUM_SIZE_VS_SPEED == 1
+ pc = C_array;
+ for (i = 0; i < 4; i++) {
+ OP(A, B, C, D, 7, *pc++);
+ OP(D, A, B, C, 12, *pc++);
+ OP(C, D, A, B, 17, *pc++);
+ OP(B, C, D, A, 22, *pc++);
+ }
+#else
+ OP(A, B, C, D, 7, 0xd76aa478);
+ OP(D, A, B, C, 12, 0xe8c7b756);
+ OP(C, D, A, B, 17, 0x242070db);
+ OP(B, C, D, A, 22, 0xc1bdceee);
+ OP(A, B, C, D, 7, 0xf57c0faf);
+ OP(D, A, B, C, 12, 0x4787c62a);
+ OP(C, D, A, B, 17, 0xa8304613);
+ OP(B, C, D, A, 22, 0xfd469501);
+ OP(A, B, C, D, 7, 0x698098d8);
+ OP(D, A, B, C, 12, 0x8b44f7af);
+ OP(C, D, A, B, 17, 0xffff5bb1);
+ OP(B, C, D, A, 22, 0x895cd7be);
+ OP(A, B, C, D, 7, 0x6b901122);
+ OP(D, A, B, C, 12, 0xfd987193);
+ OP(C, D, A, B, 17, 0xa679438e);
+ OP(B, C, D, A, 22, 0x49b40821);
+#endif
+
+ /* For the second to fourth round we have the possibly swapped words
+ in CORRECT_WORDS. Redefine the macro to take an additional first
+ argument specifying the function to use. */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T) \
+ do \
+ { \
+ a += f (b, c, d) + correct_words[k] + T; \
+ CYCLIC (a, s); \
+ a += b; \
+ } \
+ while (0)
+
+ /* Round 2. */
+#if MD5SUM_SIZE_VS_SPEED == 1
+ pp = P_array;
+ for (i = 0; i < 4; i++) {
+ OP(FG, A, B, C, D, (int) (*pp++), 5, *pc++);
+ OP(FG, D, A, B, C, (int) (*pp++), 9, *pc++);
+ OP(FG, C, D, A, B, (int) (*pp++), 14, *pc++);
+ OP(FG, B, C, D, A, (int) (*pp++), 20, *pc++);
+ }
+#else
+ OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
+ OP(FG, D, A, B, C, 6, 9, 0xc040b340);
+ OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
+ OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
+ OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
+ OP(FG, D, A, B, C, 10, 9, 0x02441453);
+ OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
+ OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
+ OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
+ OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
+ OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
+ OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
+ OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
+ OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
+ OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
+ OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+#endif
+
+ /* Round 3. */
+#if MD5SUM_SIZE_VS_SPEED == 1
+ for (i = 0; i < 4; i++) {
+ OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++);
+ OP(FH, D, A, B, C, (int) (*pp++), 11, *pc++);
+ OP(FH, C, D, A, B, (int) (*pp++), 16, *pc++);
+ OP(FH, B, C, D, A, (int) (*pp++), 23, *pc++);
+ }
+#else
+ OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
+ OP(FH, D, A, B, C, 8, 11, 0x8771f681);
+ OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
+ OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
+ OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
+ OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
+ OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
+ OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
+ OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
+ OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
+ OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
+ OP(FH, B, C, D, A, 6, 23, 0x04881d05);
+ OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
+ OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
+ OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+ OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
+#endif
+
+ /* Round 4. */
+#if MD5SUM_SIZE_VS_SPEED == 1
+ for (i = 0; i < 4; i++) {
+ OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++);
+ OP(FI, D, A, B, C, (int) (*pp++), 10, *pc++);
+ OP(FI, C, D, A, B, (int) (*pp++), 15, *pc++);
+ OP(FI, B, C, D, A, (int) (*pp++), 21, *pc++);
+ }
+#else
+ OP(FI, A, B, C, D, 0, 6, 0xf4292244);
+ OP(FI, D, A, B, C, 7, 10, 0x432aff97);
+ OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
+ OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
+ OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
+ OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
+ OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
+ OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
+ OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
+ OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+ OP(FI, C, D, A, B, 6, 15, 0xa3014314);
+ OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
+ OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
+ OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
+ OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
+ OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
+#endif
+#endif
+
+ /* Add the starting values of the context. */
+ A += A_save;
+ B += B_save;
+ C += C_save;
+ D += D_save;
+ }
+
+ /* Put checksum in context given as argument. */
+ ctx->A = A;
+ ctx->B = B;
+ ctx->C = C;
+ ctx->D = D;
+}
+
+//----------------------------------------------------------------------------
+//--------end of md5.c
+//----------------------------------------------------------------------------
+
+#define ISWHITE(c) ((c) == ' ' || (c) == '\t')
+#define ISXDIGIT(c) (isxdigit (c))
+
+/* The minimum length of a valid digest line in a file produced
+ by `md5sum FILE' and read by `md5sum -c'. This length does
+ not include any newline character at the end of a line. */
+static const int MIN_DIGEST_LINE_LENGTH = 35; /* 32 - message digest length
+ 2 - blank and binary indicator
+ 1 - minimum filename length */
+
+static int have_read_stdin; /* Nonzero if any of the files read were
+ the standard input. */
+
+static int status_only = 0; /* With -c, don't generate any output.
+ The exit code indicates success or failure */
+static int warn = 0; /* With -w, print a message to standard error warning
+ about each improperly formatted MD5 checksum line */
+
+static int split_3(char *s, size_t s_len, unsigned char **u, char **w)
+{
+ size_t i = 0;
+ int escaped_filename = 0;
+
+ while (ISWHITE(s[i]))
+ ++i;
+
+ /* The line must have at least 35 (36 if the first is a backslash)
+ more characters to contain correct message digest information.
+ Ignore this line if it is too short. */
+ if (!(s_len - i >= MIN_DIGEST_LINE_LENGTH
+ || (s[i] == '\\' && s_len - i >= 1 + MIN_DIGEST_LINE_LENGTH)))
+ return FALSE;
+
+ if (s[i] == '\\') {
+ ++i;
+ escaped_filename = 1;
+ }
+ *u = (unsigned char *) &s[i];
+
+ /* The first field has to be the 32-character hexadecimal
+ representation of the message digest. If it is not followed
+ immediately by a white space it's an error. */
+ i += 32;
+ if (!ISWHITE(s[i]))
+ return FALSE;
+
+ s[i++] = '\0';
+
+ if (s[i] != ' ' && s[i] != '*')
+ return FALSE;
+
+ /* All characters between the type indicator and end of line are
+ significant -- that includes leading and trailing white space. */
+ *w = &s[++i];
+
+ if (escaped_filename) {
+ /* Translate each `\n' string in the file name to a NEWLINE,
+ and each `\\' string to a backslash. */
+
+ char *dst = &s[i];
+
+ while (i < s_len) {
+ switch (s[i]) {
+ case '\\':
+ if (i == s_len - 1) {
+ /* A valid line does not end with a backslash. */
+ return FALSE;
+ }
+ ++i;
+ switch (s[i++]) {
+ case 'n':
+ *dst++ = '\n';
+ break;
+ case '\\':
+ *dst++ = '\\';
+ break;
+ default:
+ /* Only `\' or `n' may follow a backslash. */
+ return FALSE;
+ }
+ break;
+
+ case '\0':
+ /* The file name may not contain a NUL. */
+ return FALSE;
+ break;
+
+ default:
+ *dst++ = s[i++];
+ break;
+ }
+ }
+ *dst = '\0';
+ }
+ return TRUE;
+}
+
+static inline int hex_digits(unsigned char const *s)
+{
+ while (*s) {
+ if (!ISXDIGIT(*s))
+ return TRUE;
+ ++s;
+ }
+ return FALSE;
+}
+
+/* An interface to md5_stream. Operate on FILENAME (it may be "-") and
+ put the result in *MD5_RESULT. Return non-zero upon failure, zero
+ to indicate success. */
+static int md5_file(const char *filename, unsigned char *md5_result)
+{
+ FILE *fp;
+
+ if (filename[0] == '-' && filename[1] == '\0') {
+ have_read_stdin = 1;
+ fp = stdin;
+ } else {
+ fp = bb_wfopen(filename, "r");
+ if (fp == NULL)
+ return FALSE;
+ }
+
+ if (md5_stream(fp, md5_result)) {
+ bb_perror_msg("%s", filename);
+
+ if (fp != stdin)
+ fclose(fp);
+ return FALSE;
+ }
+
+ if (fp != stdin && fclose(fp) == EOF) {
+ bb_perror_msg("%s", filename);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int md5_check(const char *checkfile_name)
+{
+ FILE *checkfile_stream;
+ int n_properly_formated_lines = 0;
+ int n_mismatched_checksums = 0;
+ int n_open_or_read_failures = 0;
+ unsigned char md5buffer[16];
+ size_t line_number;
+ char line[BUFSIZ];
+
+ if (checkfile_name[0] == '-' && checkfile_name[1] == '\0') {
+ have_read_stdin = 1;
+ checkfile_stream = stdin;
+ } else {
+ checkfile_stream = bb_wfopen(checkfile_name, "r");
+ if (checkfile_stream == NULL)
+ return FALSE;
+ }
+
+ line_number = 0;
+
+ do {
+ char *filename;
+ unsigned char *md5num;
+ int line_length;
+
+ ++line_number;
+
+ fgets(line, BUFSIZ - 1, checkfile_stream);
+ line_length = strlen(line);
+
+ if (line_length <= 0 || line == NULL)
+ break;
+
+ /* Ignore comment lines, which begin with a '#' character. */
+ if (line[0] == '#')
+ continue;
+
+ /* Remove any trailing newline. */
+ if (line[line_length - 1] == '\n')
+ line[--line_length] = '\0';
+
+ if (split_3(line, line_length, &md5num, &filename)
+ || !hex_digits(md5num)) {
+ if (warn) {
+ bb_error_msg
+ ("%s: %lu: improperly formatted MD5 checksum line",
+ checkfile_name, (unsigned long) line_number);
+ }
+ } else {
+ static const char bin2hex[] = {
+ '0', '1', '2', '3',
+ '4', '5', '6', '7',
+ '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f'
+ };
+
+ ++n_properly_formated_lines;
+
+ if (md5_file(filename, md5buffer)) {
+ ++n_open_or_read_failures;
+ if (!status_only) {
+ printf("%s: FAILED open or read\n", filename);
+ fflush(stdout);
+ }
+ } else {
+ size_t cnt;
+
+ /* Compare generated binary number with text representation
+ in check file. Ignore case of hex digits. */
+ for (cnt = 0; cnt < 16; ++cnt) {
+ if (tolower(md5num[2 * cnt])
+ != bin2hex[md5buffer[cnt] >> 4]
+ || (tolower(md5num[2 * cnt + 1])
+ != (bin2hex[md5buffer[cnt] & 0xf])))
+ break;
+ }
+ if (cnt != 16)
+ ++n_mismatched_checksums;
+
+ if (!status_only) {
+ printf("%s: %s\n", filename,
+ (cnt != 16 ? "FAILED" : "OK"));
+ fflush(stdout);
+ }
+ }
+ }
+ }
+
+ while (!feof(checkfile_stream) && !ferror(checkfile_stream));
+
+ if (ferror(checkfile_stream)) {
+ bb_error_msg("%s: read error", checkfile_name);
+ return FALSE;
+ }
+
+ if (checkfile_stream != stdin && fclose(checkfile_stream) == EOF) {
+ bb_perror_msg("md5sum: %s", checkfile_name);
+ return FALSE;
+ }
+
+ if (n_properly_formated_lines == 0) {
+ /* Warn if no tests are found. */
+ bb_error_msg("%s: no properly formatted MD5 checksum lines found",
+ checkfile_name);
+ return FALSE;
+ } else {
+ if (!status_only) {
+ int n_computed_checkums = (n_properly_formated_lines
+ - n_open_or_read_failures);
+
+ if (n_open_or_read_failures > 0) {
+ bb_error_msg
+ ("WARNING: %d of %d listed files could not be read",
+ n_open_or_read_failures, n_properly_formated_lines);
+ return FALSE;
+ }
+
+ if (n_mismatched_checksums > 0) {
+ bb_error_msg
+ ("WARNING: %d of %d computed checksums did NOT match",
+ n_mismatched_checksums, n_computed_checkums);
+ return FALSE;
+ }
+ }
+ }
+
+ return ((n_properly_formated_lines > 0 && n_mismatched_checksums == 0
+ && n_open_or_read_failures == 0) ? 0 : 1);
+}
+
+int md5sum_main(int argc, char **argv)
+{
+ unsigned char md5buffer[16];
+ int do_check = 0;
+ int opt;
+ char **string = NULL;
+ size_t n_strings = 0;
+ size_t err = 0;
+ char file_type_specified = 0;
+ char binary = 0;
+
+ while ((opt = getopt(argc, argv, "g:bcstw")) != -1) {
+ switch (opt) {
+ case 'g':{ /* read a string */
+ if (string == NULL)
+ string = (char **) xmalloc((argc - 1) * sizeof(char *));
+
+ string[n_strings++] = optarg;
+ break;
+ }
+
+ case 'b': /* read files in binary mode */
+ file_type_specified = 1;
+ binary = 1;
+ break;
+
+ case 'c': /* check MD5 sums against given list */
+ do_check = 1;
+ break;
+
+ case 's': /* don't output anything, status code shows success */
+ status_only = 1;
+ warn = 0;
+ break;
+
+ case 't': /* read files in text mode (default) */
+ file_type_specified = 1;
+ binary = 0;
+ break;
+
+ case 'w': /* warn about improperly formated MD5 checksum lines */
+ status_only = 0;
+ warn = 1;
+ break;
+
+ default:
+ bb_show_usage();
+ }
+ }
+
+ if (file_type_specified && do_check) {
+ bb_error_msg_and_die
+ ("the -b and -t options are meaningless when verifying checksums");
+ }
+
+ if (n_strings > 0 && do_check) {
+ bb_error_msg_and_die("the -g and -c options are mutually exclusive");
+ }
+
+ if (status_only && !do_check) {
+ bb_error_msg_and_die
+ ("the -s option is meaningful only when verifying checksums");
+ }
+
+ if (warn && !do_check) {
+ bb_error_msg_and_die
+ ("the -w option is meaningful only when verifying checksums");
+ }
+
+ if (n_strings > 0) {
+ size_t i;
+
+ if (optind < argc) {
+ bb_error_msg_and_die("no files may be specified when using -g");
+ }
+ for (i = 0; i < n_strings; ++i) {
+ size_t cnt;
+
+ md5_buffer(string[i], strlen(string[i]), md5buffer);
+
+ for (cnt = 0; cnt < 16; ++cnt)
+ printf("%02x", md5buffer[cnt]);
+
+ printf(" \"%s\"\n", string[i]);
+ }
+ } else if (do_check) {
+ if (optind + 1 < argc) {
+ bb_error_msg("only one argument may be specified when using -c");
+ }
+
+ err = md5_check((optind == argc) ? "-" : argv[optind]);
+ } else {
+ if (optind == argc)
+ argv[argc++] = "-";
+
+ for (; optind < argc; ++optind) {
+ int fail;
+ char *file = argv[optind];
+
+ fail = md5_file(file, md5buffer);
+ err |= fail;
+ if (!fail && file[0] == '-' && file[1] == '\0') {
+ size_t i;
+
+ for (i = 0; i < 16; ++i)
+ printf("%02x", md5buffer[i]);
+ putchar('\n');
+ } else if (!fail) {
+ size_t i;
+
+ /* Output a leading backslash if the file name contains
+ a newline or backslash. */
+ if (strchr(file, '\n') || strchr(file, '\\'))
+ putchar('\\');
+
+ for (i = 0; i < 16; ++i)
+ printf("%02x", md5buffer[i]);
+
+ putchar(' ');
+ if (binary)
+ putchar('*');
+ else
+ putchar(' ');
+
+ /* Translate each NEWLINE byte to the string, "\\n",
+ and each backslash to "\\\\". */
+ for (i = 0; i < strlen(file); ++i) {
+ switch (file[i]) {
+ case '\n':
+ fputs("\\n", stdout);
+ break;
+
+ case '\\':
+ fputs("\\\\", stdout);
+ break;
+
+ default:
+ putchar(file[i]);
+ break;
+ }
+ }
+ putchar('\n');
+ }
+ }
+ }
+
+ if (fclose(stdout) == EOF) {
+ bb_error_msg_and_die("write error");
+ }
+
+ if (have_read_stdin && fclose(stdin) == EOF) {
+ bb_error_msg_and_die(bb_msg_standard_input);
+ }
+
+ if (err == 0)
+ return EXIT_SUCCESS;
+ else
+ return EXIT_FAILURE;
+}
diff --git a/release/src/router/busybox/coreutils/mkdir.c b/release/src/router/busybox/coreutils/mkdir.c
new file mode 100644
index 00000000..50364f17
--- /dev/null
+++ b/release/src/router/busybox/coreutils/mkdir.c
@@ -0,0 +1,75 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini mkdir implementation for busybox
+ *
+ * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/mkdir.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Fixed broken permission setting when -p was used; especially in
+ * conjunction with -m.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "busybox.h"
+
+static const struct option mkdir_long_options[] = {
+ { "mode", 1, NULL, 'm' },
+ { "parents", 0, NULL, 'p' },
+ { 0, 0, 0, 0 }
+};
+
+extern int mkdir_main (int argc, char **argv)
+{
+ mode_t mode = (mode_t)(-1);
+ int status = EXIT_SUCCESS;
+ int flags = 0;
+ unsigned long opt;
+ char *smode;
+
+ bb_applet_long_options = mkdir_long_options;
+ opt = bb_getopt_ulflags(argc, argv, "m:p", &smode);
+ if(opt & 1) {
+ mode = 0777;
+ if (!bb_parse_mode (smode, &mode)) {
+ bb_error_msg_and_die ("invalid mode `%s'", smode);
+ }
+ }
+ if(opt & 2)
+ flags |= FILEUTILS_RECUR;
+
+ if (optind == argc) {
+ bb_show_usage();
+ }
+
+ argv += optind;
+
+ do {
+ if (bb_make_directory(*argv, mode, flags)) {
+ status = EXIT_FAILURE;
+ }
+ } while (*++argv);
+
+ return status;
+}
diff --git a/release/src/router/busybox/coreutils/mkfifo.c b/release/src/router/busybox/coreutils/mkfifo.c
new file mode 100644
index 00000000..77e0e6dd
--- /dev/null
+++ b/release/src/router/busybox/coreutils/mkfifo.c
@@ -0,0 +1,51 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * mkfifo implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/mkfifo.html */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+extern int mkfifo_main(int argc, char **argv)
+{
+ mode_t mode;
+ int retval = EXIT_SUCCESS;
+
+ mode = getopt_mk_fifo_nod(argc, argv);
+
+ if (!*(argv += optind)) {
+ bb_show_usage();
+ }
+
+ do {
+ if (mkfifo(*argv, mode) < 0) {
+ bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
+ retval = EXIT_FAILURE;
+ }
+ } while (*++argv);
+
+ return retval;
+}
diff --git a/release/src/router/busybox/coreutils/mknod.c b/release/src/router/busybox/coreutils/mknod.c
new file mode 100644
index 00000000..d5e9e17f
--- /dev/null
+++ b/release/src/router/busybox/coreutils/mknod.c
@@ -0,0 +1,63 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * mknod implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+static const char modes_chars[] = { 'p', 'c', 'u', 'b', 0, 1, 1, 2 };
+static const mode_t modes_cubp[] = { S_IFIFO, S_IFCHR, S_IFBLK };
+
+extern int mknod_main(int argc, char **argv)
+{
+ mode_t mode;
+ dev_t dev;
+ const char *name;
+
+ mode = getopt_mk_fifo_nod(argc, argv);
+ argv += optind;
+ argc -= optind;
+
+ if ((argc >= 2) && ((name = strchr(modes_chars, argv[1][0])) != NULL)) {
+ mode |= modes_cubp[(int)(name[4])];
+
+ dev = 0;
+ if ((*name != 'p') && ((argc -= 2) == 2)) {
+ dev = (bb_xgetularg10_bnd(argv[2], 0, 255) << 8)
+ + bb_xgetularg10_bnd(argv[3], 0, 255);
+ }
+
+ if (argc == 2) {
+ name = *argv;
+ if (mknod(name, mode, dev) == 0) {
+ return EXIT_SUCCESS;
+ }
+ bb_perror_msg_and_die("%s", name);
+ }
+ }
+ bb_show_usage();
+}
diff --git a/release/src/router/busybox/coreutils/mv.c b/release/src/router/busybox/coreutils/mv.c
new file mode 100644
index 00000000..55da2cc6
--- /dev/null
+++ b/release/src/router/busybox/coreutils/mv.c
@@ -0,0 +1,143 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini mv implementation for busybox
+ *
+ * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Size reduction and improved error checking.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+static const struct option mv_long_options[] = {
+ { "interactive", 0, NULL, 'i' },
+ { "force", 0, NULL, 'f' },
+ { 0, 0, 0, 0 }
+};
+
+static const char mv_getopt_short_option[] = "fi";
+#define OPT_FILEUTILS_FORCE 1
+#define OPT_FILEUTILS_INTERACTIVE 2
+
+static const char fmt[] = "cannot overwrite %sdirectory with %sdirectory";
+
+extern int mv_main(int argc, char **argv)
+{
+ struct stat source_stat;
+ struct stat dest_stat;
+ const char *last;
+ const char *dest;
+ int dest_exists;
+ int source_exists;
+ unsigned long flags;
+ int status = 0;
+
+ bb_applet_long_options = mv_long_options;
+ bb_opt_complementaly = "f-i:i-f";
+ flags = bb_getopt_ulflags(argc, argv, mv_getopt_short_option);
+
+ if (optind + 2 > argc)
+ bb_show_usage();
+
+ last = argv[argc - 1];
+ argv += optind;
+
+ if (optind + 2 == argc) {
+ if ((dest_exists = cp_mv_stat(last, &dest_stat)) < 0) {
+ return 1;
+ }
+
+ if (!(dest_exists & 2)) {
+ dest = last;
+ goto DO_MOVE;
+ }
+ }
+
+ do {
+ dest = concat_path_file(last, bb_get_last_path_component(*argv));
+
+ if ((dest_exists = cp_mv_stat(dest, &dest_stat)) < 0) {
+ goto RET_1;
+ }
+
+ DO_MOVE:
+
+ if (dest_exists && !(flags & OPT_FILEUTILS_FORCE) &&
+ ((access(dest, W_OK) < 0 && isatty(0)) ||
+ (flags & OPT_FILEUTILS_INTERACTIVE))) {
+ if (fprintf(stderr, "mv: overwrite `%s'? ", dest) < 0) {
+ goto RET_1; /* Ouch! fprintf failed! */
+ }
+ if (!bb_ask_confirmation())
+ goto RET_0;
+ }
+
+ if (rename(*argv, dest) < 0) {
+ if (errno != EXDEV) {
+ bb_perror_msg("unable to rename `%s'", *argv);
+ } else if ((source_exists = cp_mv_stat(*argv, &source_stat)) >= 0) {
+ if (dest_exists) {
+ if (dest_exists & 2) {
+ if (!(source_exists & 2)) {
+ bb_error_msg(fmt, "", "non-");
+ goto RET_1;
+ }
+ } else {
+ if (source_exists & 2) {
+ bb_error_msg(fmt, "non-", "");
+ goto RET_1;
+ }
+ }
+ if (unlink(dest) < 0) {
+ bb_perror_msg("cannot remove `%s'", dest);
+ goto RET_1;
+ }
+ }
+
+ if ((copy_file(*argv, dest,
+ FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0)
+ && (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)
+ ) {
+ goto RET_0;
+ }
+
+ }
+ RET_1:
+ status = 1;
+ }
+
+ RET_0:
+ if (dest != last) {
+ free((void *) dest);
+ }
+
+ } while (*++argv != last);
+
+ exit(status);
+}
diff --git a/release/src/router/busybox/coreutils/od.c b/release/src/router/busybox/coreutils/od.c
new file mode 100644
index 00000000..b18c53c3
--- /dev/null
+++ b/release/src/router/busybox/coreutils/od.c
@@ -0,0 +1,231 @@
+/*
+ * od implementation for busybox
+ * Based on code from util-linux v 2.11l
+ *
+ * Copyright (c) 1990
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Original copyright notice is retained at the end of this file.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include "busybox.h"
+#include "dump.h"
+
+#define isdecdigit(c) (isdigit)(c)
+#define ishexdigit(c) (isxdigit)(c)
+
+static void
+odoffset(int argc, char ***argvp)
+{
+ register char *num, *p;
+ int base;
+ char *end;
+
+ /*
+ * 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 assumes it's a file if the offset is bad.
+ */
+ p = **argvp;
+
+ if (!p) {
+ /* hey someone is probably piping to us ... */
+ return;
+ }
+
+ if ((*p != '+')
+ && (argc < 2
+ || (!isdecdigit(p[0])
+ && ((p[0] != 'x') || !ishexdigit(p[1])))))
+ return;
+
+ base = 0;
+ /*
+ * bb_dump_skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
+ * set base.
+ */
+ if (p[0] == '+')
+ ++p;
+ if (p[0] == 'x' && ishexdigit(p[1])) {
+ ++p;
+ base = 16;
+ } else if (p[0] == '0' && p[1] == 'x') {
+ p += 2;
+ base = 16;
+ }
+
+ /* bb_dump_skip over the number */
+ if (base == 16)
+ for (num = p; ishexdigit(*p); ++p);
+ else
+ for (num = p; isdecdigit(*p); ++p);
+
+ /* check for no number */
+ if (num == p)
+ return;
+
+ /* if terminates with a '.', base is decimal */
+ if (*p == '.') {
+ if (base)
+ return;
+ base = 10;
+ }
+
+ bb_dump_skip = strtol(num, &end, base ? base : 8);
+
+ /* if end isn't the same as p, we got a non-octal digit */
+ if (end != p)
+ bb_dump_skip = 0;
+ else {
+ if (*p) {
+ if (*p == 'b') {
+ bb_dump_skip *= 512;
+ ++p;
+ } else if (*p == 'B') {
+ bb_dump_skip *= 1024;
+ ++p;
+ }
+ }
+ if (*p)
+ bb_dump_skip = 0;
+ else {
+ ++*argvp;
+ /*
+ * 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.
+ */
+#define TYPE_OFFSET 7
+ {
+ char x_or_d;
+ if (base == 16) {
+ x_or_d = 'x';
+ goto DO_X_OR_D;
+ }
+ if (base == 10) {
+ x_or_d = 'd';
+ DO_X_OR_D:
+ bb_dump_fshead->nextfu->fmt[TYPE_OFFSET]
+ = bb_dump_fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
+ = x_or_d;
+ }
+ }
+ }
+ }
+}
+
+static const char * const add_strings[] = {
+ "16/1 \"%3_u \" \"\\n\"", /* a */
+ "8/2 \" %06o \" \"\\n\"", /* B, o */
+ "16/1 \"%03o \" \"\\n\"", /* b */
+ "16/1 \"%3_c \" \"\\n\"", /* c */
+ "8/2 \" %05u \" \"\\n\"", /* d */
+ "4/4 \" %010u \" \"\\n\"", /* D */
+ "2/8 \" %21.14e \" \"\\n\"", /* e (undocumented in od), F */
+ "4/4 \" %14.7e \" \"\\n\"", /* f */
+ "4/4 \" %08x \" \"\\n\"", /* H, X */
+ "8/2 \" %04x \" \"\\n\"", /* h, x */
+ "4/4 \" %11d \" \"\\n\"", /* I, L, l */
+ "8/2 \" %6d \" \"\\n\"", /* i */
+ "4/4 \" %011o \" \"\\n\"", /* O */
+};
+
+static const signed char od_opts[] = "aBbcDdeFfHhIiLlOovXx";
+
+static const signed char od_o2si[] = {
+ 0, 1, 2, 3, 5,
+ 4, 6, 6, 7, 8,
+ 9, 0xa, 0xb, 0xa, 0xa,
+ 0xb, 1, -1, 8, 9,
+};
+
+int od_main(int argc, char **argv)
+{
+ int ch;
+ int first = 1;
+ signed char *p;
+ bb_dump_vflag = FIRST;
+ bb_dump_length = -1;
+
+ while ((ch = getopt(argc, argv, od_opts)) > 0) {
+ if (((p = strchr(od_opts, ch)) != NULL) && (*p >= 0)) {
+ if (first) {
+ first = 0;
+ bb_dump_add("\"%07.7_Ao\n\"");
+ bb_dump_add("\"%07.7_ao \"");
+ } else {
+ bb_dump_add("\" \"");
+ }
+ bb_dump_add(add_strings[od_o2si[(int)(p-od_opts)]]);
+ } else if (ch == 'v') {
+ bb_dump_vflag = ALL;
+ } else { /* P, p, s, w, or other unhandled */
+ bb_show_usage();
+ }
+ }
+ if (!bb_dump_fshead) {
+ bb_dump_add("\"%07.7_Ao\n\"");
+ bb_dump_add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\"");
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ odoffset(argc, &argv);
+
+ return(bb_dump_dump(argv));
+}
+
+/*-
+ * Copyright (c) 1990 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.
+ */
diff --git a/release/src/router/busybox/coreutils/printf.c b/release/src/router/busybox/coreutils/printf.c
new file mode 100644
index 00000000..28f8aa45
--- /dev/null
+++ b/release/src/router/busybox/coreutils/printf.c
@@ -0,0 +1,452 @@
+/* vi: set sw=4 ts=4: */
+/* printf - format and print data
+ Copyright (C) 90, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Usage: printf format [argument...]
+
+ A front end to the printf function that lets it be used from the shell.
+
+ Backslash escapes:
+
+ \" = double quote
+ \\ = backslash
+ \a = alert (bell)
+ \b = backspace
+ \c = produce no further output
+ \f = form feed
+ \n = new line
+ \r = carriage return
+ \t = horizontal tab
+ \v = vertical tab
+ \0ooo = octal number (ooo is 0 to 3 digits)
+ \xhhh = hexadecimal number (hhh is 1 to 3 digits)
+
+ Additional directive:
+
+ %b = print an argument string, interpreting backslash escapes
+
+ The `format' argument is re-used as many times as necessary
+ to convert all of the given arguments.
+
+ David MacKenzie <djm@gnu.ai.mit.edu> */
+
+
+// 19990508 Busy Boxed! Dave Cinege
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <assert.h>
+#include "busybox.h"
+
+
+#ifndef S_IFMT
+static const int S_IFMT = 0170000;
+#endif
+#if !defined(S_ISBLK) && defined(S_IFBLK)
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#endif
+#if !defined(S_ISCHR) && defined(S_IFCHR)
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG) && defined(S_IFREG)
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISFIFO) && defined(S_IFIFO)
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK) && defined(S_IFSOCK)
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
+# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
+# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
+#endif
+#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
+# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
+#endif
+
+#define IN_CTYPE_DOMAIN(c) 1
+
+#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c))
+#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
+#define ISDIGIT(c) (((unsigned char) (c)) - '0' <= 9)
+
+#define isodigit(c) ((c) >= '0' && (c) <= '7')
+#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
+#define octtobin(c) ((c) - '0')
+
+static double xstrtod __P((char *s));
+static int print_esc __P((char *escstart));
+static int print_formatted __P((char *format, int argc, char **argv));
+static long xstrtol __P((char *s));
+static unsigned long xstrtoul __P((char *s));
+static void print_direc __P( (char *start, size_t length,
+ int field_width, int precision, char *argument));
+static void print_esc_char __P((int c));
+static void print_esc_string __P((char *str));
+
+/* The value to return to the calling program. */
+static int exit_status;
+
+int printf_main(int argc, char **argv)
+{
+ char *format;
+ int args_used;
+
+ exit_status = 0;
+ if (argc <= 1 || **(argv + 1) == '-') {
+ bb_show_usage();
+ }
+
+ format = argv[1];
+ argc -= 2;
+ argv += 2;
+
+ do {
+ args_used = print_formatted(format, argc, argv);
+ argc -= args_used;
+ argv += args_used;
+ }
+ while (args_used > 0 && argc > 0);
+
+/*
+ if (argc > 0)
+ fprintf(stderr, "excess args ignored");
+*/
+
+ return(exit_status);
+}
+
+/* Print the text in FORMAT, using ARGV (with ARGC elements) for
+ arguments to any `%' directives.
+ Return the number of elements of ARGV used. */
+
+static int print_formatted(char *format, int argc, char **argv)
+{
+ int save_argc = argc; /* Preserve original value. */
+ char *f; /* Pointer into `format'. */
+ char *direc_start; /* Start of % directive. */
+ size_t direc_length; /* Length of % directive. */
+ int field_width; /* Arg to first '*', or -1 if none. */
+ int precision; /* Arg to second '*', or -1 if none. */
+
+ for (f = format; *f; ++f) {
+ switch (*f) {
+ case '%':
+ direc_start = f++;
+ direc_length = 1;
+ field_width = precision = -1;
+ if (*f == '%') {
+ putchar('%');
+ break;
+ }
+ if (*f == 'b') {
+ if (argc > 0) {
+ print_esc_string(*argv);
+ ++argv;
+ --argc;
+ }
+ break;
+ }
+ if (strchr("-+ #", *f)) {
+ ++f;
+ ++direc_length;
+ }
+ if (*f == '*') {
+ ++f;
+ ++direc_length;
+ if (argc > 0) {
+ field_width = xstrtoul(*argv);
+ ++argv;
+ --argc;
+ } else
+ field_width = 0;
+ } else
+ while (ISDIGIT(*f)) {
+ ++f;
+ ++direc_length;
+ }
+ if (*f == '.') {
+ ++f;
+ ++direc_length;
+ if (*f == '*') {
+ ++f;
+ ++direc_length;
+ if (argc > 0) {
+ precision = xstrtoul(*argv);
+ ++argv;
+ --argc;
+ } else
+ precision = 0;
+ } else
+ while (ISDIGIT(*f)) {
+ ++f;
+ ++direc_length;
+ }
+ }
+ if (*f == 'l' || *f == 'L' || *f == 'h') {
+ ++f;
+ ++direc_length;
+ }
+ /*
+ if (!strchr ("diouxXfeEgGcs", *f))
+ fprintf(stderr, "%%%c: invalid directive", *f);
+ */
+ ++direc_length;
+ if (argc > 0) {
+ print_direc(direc_start, direc_length, field_width,
+ precision, *argv);
+ ++argv;
+ --argc;
+ } else
+ print_direc(direc_start, direc_length, field_width,
+ precision, "");
+ break;
+
+ case '\\':
+ f += print_esc(f);
+ break;
+
+ default:
+ putchar(*f);
+ }
+ }
+
+ return save_argc - argc;
+}
+
+/* Print a \ escape sequence starting at ESCSTART.
+ Return the number of characters in the escape sequence
+ besides the backslash. */
+
+static int print_esc(char *escstart)
+{
+ register char *p = escstart + 1;
+ int esc_value = 0; /* Value of \nnn escape. */
+ int esc_length; /* Length of \nnn escape. */
+
+ /* \0ooo and \xhhh escapes have maximum length of 3 chars. */
+ if (*p == 'x') {
+ for (esc_length = 0, ++p;
+ esc_length < 3 && ISXDIGIT(*p); ++esc_length, ++p)
+ esc_value = esc_value * 16 + hextobin(*p);
+/* if (esc_length == 0)
+ fprintf(stderr, "missing hex in esc");
+*/
+ putchar(esc_value);
+ } else if (*p == '0') {
+ for (esc_length = 0, ++p;
+ esc_length < 3 && isodigit(*p); ++esc_length, ++p)
+ esc_value = esc_value * 8 + octtobin(*p);
+ putchar(esc_value);
+ } else if (strchr("\"\\abcfnrtv", *p))
+ print_esc_char(*p++);
+/* else
+ fprintf(stderr, "\\%c: invalid esc", *p);
+*/
+ return p - escstart - 1;
+}
+
+/* Output a single-character \ escape. */
+
+static void print_esc_char(int c)
+{
+ switch (c) {
+ case 'a': /* Alert. */
+ putchar(7);
+ break;
+ case 'b': /* Backspace. */
+ putchar(8);
+ break;
+ case 'c': /* Cancel the rest of the output. */
+ exit(0);
+ break;
+ case 'f': /* Form feed. */
+ putchar(12);
+ break;
+ case 'n': /* New line. */
+ putchar(10);
+ break;
+ case 'r': /* Carriage return. */
+ putchar(13);
+ break;
+ case 't': /* Horizontal tab. */
+ putchar(9);
+ break;
+ case 'v': /* Vertical tab. */
+ putchar(11);
+ break;
+ default:
+ putchar(c);
+ break;
+ }
+}
+
+/* Print string STR, evaluating \ escapes. */
+
+static void print_esc_string(char *str)
+{
+ for (; *str; str++)
+ if (*str == '\\')
+ str += print_esc(str);
+ else
+ putchar(*str);
+}
+
+static void
+print_direc(char *start, size_t length, int field_width, int precision,
+ char *argument)
+{
+ char *p; /* Null-terminated copy of % directive. */
+
+ p = xmalloc((unsigned) (length + 1));
+ strncpy(p, start, length);
+ p[length] = 0;
+
+ switch (p[length - 1]) {
+ case 'd':
+ case 'i':
+ if (field_width < 0) {
+ if (precision < 0)
+ printf(p, xstrtol(argument));
+ else
+ printf(p, precision, xstrtol(argument));
+ } else {
+ if (precision < 0)
+ printf(p, field_width, xstrtol(argument));
+ else
+ printf(p, field_width, precision, xstrtol(argument));
+ }
+ break;
+
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ if (field_width < 0) {
+ if (precision < 0)
+ printf(p, xstrtoul(argument));
+ else
+ printf(p, precision, xstrtoul(argument));
+ } else {
+ if (precision < 0)
+ printf(p, field_width, xstrtoul(argument));
+ else
+ printf(p, field_width, precision, xstrtoul(argument));
+ }
+ break;
+
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ if (field_width < 0) {
+ if (precision < 0)
+ printf(p, xstrtod(argument));
+ else
+ printf(p, precision, xstrtod(argument));
+ } else {
+ if (precision < 0)
+ printf(p, field_width, xstrtod(argument));
+ else
+ printf(p, field_width, precision, xstrtod(argument));
+ }
+ break;
+
+ case 'c':
+ printf(p, *argument);
+ break;
+
+ case 's':
+ if (field_width < 0) {
+ if (precision < 0)
+ printf(p, argument);
+ else
+ printf(p, precision, argument);
+ } else {
+ if (precision < 0)
+ printf(p, field_width, argument);
+ else
+ printf(p, field_width, precision, argument);
+ }
+ break;
+ }
+
+ free(p);
+}
+
+static unsigned long xstrtoul(char *arg)
+{
+ unsigned long result;
+ char *endptr;
+ //int errno_save = errno;
+
+ assert(arg!=NULL);
+
+ errno = 0;
+ result = strtoul(arg, &endptr, 10);
+ if (errno != 0 || *endptr!='\0' || endptr==arg)
+ fprintf(stderr, "%s", arg);
+ //errno = errno_save;
+ return result;
+}
+
+static long xstrtol(char *arg)
+{
+ long result;
+ char *endptr;
+ //int errno_save = errno;
+
+ assert(arg!=NULL);
+
+ errno = 0;
+ result = strtoul(arg, &endptr, 10);
+ if (errno != 0 || *endptr!='\0' || endptr==arg)
+ fprintf(stderr, "%s", arg);
+ //errno = errno_save;
+ return result;
+}
+
+static double xstrtod(char *arg)
+{
+ double result;
+ char *endptr;
+ //int errno_save = errno;
+
+ assert(arg!=NULL);
+
+ errno = 0;
+ result = strtod(arg, &endptr);
+ if (errno != 0 || *endptr!='\0' || endptr==arg)
+ fprintf(stderr, "%s", arg);
+ //errno = errno_save;
+ return result;
+}
+
diff --git a/release/src/router/busybox/coreutils/pwd.c b/release/src/router/busybox/coreutils/pwd.c
new file mode 100644
index 00000000..7e0dc056
--- /dev/null
+++ b/release/src/router/busybox/coreutils/pwd.c
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini pwd implementation for busybox
+ *
+ * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+extern int pwd_main(int argc, char **argv)
+{
+ char *buf;
+
+ if ((buf = xgetcwd(NULL)) != NULL) {
+ puts(buf);
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+ }
+
+ return EXIT_FAILURE;
+}
diff --git a/release/src/router/busybox/coreutils/realpath.c b/release/src/router/busybox/coreutils/realpath.c
new file mode 100644
index 00000000..ec98221a
--- /dev/null
+++ b/release/src/router/busybox/coreutils/realpath.c
@@ -0,0 +1,54 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Apparently a busybox extension. */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Now does proper error checking on output and returns a failure exit code
+ * if one or more paths can not be resolved.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+int realpath_main(int argc, char **argv)
+{
+ int retval = EXIT_SUCCESS;
+
+ RESERVE_CONFIG_BUFFER(resolved_path, PATH_MAX);
+
+ if (--argc == 0) {
+ bb_show_usage();
+ }
+
+ do {
+ argv++;
+ if (realpath(*argv, resolved_path) != NULL) {
+ puts(resolved_path);
+ } else {
+ retval = EXIT_FAILURE;
+ bb_perror_msg("%s", *argv);
+ }
+ } while (--argc);
+
+#ifdef CONFIG_FEATURE_CLEAN_UP
+ RELEASE_CONFIG_BUFFER(resolved_path);
+#endif
+
+ bb_fflush_stdout_and_exit(retval);
+}
diff --git a/release/src/router/busybox/coreutils/rm.c b/release/src/router/busybox/coreutils/rm.c
new file mode 100644
index 00000000..39609e7b
--- /dev/null
+++ b/release/src/router/busybox/coreutils/rm.c
@@ -0,0 +1,66 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini rm implementation for busybox
+ *
+ * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/rm.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Size reduction.
+ */
+
+#include <unistd.h>
+#include "busybox.h"
+
+extern int rm_main(int argc, char **argv)
+{
+ int status = 0;
+ int flags = 0;
+ unsigned long opt;
+
+ bb_opt_complementaly = "f-i:i-f";
+ opt = bb_getopt_ulflags(argc, argv, "fiRr");
+ if(opt & 1)
+ flags |= FILEUTILS_FORCE;
+ if(opt & 2)
+ flags |= FILEUTILS_INTERACTIVE;
+ if(opt & 12)
+ flags |= FILEUTILS_RECUR;
+
+ if (*(argv += optind) != NULL) {
+ do {
+ const char *base = bb_get_last_path_component(*argv);
+
+ if ((base[0] == '.') && (!base[1] || ((base[1] == '.') && !base[2]))) {
+ bb_error_msg("cannot remove `.' or `..'");
+ } else if (remove_file(*argv, flags) >= 0) {
+ continue;
+ }
+ status = 1;
+ } while (*++argv);
+ } else if (!(flags & FILEUTILS_FORCE)) {
+ bb_show_usage();
+ }
+
+ return status;
+}
diff --git a/release/src/router/busybox/coreutils/rmdir.c b/release/src/router/busybox/coreutils/rmdir.c
new file mode 100644
index 00000000..3f603717
--- /dev/null
+++ b/release/src/router/busybox/coreutils/rmdir.c
@@ -0,0 +1,73 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * rmdir implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <libgen.h>
+#include "busybox.h"
+
+extern int rmdir_main(int argc, char **argv)
+{
+ int status = EXIT_SUCCESS;
+ int flags;
+ int do_dot;
+ char *path;
+
+ flags = bb_getopt_ulflags(argc, argv, "p");
+
+ argv += optind;
+
+ if (!*argv) {
+ bb_show_usage();
+ }
+
+ do {
+ path = *argv;
+
+ /* Record if the first char was a '.' so we can use dirname later. */
+ do_dot = (*path == '.');
+
+ do {
+ if (rmdir(path) < 0) {
+ bb_perror_msg("`%s'", path); /* Match gnu rmdir msg. */
+ status = EXIT_FAILURE;
+ } else if (flags) {
+ /* Note: path was not empty or null since rmdir succeeded. */
+ path = dirname(path);
+ /* Path is now just the parent component. Note that dirname
+ * returns "." if there are no parents. We must distinguish
+ * this from the case of the original path starting with '.'.
+ */
+ if (do_dot || (*path != '.') || path[1]) {
+ continue;
+ }
+ }
+ break;
+ } while (1);
+
+ } while (*++argv);
+
+ return status;
+}
diff --git a/release/src/router/busybox/coreutils/sha1sum.c b/release/src/router/busybox/coreutils/sha1sum.c
new file mode 100644
index 00000000..1148aac1
--- /dev/null
+++ b/release/src/router/busybox/coreutils/sha1sum.c
@@ -0,0 +1,492 @@
+/*
+ * Based on shasum from http://www.netsw.org/crypto/hash/
+ * Majorly hacked up to use Dr Brian Gladman's sha1 code
+ *
+ * Copyright (C) 1999 Scott G. Miller
+ * Copyright (C) 2003 Glenn L. McGrath
+ * Copyright (C) 2003 Erik Andersen
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+#include <endian.h>
+#include <byteswap.h>
+#include "busybox.h"
+
+
+/*
+ ---------------------------------------------------------------------------
+ Begin Dr. Gladman's sha1 code
+ ---------------------------------------------------------------------------
+*/
+
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ ALTERNATIVELY, provided that this notice is retained in full, this product
+ may be distributed under the terms of the GNU General Public License (GPL),
+ in which case the provisions of the GPL apply INSTEAD OF those given above.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 10/11/2002
+
+ This is a byte oriented version of SHA1 that operates on arrays of bytes
+ stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
+*/
+
+#define SHA1_BLOCK_SIZE 64
+#define SHA1_DIGEST_SIZE 20
+#define SHA1_HASH_SIZE SHA1_DIGEST_SIZE
+#define SHA2_GOOD 0
+#define SHA2_BAD 1
+
+/* type to hold the SHA1 context */
+typedef struct
+{ uint32_t count[2];
+ uint32_t hash[5];
+ uint32_t wbuf[16];
+} sha1_ctx;
+
+#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define swap_b32(x) (x)
+#elif defined(bswap_32)
+# define swap_b32(x) bswap_32(x)
+#else
+# define swap_b32(x) ((rotl32((x), 8) & 0x00ff00ff) | (rotl32((x), 24) & 0xff00ff00))
+#endif
+
+#define SHA1_MASK (SHA1_BLOCK_SIZE - 1)
+
+/* reverse byte order in 32-bit words */
+#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
+#define parity(x,y,z) ((x) ^ (y) ^ (z))
+#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* A normal version as set out in the FIPS. This version uses */
+/* partial loop unrolling and is optimised for the Pentium 4 */
+#define rnd(f,k) \
+ t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; \
+ e = d; d = c; c = rotl32(b, 30); b = t
+
+void sha1_compile(sha1_ctx ctx[1])
+{
+ uint32_t w[80], i, a, b, c, d, e, t;
+
+ /* note that words are compiled from the buffer into 32-bit */
+ /* words in big-endian order so an order reversal is needed */
+ /* here on little endian machines */
+ for(i = 0; i < SHA1_BLOCK_SIZE / 4; ++i)
+ w[i] = swap_b32(ctx->wbuf[i]);
+
+ for(i = SHA1_BLOCK_SIZE / 4; i < 80; ++i)
+ w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
+
+ a = ctx->hash[0];
+ b = ctx->hash[1];
+ c = ctx->hash[2];
+ d = ctx->hash[3];
+ e = ctx->hash[4];
+
+ for(i = 0; i < 20; ++i)
+ {
+ rnd(ch, 0x5a827999);
+ }
+
+ for(i = 20; i < 40; ++i)
+ {
+ rnd(parity, 0x6ed9eba1);
+ }
+
+ for(i = 40; i < 60; ++i)
+ {
+ rnd(maj, 0x8f1bbcdc);
+ }
+
+ for(i = 60; i < 80; ++i)
+ {
+ rnd(parity, 0xca62c1d6);
+ }
+
+ ctx->hash[0] += a;
+ ctx->hash[1] += b;
+ ctx->hash[2] += c;
+ ctx->hash[3] += d;
+ ctx->hash[4] += e;
+}
+
+void sha1_begin(sha1_ctx ctx[1])
+{
+ ctx->count[0] = ctx->count[1] = 0;
+ ctx->hash[0] = 0x67452301;
+ ctx->hash[1] = 0xefcdab89;
+ ctx->hash[2] = 0x98badcfe;
+ ctx->hash[3] = 0x10325476;
+ ctx->hash[4] = 0xc3d2e1f0;
+}
+
+/* SHA1 hash data in an array of bytes into hash buffer and call the */
+/* hash_compile function as required. */
+void sha1_hash(const unsigned char data[], unsigned int len, sha1_ctx ctx[1])
+{
+ uint32_t pos = (uint32_t)(ctx->count[0] & SHA1_MASK),
+ freeb = SHA1_BLOCK_SIZE - pos;
+ const unsigned char *sp = data;
+
+ if((ctx->count[0] += len) < len)
+ ++(ctx->count[1]);
+
+ while(len >= freeb) /* tranfer whole blocks while possible */
+ {
+ memcpy(((unsigned char*)ctx->wbuf) + pos, sp, freeb);
+ sp += freeb; len -= freeb; freeb = SHA1_BLOCK_SIZE; pos = 0;
+ sha1_compile(ctx);
+ }
+
+ memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
+}
+
+/* SHA1 Final padding and digest calculation */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+static uint32_t mask[4] =
+ { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff };
+static uint32_t bits[4] =
+ { 0x00000080, 0x00008000, 0x00800000, 0x80000000 };
+#else
+static uint32_t mask[4] =
+ { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 };
+static uint32_t bits[4] =
+ { 0x80000000, 0x00800000, 0x00008000, 0x00000080 };
+#endif
+
+void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
+{
+ uint32_t i, cnt = (uint32_t)(ctx->count[0] & SHA1_MASK);
+
+ /* mask out the rest of any partial 32-bit word and then set */
+ /* the next byte to 0x80. On big-endian machines any bytes in */
+ /* the buffer will be at the top end of 32 bit words, on little */
+ /* endian machines they will be at the bottom. Hence the AND */
+ /* and OR masks above are reversed for little endian systems */
+ ctx->wbuf[cnt >> 2] = (ctx->wbuf[cnt >> 2] & mask[cnt & 3]) | bits[cnt & 3];
+
+ /* we need 9 or more empty positions, one for the padding byte */
+ /* (above) and eight for the length count. If there is not */
+ /* enough space pad and empty the buffer */
+ if(cnt > SHA1_BLOCK_SIZE - 9)
+ {
+ if(cnt < 60) ctx->wbuf[15] = 0;
+ sha1_compile(ctx);
+ cnt = 0;
+ }
+ else /* compute a word index for the empty buffer positions */
+ cnt = (cnt >> 2) + 1;
+
+ while(cnt < 14) /* and zero pad all but last two positions */
+ ctx->wbuf[cnt++] = 0;
+
+ /* assemble the eight byte counter in the buffer in big-endian */
+ /* format */
+
+ ctx->wbuf[14] = swap_b32((ctx->count[1] << 3) | (ctx->count[0] >> 29));
+ ctx->wbuf[15] = swap_b32(ctx->count[0] << 3);
+
+ sha1_compile(ctx);
+
+ /* extract the hash value as bytes in case the hash buffer is */
+ /* misaligned for 32-bit words */
+
+ for(i = 0; i < SHA1_DIGEST_SIZE; ++i)
+ hval[i] = (unsigned char)(ctx->hash[i >> 2] >> 8 * (~i & 3));
+}
+
+#if 0
+void sha1(unsigned char hval[], const unsigned char data[], unsigned int len)
+{ sha1_ctx cx[1];
+
+ sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx);
+}
+#endif
+
+/*
+ ---------------------------------------------------------------------------
+ End of Dr. Gladman's sha1 code
+ ---------------------------------------------------------------------------
+*/
+
+/* Using a larger blocksize can make things _much_ faster
+ * by avoiding a zillion tiny little reads */
+#define BLOCKSIZE 65536
+/* Ensure that BLOCKSIZE is a multiple of 64. */
+#if BLOCKSIZE % SHA1_BLOCK_SIZE != 0
+# error "BLOCKSIZE not a multiple of 64"
+#endif
+
+static int sha1sum_stream(FILE *stream, unsigned char *hashval)
+{
+ int result = 0;
+ sha1_ctx cx[1];
+ size_t sum, n;
+ RESERVE_CONFIG_BUFFER(buffer, BLOCKSIZE + 72);
+
+ /* Initialize the computation context. */
+ sha1_begin(cx);
+
+ /* Iterate over full file contents. */
+ while (1)
+ {
+ /* We read the file in blocks of BLOCKSIZE bytes. One call of the
+ computation function processes the whole buffer so that with the
+ next round of the loop another block can be read. */
+ sum = 0;
+
+ /* Read block. Take care for partial reads. */
+ while (1)
+ {
+ n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+ sum += n;
+
+ if (sum == BLOCKSIZE)
+ break;
+
+ if (n == 0) {
+ /* Check for the error flag IFF N == 0, so that we don't
+ exit the loop after a partial read due to e.g., EAGAIN
+ or EWOULDBLOCK. */
+ if (feof (stream)) {
+ sum = 0;
+ goto process_partial_block;
+ }
+ if (ferror (stream)) {
+ result++;
+ goto all_done;
+ }
+ goto process_partial_block;
+ }
+
+ /* We've read at least one byte, so ignore errors. But always
+ check for EOF, since feof may be true even though N > 0.
+ Otherwise, we could end up calling fread after EOF. */
+ if (feof (stream))
+ goto process_partial_block;
+ }
+
+ /* Process buffer */
+ sha1_hash(buffer, BLOCKSIZE, cx);
+ }
+
+process_partial_block:
+
+ /* Process any remaining bytes. */
+ if (sum > 0)
+ sha1_hash(buffer, sum, cx);
+
+ /* Finalize and write the hash into our buffer. */
+ sha1_end(hashval, cx);
+
+all_done:
+
+ RELEASE_CONFIG_BUFFER(buffer);
+ return result;
+}
+
+#define FLAG_SILENT 1
+#define FLAG_CHECK 2
+#define FLAG_WARN 4
+
+static unsigned char *hash_bin_to_hex(unsigned char *hash_value, unsigned char hash_length)
+{
+ int x, len, max;
+ unsigned char *hex_value;
+
+ max = (hash_length * 2) + 2;
+ hex_value = xmalloc(max);
+ for (x = len = 0; x < hash_length; x++) {
+ len += snprintf(hex_value+len, max-len, "%02x", hash_value[x]);
+ }
+ return(hex_value);
+}
+
+FILE *wfopen_file_or_stdin(const char *file_ptr)
+{
+ FILE *stream;
+
+ if ((file_ptr[0] == '-') && (file_ptr[1] == '\0')) {
+ stream = stdin;
+ } else {
+ stream = bb_wfopen(file_ptr, "r");
+ }
+
+ return(stream);
+}
+
+/* This could become a common function for md5 as well, by using md5_stream */
+extern int authenticate(int argc, char **argv,
+ int (*hash_ptr)(FILE *stream, unsigned char *hashval),
+ const unsigned char hash_length)
+{
+ unsigned char hash_value[hash_length];
+ unsigned int flags;
+ int return_value = EXIT_SUCCESS;
+
+#ifdef CONFIG_FEATURE_SHA1SUM_CHECK
+ flags = bb_getopt_ulflags(argc, argv, "scw");
+#else
+ flags = bb_getopt_ulflags(argc, argv, "s");
+#endif
+
+#ifdef CONFIG_FEATURE_SHA1SUM_CHECK
+ if (!(flags & FLAG_CHECK)) {
+ if (flags & FLAG_SILENT) {
+ bb_error_msg_and_die("the -s option is meaningful only when verifying checksums");
+ }
+ else if (flags & FLAG_WARN) {
+ bb_error_msg_and_die("the -w option is meaningful only when verifying checksums");
+ }
+ }
+#endif
+
+ if (argc == optind) {
+ argv[argc++] = "-";
+ }
+
+#ifdef CONFIG_FEATURE_SHA1SUM_CHECK
+ if (flags & FLAG_CHECK) {
+ FILE *pre_computed_stream;
+ int count_total = 0;
+ int count_failed = 0;
+ unsigned char *file_ptr = argv[optind];
+
+ if (optind + 1 != argc) {
+ bb_error_msg_and_die("only one argument may be specified when using -c");
+ }
+ pre_computed_stream = wfopen_file_or_stdin(file_ptr);
+ while (!feof(pre_computed_stream) && !ferror(pre_computed_stream)) {
+ FILE *stream;
+ char *line;
+ char *line_ptr;
+ char *hex_value;
+
+ line = bb_get_chomped_line_from_file(pre_computed_stream);
+ if (line == NULL) {
+ break;
+ }
+ count_total++;
+ line_ptr = strchr(line, ' ');
+ if (line_ptr == NULL) {
+ if (flags & FLAG_WARN) {
+ bb_error_msg("Invalid format");
+ }
+ free(line);
+ continue;
+ }
+ *line_ptr = '\0';
+ line_ptr++;
+ if ((flags & FLAG_WARN) && (*line_ptr != ' ')) {
+ bb_error_msg("Invalid format");
+ free(line);
+ continue;
+ }
+ line_ptr++;
+ stream = bb_wfopen(line_ptr, "r");
+ if (hash_ptr(stream, hash_value) == EXIT_FAILURE) {
+ bb_perror_msg("%s", file_ptr);
+ return_value = EXIT_FAILURE;
+ }
+ if (fclose(stream) == EOF) {
+ bb_perror_msg("Couldnt close file %s", file_ptr);
+ }
+ hex_value = hash_bin_to_hex(hash_value, hash_length);
+ printf("%s: ", line_ptr);
+ if (strcmp(hex_value, line) != 0) {
+ puts("FAILED");
+ count_failed++;
+ } else {
+ puts("ok");
+ }
+ free(line);
+ }
+ if (count_failed) {
+ bb_error_msg("WARNING: %d of %d computed checksum did NOT match", count_failed, count_total);
+ }
+ if (bb_fclose_nonstdin(pre_computed_stream) == EOF) {
+ bb_perror_msg_and_die("Couldnt close file %s", file_ptr);
+ }
+ } else
+#endif
+ while (optind < argc) {
+ FILE *stream;
+ unsigned char *file_ptr = argv[optind];
+
+ optind++;
+
+ stream = wfopen_file_or_stdin(file_ptr);
+ if (stream == NULL) {
+ return_value = EXIT_FAILURE;
+ continue;
+ }
+ if (hash_ptr(stream, hash_value) == EXIT_FAILURE) {
+ bb_perror_msg("%s", file_ptr);
+ return_value = EXIT_FAILURE;
+ }
+ else if (!flags & FLAG_SILENT) {
+ char *hex_value = hash_bin_to_hex(hash_value, hash_length);
+ printf("%s %s\n", hex_value, file_ptr);
+ free(hex_value);
+ }
+
+ if (bb_fclose_nonstdin(stream) == EOF) {
+ bb_perror_msg("Couldnt close file %s", file_ptr);
+ return_value = EXIT_FAILURE;
+ }
+ }
+
+ return(return_value);
+}
+
+extern int sha1sum_main(int argc, char **argv)
+{
+ return (authenticate(argc, argv, sha1sum_stream, SHA1_HASH_SIZE));
+}
diff --git a/release/src/router/busybox/coreutils/sleep.c b/release/src/router/busybox/coreutils/sleep.c
new file mode 100644
index 00000000..506192dd
--- /dev/null
+++ b/release/src/router/busybox/coreutils/sleep.c
@@ -0,0 +1,86 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * sleep implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/sleep.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Rewritten to do proper arg and error checking.
+ * Also, added a 'fancy' configuration to accept multiple args with
+ * time suffixes for seconds, minutes, hours, and days.
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include "busybox.h"
+
+#ifdef CONFIG_FEATURE_FANCY_SLEEP
+static const struct suffix_mult sleep_suffixes[] = {
+ { "s", 1 },
+ { "m", 60 },
+ { "h", 60*60 },
+ { "d", 24*60*60 },
+ { NULL, 0 }
+};
+#endif
+
+extern int sleep_main(int argc, char **argv)
+{
+ unsigned int duration;
+
+#ifdef CONFIG_FEATURE_FANCY_SLEEP
+
+ if (argc < 2) {
+ bb_show_usage();
+ }
+
+ ++argv;
+ duration = 0;
+ do {
+ duration += bb_xgetularg_bnd_sfx(*argv, 10,
+ 0, UINT_MAX-duration,
+ sleep_suffixes);
+ } while (*++argv);
+
+#else /* CONFIG_FEATURE_FANCY_SLEEP */
+
+ if (argc != 2) {
+ bb_show_usage();
+ }
+
+#if UINT_MAX == ULONG_MAX
+ duration = bb_xgetularg10(argv[1]);
+#else
+ duration = bb_xgetularg10_bnd(argv[1], 0, UINT_MAX);
+#endif
+
+#endif /* CONFIG_FEATURE_FANCY_SLEEP */
+
+ if (sleep(duration)) {
+ bb_perror_nomsg_and_die();
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/coreutils/sort.c b/release/src/router/busybox/coreutils/sort.c
new file mode 100644
index 00000000..8cc4d888
--- /dev/null
+++ b/release/src/router/busybox/coreutils/sort.c
@@ -0,0 +1,100 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini sort implementation for busybox
+ *
+ * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 _NOT_ compliant -- a number of options are not supported. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Now does proper error checking on i/o. Plus some space savings.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+static int compare_ascii(const void *x, const void *y)
+{
+ return strcmp(*(char **)x, *(char **)y);
+}
+
+static int compare_numeric(const void *x, const void *y)
+{
+ int z = atoi(*(char **)x) - atoi(*(char **)y);
+ return z ? z : strcmp(*(char **)x, *(char **)y);
+}
+
+int sort_main(int argc, char **argv)
+{
+ FILE *fp;
+ char *line, **lines = NULL;
+ int i, nlines = 0, inc;
+ int (*compare)(const void *, const void *) = compare_ascii;
+
+ int flags;
+
+ bb_default_error_retval = 2;
+
+ flags = bb_getopt_ulflags(argc, argv, "nru");
+ if (flags & 1) {
+ compare = compare_numeric;
+ }
+
+ argv += optind;
+ if (!*argv) {
+ *--argv = "-";
+ }
+
+ do {
+ fp = xgetoptfile_sort_uniq(argv, "r");
+ while ((line = bb_get_chomped_line_from_file(fp)) != NULL) {
+ lines = xrealloc(lines, sizeof(char *) * (nlines + 1));
+ lines[nlines++] = line;
+ }
+ bb_xferror(fp, *argv);
+ bb_fclose_nonstdin(fp);
+ } while (*++argv);
+
+ /* sort it */
+ qsort(lines, nlines, sizeof(char *), compare);
+
+ /* print it */
+ i = 0;
+ --nlines;
+ if ((inc = 1 - (flags & 2)) < 0) { /* reverse */
+ i = nlines;
+ }
+ flags &= 4;
+
+ while (nlines >= 0) {
+ if (!flags || !nlines || strcmp(lines[i+inc], lines[i])) {
+ puts(lines[i]);
+ }
+ i += inc;
+ --nlines;
+ }
+
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}
diff --git a/release/src/router/busybox/coreutils/stty.c b/release/src/router/busybox/coreutils/stty.c
new file mode 100644
index 00000000..bd3a3691
--- /dev/null
+++ b/release/src/router/busybox/coreutils/stty.c
@@ -0,0 +1,1313 @@
+/* vi: set sw=4 ts=4: */
+/* stty -- change and print terminal line settings
+ Copyright (C) 1990-1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Usage: stty [-ag] [-F device] [setting...]
+
+ Options:
+ -a Write all current settings to stdout in human-readable form.
+ -g Write all current settings to stdout in stty-readable form.
+ -F Open and use the specified device instead of stdin
+
+ If no args are given, write to stdout the baud rate and settings that
+ have been changed from their defaults. Mode reading and changes
+ are done on the specified device, or stdin if none was specified.
+
+ David MacKenzie <djm@gnu.ai.mit.edu>
+
+ Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001
+
+ */
+
+//#define TEST
+
+#include <stddef.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include <sys/param.h>
+#include <unistd.h>
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <memory.h>
+#include <fcntl.h>
+#include "busybox.h"
+
+#define STREQ(a, b) (strcmp ((a), (b)) == 0)
+
+
+#ifndef _POSIX_VDISABLE
+# define _POSIX_VDISABLE ((unsigned char) 0)
+#endif
+
+#define Control(c) ((c) & 0x1f)
+/* Canonical values for control characters. */
+#ifndef CINTR
+# define CINTR Control ('c')
+#endif
+#ifndef CQUIT
+# define CQUIT 28
+#endif
+#ifndef CERASE
+# define CERASE 127
+#endif
+#ifndef CKILL
+# define CKILL Control ('u')
+#endif
+#ifndef CEOF
+# define CEOF Control ('d')
+#endif
+#ifndef CEOL
+# define CEOL _POSIX_VDISABLE
+#endif
+#ifndef CSTART
+# define CSTART Control ('q')
+#endif
+#ifndef CSTOP
+# define CSTOP Control ('s')
+#endif
+#ifndef CSUSP
+# define CSUSP Control ('z')
+#endif
+#if defined(VEOL2) && !defined(CEOL2)
+# define CEOL2 _POSIX_VDISABLE
+#endif
+/* ISC renamed swtch to susp for termios, but we'll accept either name. */
+#if defined(VSUSP) && !defined(VSWTCH)
+# define VSWTCH VSUSP
+# define CSWTCH CSUSP
+#endif
+#if defined(VSWTCH) && !defined(CSWTCH)
+# define CSWTCH _POSIX_VDISABLE
+#endif
+
+/* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
+ So the default is to disable `swtch.' */
+#if defined (__sparc__) && defined (__svr4__)
+# undef CSWTCH
+# define CSWTCH _POSIX_VDISABLE
+#endif
+
+#if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */
+# define VWERASE VWERSE
+#endif
+#if defined(VDSUSP) && !defined (CDSUSP)
+# define CDSUSP Control ('y')
+#endif
+#if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
+# define VREPRINT VRPRNT
+#endif
+#if defined(VREPRINT) && !defined(CRPRNT)
+# define CRPRNT Control ('r')
+#endif
+#if defined(VWERASE) && !defined(CWERASE)
+# define CWERASE Control ('w')
+#endif
+#if defined(VLNEXT) && !defined(CLNEXT)
+# define CLNEXT Control ('v')
+#endif
+#if defined(VDISCARD) && !defined(VFLUSHO)
+# define VFLUSHO VDISCARD
+#endif
+#if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */
+# define VFLUSHO VFLUSH
+#endif
+#if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */
+# define ECHOCTL CTLECH
+#endif
+#if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */
+# define ECHOCTL TCTLECH
+#endif
+#if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */
+# define ECHOKE CRTKIL
+#endif
+#if defined(VFLUSHO) && !defined(CFLUSHO)
+# define CFLUSHO Control ('o')
+#endif
+#if defined(VSTATUS) && !defined(CSTATUS)
+# define CSTATUS Control ('t')
+#endif
+
+/* Which speeds to set. */
+enum speed_setting {
+ input_speed, output_speed, both_speeds
+};
+
+/* Which member(s) of `struct termios' a mode uses. */
+enum mode_type {
+ /* Do NOT change the order or values, as mode_type_flag()
+ * depends on them. */
+ control, input, output, local, combination
+};
+
+
+static const char evenp [] = "evenp";
+static const char raw [] = "raw";
+static const char stty_min [] = "min";
+static const char stty_time [] = "time";
+static const char stty_swtch[] = "swtch";
+static const char stty_eol [] = "eol";
+static const char stty_eof [] = "eof";
+static const char parity [] = "parity";
+static const char stty_oddp [] = "oddp";
+static const char stty_nl [] = "nl";
+static const char stty_ek [] = "ek";
+static const char stty_sane [] = "sane";
+static const char cbreak [] = "cbreak";
+static const char stty_pass8[] = "pass8";
+static const char litout [] = "litout";
+static const char cooked [] = "cooked";
+static const char decctlq [] = "decctlq";
+static const char stty_tabs [] = "tabs";
+static const char stty_lcase[] = "lcase";
+static const char stty_LCASE[] = "LCASE";
+static const char stty_crt [] = "crt";
+static const char stty_dec [] = "dec";
+
+
+/* Flags for `struct mode_info'. */
+#define SANE_SET 1 /* Set in `sane' mode. */
+#define SANE_UNSET 2 /* Unset in `sane' mode. */
+#define REV 4 /* Can be turned off by prepending `-'. */
+#define OMIT 8 /* Don't display value. */
+
+/* Each mode. */
+struct mode_info {
+ const char *name; /* Name given on command line. */
+ /* enum mode_type type; */
+ char type; /* Which structure element to change. */
+ char flags; /* Setting and display options. */
+ unsigned short mask; /* Other bits to turn off for this mode. */
+ unsigned long bits; /* Bits to set for this mode. */
+};
+
+#define MI_ENTRY(N,T,F,B,M) { N, T, F, M, B }
+
+static const struct mode_info mode_info[] = {
+ MI_ENTRY("parenb", control, REV, PARENB, 0 ),
+ MI_ENTRY("parodd", control, REV, PARODD, 0 ),
+ MI_ENTRY("cs5", control, 0, CS5, CSIZE),
+ MI_ENTRY("cs6", control, 0, CS6, CSIZE),
+ MI_ENTRY("cs7", control, 0, CS7, CSIZE),
+ MI_ENTRY("cs8", control, 0, CS8, CSIZE),
+ MI_ENTRY("hupcl", control, REV, HUPCL, 0 ),
+ MI_ENTRY("hup", control, REV | OMIT, HUPCL, 0 ),
+ MI_ENTRY("cstopb", control, REV, CSTOPB, 0 ),
+ MI_ENTRY("cread", control, SANE_SET | REV, CREAD, 0 ),
+ MI_ENTRY("clocal", control, REV, CLOCAL, 0 ),
+#ifdef CRTSCTS
+ MI_ENTRY("crtscts", control, REV, CRTSCTS, 0 ),
+#endif
+ MI_ENTRY("ignbrk", input, SANE_UNSET | REV, IGNBRK, 0 ),
+ MI_ENTRY("brkint", input, SANE_SET | REV, BRKINT, 0 ),
+ MI_ENTRY("ignpar", input, REV, IGNPAR, 0 ),
+ MI_ENTRY("parmrk", input, REV, PARMRK, 0 ),
+ MI_ENTRY("inpck", input, REV, INPCK, 0 ),
+ MI_ENTRY("istrip", input, REV, ISTRIP, 0 ),
+ MI_ENTRY("inlcr", input, SANE_UNSET | REV, INLCR, 0 ),
+ MI_ENTRY("igncr", input, SANE_UNSET | REV, IGNCR, 0 ),
+ MI_ENTRY("icrnl", input, SANE_SET | REV, ICRNL, 0 ),
+ MI_ENTRY("ixon", input, REV, IXON, 0 ),
+ MI_ENTRY("ixoff", input, SANE_UNSET | REV, IXOFF, 0 ),
+ MI_ENTRY("tandem", input, REV | OMIT, IXOFF, 0 ),
+#ifdef IUCLC
+ MI_ENTRY("iuclc", input, SANE_UNSET | REV, IUCLC, 0 ),
+#endif
+#ifdef IXANY
+ MI_ENTRY("ixany", input, SANE_UNSET | REV, IXANY, 0 ),
+#endif
+#ifdef IMAXBEL
+ MI_ENTRY("imaxbel", input, SANE_SET | REV, IMAXBEL, 0 ),
+#endif
+ MI_ENTRY("opost", output, SANE_SET | REV, OPOST, 0 ),
+#ifdef OLCUC
+ MI_ENTRY("olcuc", output, SANE_UNSET | REV, OLCUC, 0 ),
+#endif
+#ifdef OCRNL
+ MI_ENTRY("ocrnl", output, SANE_UNSET | REV, OCRNL, 0 ),
+#endif
+#ifdef ONLCR
+ MI_ENTRY("onlcr", output, SANE_SET | REV, ONLCR, 0 ),
+#endif
+#ifdef ONOCR
+ MI_ENTRY("onocr", output, SANE_UNSET | REV, ONOCR, 0 ),
+#endif
+#ifdef ONLRET
+ MI_ENTRY("onlret", output, SANE_UNSET | REV, ONLRET, 0 ),
+#endif
+#ifdef OFILL
+ MI_ENTRY("ofill", output, SANE_UNSET | REV, OFILL, 0 ),
+#endif
+#ifdef OFDEL
+ MI_ENTRY("ofdel", output, SANE_UNSET | REV, OFDEL, 0 ),
+#endif
+#ifdef NLDLY
+ MI_ENTRY("nl1", output, SANE_UNSET, NL1, NLDLY),
+ MI_ENTRY("nl0", output, SANE_SET, NL0, NLDLY),
+#endif
+#ifdef CRDLY
+ MI_ENTRY("cr3", output, SANE_UNSET, CR3, CRDLY),
+ MI_ENTRY("cr2", output, SANE_UNSET, CR2, CRDLY),
+ MI_ENTRY("cr1", output, SANE_UNSET, CR1, CRDLY),
+ MI_ENTRY("cr0", output, SANE_SET, CR0, CRDLY),
+#endif
+
+#ifdef TABDLY
+ MI_ENTRY("tab3", output, SANE_UNSET, TAB3, TABDLY),
+ MI_ENTRY("tab2", output, SANE_UNSET, TAB2, TABDLY),
+ MI_ENTRY("tab1", output, SANE_UNSET, TAB1, TABDLY),
+ MI_ENTRY("tab0", output, SANE_SET, TAB0, TABDLY),
+#else
+# ifdef OXTABS
+ MI_ENTRY("tab3", output, SANE_UNSET, OXTABS, 0 ),
+# endif
+#endif
+
+#ifdef BSDLY
+ MI_ENTRY("bs1", output, SANE_UNSET, BS1, BSDLY),
+ MI_ENTRY("bs0", output, SANE_SET, BS0, BSDLY),
+#endif
+#ifdef VTDLY
+ MI_ENTRY("vt1", output, SANE_UNSET, VT1, VTDLY),
+ MI_ENTRY("vt0", output, SANE_SET, VT0, VTDLY),
+#endif
+#ifdef FFDLY
+ MI_ENTRY("ff1", output, SANE_UNSET, FF1, FFDLY),
+ MI_ENTRY("ff0", output, SANE_SET, FF0, FFDLY),
+#endif
+ MI_ENTRY("isig", local, SANE_SET | REV, ISIG, 0 ),
+ MI_ENTRY("icanon", local, SANE_SET | REV, ICANON, 0 ),
+#ifdef IEXTEN
+ MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 ),
+#endif
+ MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 ),
+ MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 ),
+ MI_ENTRY("crterase", local, REV | OMIT, ECHOE, 0 ),
+ MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 ),
+ MI_ENTRY("echonl", local, SANE_UNSET | REV, ECHONL, 0 ),
+ MI_ENTRY("noflsh", local, SANE_UNSET | REV, NOFLSH, 0 ),
+#ifdef XCASE
+ MI_ENTRY("xcase", local, SANE_UNSET | REV, XCASE, 0 ),
+#endif
+#ifdef TOSTOP
+ MI_ENTRY("tostop", local, SANE_UNSET | REV, TOSTOP, 0 ),
+#endif
+#ifdef ECHOPRT
+ MI_ENTRY("echoprt", local, SANE_UNSET | REV, ECHOPRT, 0 ),
+ MI_ENTRY("prterase", local, REV | OMIT, ECHOPRT, 0 ),
+#endif
+#ifdef ECHOCTL
+ MI_ENTRY("echoctl", local, SANE_SET | REV, ECHOCTL, 0 ),
+ MI_ENTRY("ctlecho", local, REV | OMIT, ECHOCTL, 0 ),
+#endif
+#ifdef ECHOKE
+ MI_ENTRY("echoke", local, SANE_SET | REV, ECHOKE, 0 ),
+ MI_ENTRY("crtkill", local, REV | OMIT, ECHOKE, 0 ),
+#endif
+ MI_ENTRY(evenp, combination, REV | OMIT, 0, 0 ),
+ MI_ENTRY(parity, combination, REV | OMIT, 0, 0 ),
+ MI_ENTRY(stty_oddp, combination, REV | OMIT, 0, 0 ),
+ MI_ENTRY(stty_nl, combination, REV | OMIT, 0, 0 ),
+ MI_ENTRY(stty_ek, combination, OMIT, 0, 0 ),
+ MI_ENTRY(stty_sane, combination, OMIT, 0, 0 ),
+ MI_ENTRY(cooked, combination, REV | OMIT, 0, 0 ),
+ MI_ENTRY(raw, combination, REV | OMIT, 0, 0 ),
+ MI_ENTRY(stty_pass8, combination, REV | OMIT, 0, 0 ),
+ MI_ENTRY(litout, combination, REV | OMIT, 0, 0 ),
+ MI_ENTRY(cbreak, combination, REV | OMIT, 0, 0 ),
+#ifdef IXANY
+ MI_ENTRY(decctlq, combination, REV | OMIT, 0, 0 ),
+#endif
+#if defined (TABDLY) || defined (OXTABS)
+ MI_ENTRY(stty_tabs, combination, REV | OMIT, 0, 0 ),
+#endif
+#if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
+ MI_ENTRY(stty_lcase, combination, REV | OMIT, 0, 0 ),
+ MI_ENTRY(stty_LCASE, combination, REV | OMIT, 0, 0 ),
+#endif
+ MI_ENTRY(stty_crt, combination, OMIT, 0, 0 ),
+ MI_ENTRY(stty_dec, combination, OMIT, 0, 0 ),
+};
+
+static const int NUM_mode_info =
+
+ (sizeof(mode_info) / sizeof(struct mode_info));
+
+/* Control character settings. */
+struct control_info {
+ const char *name; /* Name given on command line. */
+ unsigned char saneval; /* Value to set for `stty sane'. */
+ unsigned char offset; /* Offset in c_cc. */
+};
+
+/* Control characters. */
+
+static const struct control_info control_info[] = {
+ {"intr", CINTR, VINTR},
+ {"quit", CQUIT, VQUIT},
+ {"erase", CERASE, VERASE},
+ {"kill", CKILL, VKILL},
+ {stty_eof, CEOF, VEOF},
+ {stty_eol, CEOL, VEOL},
+#ifdef VEOL2
+ {"eol2", CEOL2, VEOL2},
+#endif
+#ifdef VSWTCH
+ {stty_swtch, CSWTCH, VSWTCH},
+#endif
+ {"start", CSTART, VSTART},
+ {"stop", CSTOP, VSTOP},
+ {"susp", CSUSP, VSUSP},
+#ifdef VDSUSP
+ {"dsusp", CDSUSP, VDSUSP},
+#endif
+#ifdef VREPRINT
+ {"rprnt", CRPRNT, VREPRINT},
+#endif
+#ifdef VWERASE
+ {"werase", CWERASE, VWERASE},
+#endif
+#ifdef VLNEXT
+ {"lnext", CLNEXT, VLNEXT},
+#endif
+#ifdef VFLUSHO
+ {"flush", CFLUSHO, VFLUSHO},
+#endif
+#ifdef VSTATUS
+ {"status", CSTATUS, VSTATUS},
+#endif
+ /* These must be last because of the display routines. */
+ {stty_min, 1, VMIN},
+ {stty_time, 0, VTIME},
+};
+
+static const int NUM_control_info =
+ (sizeof(control_info) / sizeof(struct control_info));
+
+
+static const char * visible(unsigned int ch);
+static int recover_mode(char *arg, struct termios *mode);
+static int screen_columns(void);
+static int set_mode(const struct mode_info *info,
+ int reversed, struct termios *mode);
+static speed_t string_to_baud(const char *arg);
+static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode);
+static void display_all(struct termios *mode, int fd);
+static void display_changed(struct termios *mode, int fd);
+static void display_recoverable(struct termios *mode, int fd);
+static void display_speed(struct termios *mode, int fancy);
+static void display_window_size(int fancy, int fd);
+static void sane_mode(struct termios *mode);
+static void set_control_char(const struct control_info *info,
+ const char *arg, struct termios *mode);
+static void set_speed(enum speed_setting type,
+ const char *arg, struct termios *mode);
+static void set_window_size(int rows, int cols, int fd);
+
+static const char *device_name;
+
+static __attribute__ ((noreturn)) void perror_on_device(const char *fmt)
+{
+ bb_perror_msg_and_die(fmt, device_name);
+}
+
+
+/* The width of the screen, for output wrapping. */
+static int max_col;
+
+/* Current position, to know when to wrap. */
+static int current_col;
+
+/* Print format string MESSAGE and optional args.
+ Wrap to next line first if it won't fit.
+ Print a space first unless MESSAGE will start a new line. */
+
+static void wrapf(const char *message, ...)
+{
+ va_list args;
+ char buf[1024]; /* Plenty long for our needs. */
+ int buflen;
+
+ va_start(args, message);
+ vsprintf(buf, message, args);
+ va_end(args);
+ buflen = strlen(buf);
+ if (current_col + (current_col > 0) + buflen >= max_col) {
+ putchar('\n');
+ current_col = 0;
+ }
+ if (current_col > 0) {
+ putchar(' ');
+ current_col++;
+ }
+ fputs(buf, stdout);
+ current_col += buflen;
+}
+
+static const struct suffix_mult stty_suffixes[] = {
+ {"b", 512 },
+ {"k", 1024},
+ {"B", 1024},
+ {NULL, 0 }
+};
+
+#ifndef TEST
+extern int stty_main(int argc, char **argv)
+#else
+extern int main(int argc, char **argv)
+#endif
+{
+ struct termios mode;
+ void (*output_func)(struct termios *, int);
+ int optc;
+ int require_set_attr;
+ int speed_was_set;
+ int verbose_output;
+ int recoverable_output;
+ int k;
+ int noargs = 1;
+ char * file_name = NULL;
+ int fd;
+
+
+ output_func = display_changed;
+ verbose_output = 0;
+ recoverable_output = 0;
+
+ /* Don't print error messages for unrecognized options. */
+ opterr = 0;
+
+ while ((optc = getopt(argc, argv, "agF:")) != -1) {
+ switch (optc) {
+ case 'a':
+ verbose_output = 1;
+ output_func = display_all;
+ break;
+
+ case 'g':
+ recoverable_output = 1;
+ output_func = display_recoverable;
+ break;
+
+ case 'F':
+ if (file_name)
+ bb_error_msg_and_die("only one device may be specified");
+ file_name = optarg;
+ break;
+
+ default: /* unrecognized option */
+ noargs = 0;
+ break;
+ }
+
+ if (noargs == 0)
+ break;
+ }
+
+ if (optind < argc)
+ noargs = 0;
+
+ /* Specifying both -a and -g gets an error. */
+ if (verbose_output & recoverable_output)
+ bb_error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive");
+
+ /* Specifying any other arguments with -a or -g gets an error. */
+ if (~noargs & (verbose_output | recoverable_output))
+ bb_error_msg_and_die ("modes may not be set when specifying an output style");
+
+ /* FIXME: it'd be better not to open the file until we've verified
+ that all arguments are valid. Otherwise, we could end up doing
+ only some of the requested operations and then failing, probably
+ leaving things in an undesirable state. */
+
+ if (file_name) {
+ int fdflags;
+
+ device_name = file_name;
+ fd = bb_xopen(device_name, O_RDONLY | O_NONBLOCK);
+ if ((fdflags = fcntl(fd, F_GETFL)) == -1
+ || fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
+ perror_on_device("%s: couldn't reset non-blocking mode");
+ } else {
+ fd = 0;
+ device_name = bb_msg_standard_input;
+ }
+
+ /* Initialize to all zeroes so there is no risk memcmp will report a
+ spurious difference in an uninitialized portion of the structure. */
+ memset(&mode, 0, sizeof(mode));
+ if (tcgetattr(fd, &mode))
+ perror_on_device("%s");
+
+ if (verbose_output | recoverable_output | noargs) {
+ max_col = screen_columns();
+ current_col = 0;
+ output_func(&mode, fd);
+ return EXIT_SUCCESS;
+ }
+
+ speed_was_set = 0;
+ require_set_attr = 0;
+ k = 0;
+ while (++k < argc) {
+ int match_found = 0;
+ int reversed = 0;
+ int i;
+
+ if (argv[k][0] == '-') {
+ char *find_dev_opt;
+
+ ++argv[k];
+
+ /* Handle "-a", "-ag", "-aF/dev/foo", "-aF /dev/foo", etc.
+ Find the options that have been parsed. This is really
+ gross, but it's needed because stty SETTINGS look like options to
+ getopt(), so we need to work around things in a really horrible
+ way. If any new options are ever added to stty, the short option
+ MUST NOT be a letter which is the first letter of one of the
+ possible stty settings.
+ */
+ find_dev_opt = strchr(argv[k], 'F'); /* find -*F* */
+ if(find_dev_opt) {
+ if(find_dev_opt[1]==0) /* -*F /dev/foo */
+ k++; /* skip /dev/foo */
+ continue; /* else -*F/dev/foo - no skip */
+ }
+ if(argv[k][0]=='a' || argv[k][0]=='g')
+ continue;
+ /* Is not options - is reverse params */
+ reversed = 1;
+ }
+ for (i = 0; i < NUM_mode_info; ++i)
+ if (STREQ(argv[k], mode_info[i].name)) {
+ match_found = set_mode(&mode_info[i], reversed, &mode);
+ require_set_attr = 1;
+ break;
+ }
+
+ if (match_found == 0 && reversed)
+ bb_error_msg_and_die("invalid argument `%s'", --argv[k]);
+
+ if (match_found == 0)
+ for (i = 0; i < NUM_control_info; ++i)
+ if (STREQ(argv[k], control_info[i].name)) {
+ if (k == argc - 1)
+ bb_error_msg_and_die("missing argument to `%s'", argv[k]);
+ match_found = 1;
+ ++k;
+ set_control_char(&control_info[i], argv[k], &mode);
+ require_set_attr = 1;
+ break;
+ }
+
+ if (match_found == 0) {
+ if (STREQ(argv[k], "ispeed")) {
+ if (k == argc - 1)
+ bb_error_msg_and_die("missing argument to `%s'", argv[k]);
+ ++k;
+ set_speed(input_speed, argv[k], &mode);
+ speed_was_set = 1;
+ require_set_attr = 1;
+ } else if (STREQ(argv[k], "ospeed")) {
+ if (k == argc - 1)
+ bb_error_msg_and_die("missing argument to `%s'", argv[k]);
+ ++k;
+ set_speed(output_speed, argv[k], &mode);
+ speed_was_set = 1;
+ require_set_attr = 1;
+ }
+#ifdef TIOCGWINSZ
+ else if (STREQ(argv[k], "rows")) {
+ if (k == argc - 1)
+ bb_error_msg_and_die("missing argument to `%s'", argv[k]);
+ ++k;
+ set_window_size((int) bb_xparse_number(argv[k], stty_suffixes),
+ -1, fd);
+ } else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) {
+ if (k == argc - 1)
+ bb_error_msg_and_die("missing argument to `%s'", argv[k]);
+ ++k;
+ set_window_size(-1,
+ (int) bb_xparse_number(argv[k], stty_suffixes),
+ fd);
+ } else if (STREQ(argv[k], "size")) {
+ max_col = screen_columns();
+ current_col = 0;
+ display_window_size(0, fd);
+ }
+#endif
+#ifdef HAVE_C_LINE
+ else if (STREQ(argv[k], "line")) {
+ if (k == argc - 1)
+ bb_error_msg_and_die("missing argument to `%s'", argv[k]);
+ ++k;
+ mode.c_line = bb_xparse_number(argv[k], stty_suffixes);
+ require_set_attr = 1;
+ }
+#endif
+ else if (STREQ(argv[k], "speed")) {
+ max_col = screen_columns();
+ display_speed(&mode, 0);
+ } else if (recover_mode(argv[k], &mode) == 1)
+ require_set_attr = 1;
+ else if (string_to_baud(argv[k]) != (speed_t) - 1) {
+ set_speed(both_speeds, argv[k], &mode);
+ speed_was_set = 1;
+ require_set_attr = 1;
+ } else
+ bb_error_msg_and_die("invalid argument `%s'", argv[k]);
+ }
+ }
+
+ if (require_set_attr) {
+ struct termios new_mode;
+
+ if (tcsetattr(fd, TCSADRAIN, &mode))
+ perror_on_device("%s");
+
+ /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
+ it performs *any* of the requested operations. This means it
+ can report `success' when it has actually failed to perform
+ some proper subset of the requested operations. To detect
+ this partial failure, get the current terminal attributes and
+ compare them to the requested ones. */
+
+ /* Initialize to all zeroes so there is no risk memcmp will report a
+ spurious difference in an uninitialized portion of the structure. */
+ memset(&new_mode, 0, sizeof(new_mode));
+ if (tcgetattr(fd, &new_mode))
+ perror_on_device("%s");
+
+ /* Normally, one shouldn't use memcmp to compare structures that
+ may have `holes' containing uninitialized data, but we have been
+ careful to initialize the storage of these two variables to all
+ zeroes. One might think it more efficient simply to compare the
+ modified fields, but that would require enumerating those fields --
+ and not all systems have the same fields in this structure. */
+
+ if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) {
+#ifdef CIBAUD
+ /* SunOS 4.1.3 (at least) has the problem that after this sequence,
+ tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
+ sometimes (m1 != m2). The only difference is in the four bits
+ of the c_cflag field corresponding to the baud rate. To save
+ Sun users a little confusion, don't report an error if this
+ happens. But suppress the error only if we haven't tried to
+ set the baud rate explicitly -- otherwise we'd never give an
+ error for a true failure to set the baud rate. */
+
+ new_mode.c_cflag &= (~CIBAUD);
+ if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0)
+#endif
+ perror_on_device ("%s: unable to perform all requested operations");
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/* Return 0 if not applied because not reversible; otherwise return 1. */
+
+static int
+set_mode(const struct mode_info *info, int reversed, struct termios *mode)
+{
+ tcflag_t *bitsp;
+
+ if (reversed && (info->flags & REV) == 0)
+ return 0;
+
+ bitsp = mode_type_flag(info->type, mode);
+
+ if (bitsp == NULL) {
+ /* Combination mode. */
+ if (info->name == evenp || info->name == parity) {
+ if (reversed)
+ mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
+ else
+ mode->c_cflag =
+ (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
+ } else if (info->name == stty_oddp) {
+ if (reversed)
+ mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
+ else
+ mode->c_cflag =
+ (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
+ } else if (info->name == stty_nl) {
+ if (reversed) {
+ mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
+ mode->c_oflag = (mode->c_oflag
+#ifdef ONLCR
+ | ONLCR
+#endif
+ )
+#ifdef OCRNL
+ & ~OCRNL
+#endif
+#ifdef ONLRET
+ & ~ONLRET
+#endif
+ ;
+ } else {
+ mode->c_iflag = mode->c_iflag & ~ICRNL;
+#ifdef ONLCR
+ mode->c_oflag = mode->c_oflag & ~ONLCR;
+#endif
+ }
+ } else if (info->name == stty_ek) {
+ mode->c_cc[VERASE] = CERASE;
+ mode->c_cc[VKILL] = CKILL;
+ } else if (info->name == stty_sane)
+ sane_mode(mode);
+ else if (info->name == cbreak) {
+ if (reversed)
+ mode->c_lflag |= ICANON;
+ else
+ mode->c_lflag &= ~ICANON;
+ } else if (info->name == stty_pass8) {
+ if (reversed) {
+ mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
+ mode->c_iflag |= ISTRIP;
+ } else {
+ mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
+ mode->c_iflag &= ~ISTRIP;
+ }
+ } else if (info->name == litout) {
+ if (reversed) {
+ mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
+ mode->c_iflag |= ISTRIP;
+ mode->c_oflag |= OPOST;
+ } else {
+ mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
+ mode->c_iflag &= ~ISTRIP;
+ mode->c_oflag &= ~OPOST;
+ }
+ } else if (info->name == raw || info->name == cooked) {
+ if ((info->name[0] == 'r' && reversed)
+ || (info->name[0] == 'c' && !reversed)) {
+ /* Cooked mode. */
+ mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
+ mode->c_oflag |= OPOST;
+ mode->c_lflag |= ISIG | ICANON;
+#if VMIN == VEOF
+ mode->c_cc[VEOF] = CEOF;
+#endif
+#if VTIME == VEOL
+ mode->c_cc[VEOL] = CEOL;
+#endif
+ } else {
+ /* Raw mode. */
+ mode->c_iflag = 0;
+ mode->c_oflag &= ~OPOST;
+ mode->c_lflag &= ~(ISIG | ICANON
+#ifdef XCASE
+ | XCASE
+#endif
+ );
+ mode->c_cc[VMIN] = 1;
+ mode->c_cc[VTIME] = 0;
+ }
+ }
+#ifdef IXANY
+ else if (info->name == decctlq) {
+ if (reversed)
+ mode->c_iflag |= IXANY;
+ else
+ mode->c_iflag &= ~IXANY;
+ }
+#endif
+#ifdef TABDLY
+ else if (info->name == stty_tabs) {
+ if (reversed)
+ mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
+ else
+ mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
+ }
+#else
+# ifdef OXTABS
+ else if (info->name == stty_tabs) {
+ if (reversed)
+ mode->c_oflag = mode->c_oflag | OXTABS;
+ else
+ mode->c_oflag = mode->c_oflag & ~OXTABS;
+ }
+# endif
+#endif
+#if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
+ else if (info->name == stty_lcase || info->name == stty_LCASE) {
+ if (reversed) {
+ mode->c_lflag &= ~XCASE;
+ mode->c_iflag &= ~IUCLC;
+ mode->c_oflag &= ~OLCUC;
+ } else {
+ mode->c_lflag |= XCASE;
+ mode->c_iflag |= IUCLC;
+ mode->c_oflag |= OLCUC;
+ }
+ }
+#endif
+ else if (info->name == stty_crt)
+ mode->c_lflag |= ECHOE
+#ifdef ECHOCTL
+ | ECHOCTL
+#endif
+#ifdef ECHOKE
+ | ECHOKE
+#endif
+ ;
+ else if (info->name == stty_dec) {
+ mode->c_cc[VINTR] = 3; /* ^C */
+ mode->c_cc[VERASE] = 127; /* DEL */
+ mode->c_cc[VKILL] = 21; /* ^U */
+ mode->c_lflag |= ECHOE
+#ifdef ECHOCTL
+ | ECHOCTL
+#endif
+#ifdef ECHOKE
+ | ECHOKE
+#endif
+ ;
+#ifdef IXANY
+ mode->c_iflag &= ~IXANY;
+#endif
+ }
+ } else if (reversed)
+ *bitsp = *bitsp & ~((unsigned long)info->mask) & ~info->bits;
+ else
+ *bitsp = (*bitsp & ~((unsigned long)info->mask)) | info->bits;
+
+ return 1;
+}
+
+static void
+set_control_char(const struct control_info *info, const char *arg,
+ struct termios *mode)
+{
+ unsigned char value;
+
+ if (info->name == stty_min || info->name == stty_time)
+ value = bb_xparse_number(arg, stty_suffixes);
+ else if (arg[0] == '\0' || arg[1] == '\0')
+ value = arg[0];
+ else if (STREQ(arg, "^-") || STREQ(arg, "undef"))
+ value = _POSIX_VDISABLE;
+ else if (arg[0] == '^' && arg[1] != '\0') { /* Ignore any trailing junk. */
+ if (arg[1] == '?')
+ value = 127;
+ else
+ value = arg[1] & ~0140; /* Non-letters get weird results. */
+ } else
+ value = bb_xparse_number(arg, stty_suffixes);
+ mode->c_cc[info->offset] = value;
+}
+
+static void
+set_speed(enum speed_setting type, const char *arg, struct termios *mode)
+{
+ speed_t baud;
+
+ baud = string_to_baud(arg);
+
+ if (type != output_speed) { /* either input or both */
+ cfsetispeed(mode, baud);
+ }
+ if (type != input_speed) { /* either output or both */
+ cfsetospeed(mode, baud);
+ }
+}
+
+#ifdef TIOCGWINSZ
+
+static int get_win_size(int fd, struct winsize *win)
+{
+ int err = ioctl(fd, TIOCGWINSZ, (char *) win);
+
+ return err;
+}
+
+static void
+set_window_size(int rows, int cols, int fd)
+{
+ struct winsize win;
+
+ if (get_win_size(fd, &win)) {
+ if (errno != EINVAL)
+ perror_on_device("%s");
+ memset(&win, 0, sizeof(win));
+ }
+
+ if (rows >= 0)
+ win.ws_row = rows;
+ if (cols >= 0)
+ win.ws_col = cols;
+
+# ifdef TIOCSSIZE
+ /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
+ The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
+ This comment from sys/ttold.h describes Sun's twisted logic - a better
+ test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
+ At any rate, the problem is gone in Solaris 2.x. */
+
+ if (win.ws_row == 0 || win.ws_col == 0) {
+ struct ttysize ttysz;
+
+ ttysz.ts_lines = win.ws_row;
+ ttysz.ts_cols = win.ws_col;
+
+ win.ws_row = win.ws_col = 1;
+
+ if ((ioctl(fd, TIOCSWINSZ, (char *) &win) != 0)
+ || (ioctl(fd, TIOCSSIZE, (char *) &ttysz) != 0)) {
+ perror_on_device("%s");
+ return;
+ }
+# endif
+
+ if (ioctl(fd, TIOCSWINSZ, (char *) &win))
+ perror_on_device("%s");
+}
+
+static void display_window_size(int fancy, int fd)
+{
+ const char *fmt_str = "%s" "\0" "%s: no size information for this device";
+ struct winsize win;
+
+ if (get_win_size(fd, &win)) {
+ if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) {
+ perror_on_device(fmt_str);
+ }
+ } else {
+ wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n",
+ win.ws_row, win.ws_col);
+ if (!fancy)
+ current_col = 0;
+ }
+}
+#endif
+
+static int screen_columns(void)
+{
+ int columns;
+ const char *s;
+
+#ifdef TIOCGWINSZ
+ struct winsize win;
+
+ /* With Solaris 2.[123], this ioctl fails and errno is set to
+ EINVAL for telnet (but not rlogin) sessions.
+ On ISC 3.0, it fails for the console and the serial port
+ (but it works for ptys).
+ It can also fail on any system when stdout isn't a tty.
+ In case of any failure, just use the default. */
+ if (get_win_size(STDOUT_FILENO, &win) == 0 && win.ws_col > 0)
+ return win.ws_col;
+#endif
+
+ columns = 80;
+ if ((s = getenv("COLUMNS"))) {
+ columns = atoi(s);
+ }
+ return columns;
+}
+
+static tcflag_t *mode_type_flag(enum mode_type type, struct termios *mode)
+{
+ static const unsigned char tcflag_offsets[] = {
+ offsetof(struct termios, c_cflag), /* control */
+ offsetof(struct termios, c_iflag), /* input */
+ offsetof(struct termios, c_oflag), /* output */
+ offsetof(struct termios, c_lflag) /* local */
+ };
+
+ if (((unsigned int) type) <= local) {
+ return (tcflag_t *)(((char *) mode) + tcflag_offsets[(int)type]);
+ }
+ return NULL;
+}
+
+static void display_changed(struct termios *mode, int fd)
+{
+ int i;
+ int empty_line;
+ tcflag_t *bitsp;
+ unsigned long mask;
+ enum mode_type prev_type = control;
+
+ display_speed(mode, 1);
+#ifdef HAVE_C_LINE
+ wrapf("line = %d;", mode->c_line);
+#endif
+ putchar('\n');
+ current_col = 0;
+
+ empty_line = 1;
+ for (i = 0; control_info[i].name != stty_min; ++i) {
+ if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
+ continue;
+ /* If swtch is the same as susp, don't print both. */
+#if VSWTCH == VSUSP
+ if (control_info[i].name == stty_swtch)
+ continue;
+#endif
+ /* If eof uses the same slot as min, only print whichever applies. */
+#if VEOF == VMIN
+ if ((mode->c_lflag & ICANON) == 0
+ && (control_info[i].name == stty_eof
+ || control_info[i].name == stty_eol)) continue;
+#endif
+
+ empty_line = 0;
+ wrapf("%s = %s;", control_info[i].name,
+ visible(mode->c_cc[control_info[i].offset]));
+ }
+ if ((mode->c_lflag & ICANON) == 0) {
+ wrapf("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
+ (int) mode->c_cc[VTIME]);
+ } else if (empty_line == 0)
+ putchar('\n');
+ current_col = 0;
+
+ empty_line = 1;
+ for (i = 0; i < NUM_mode_info; ++i) {
+ if (mode_info[i].flags & OMIT)
+ continue;
+ if (mode_info[i].type != prev_type) {
+ if (empty_line == 0) {
+ putchar('\n');
+ current_col = 0;
+ empty_line = 1;
+ }
+ prev_type = mode_info[i].type;
+ }
+
+ bitsp = mode_type_flag(mode_info[i].type, mode);
+ mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
+ if ((*bitsp & mask) == mode_info[i].bits) {
+ if (mode_info[i].flags & SANE_UNSET) {
+ wrapf("%s", mode_info[i].name);
+ empty_line = 0;
+ }
+ }
+ else if ((mode_info[i].flags & (SANE_SET | REV)) ==
+ (SANE_SET | REV)) {
+ wrapf("-%s", mode_info[i].name);
+ empty_line = 0;
+ }
+ }
+ if (empty_line == 0)
+ putchar('\n');
+ current_col = 0;
+}
+
+static void
+display_all(struct termios *mode, int fd)
+{
+ int i;
+ tcflag_t *bitsp;
+ unsigned long mask;
+ enum mode_type prev_type = control;
+
+ display_speed(mode, 1);
+#ifdef TIOCGWINSZ
+ display_window_size(1, fd);
+#endif
+#ifdef HAVE_C_LINE
+ wrapf("line = %d;", mode->c_line);
+#endif
+ putchar('\n');
+ current_col = 0;
+
+ for (i = 0; control_info[i].name != stty_min; ++i) {
+ /* If swtch is the same as susp, don't print both. */
+#if VSWTCH == VSUSP
+ if (control_info[i].name == stty_swtch)
+ continue;
+#endif
+ /* If eof uses the same slot as min, only print whichever applies. */
+#if VEOF == VMIN
+ if ((mode->c_lflag & ICANON) == 0
+ && (control_info[i].name == stty_eof
+ || control_info[i].name == stty_eol)) continue;
+#endif
+ wrapf("%s = %s;", control_info[i].name,
+ visible(mode->c_cc[control_info[i].offset]));
+ }
+#if VEOF == VMIN
+ if ((mode->c_lflag & ICANON) == 0)
+#endif
+ wrapf("min = %d; time = %d;", mode->c_cc[VMIN], mode->c_cc[VTIME]);
+ if (current_col != 0)
+ putchar('\n');
+ current_col = 0;
+
+ for (i = 0; i < NUM_mode_info; ++i) {
+ if (mode_info[i].flags & OMIT)
+ continue;
+ if (mode_info[i].type != prev_type) {
+ putchar('\n');
+ current_col = 0;
+ prev_type = mode_info[i].type;
+ }
+
+ bitsp = mode_type_flag(mode_info[i].type, mode);
+ mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
+ if ((*bitsp & mask) == mode_info[i].bits)
+ wrapf("%s", mode_info[i].name);
+ else if (mode_info[i].flags & REV)
+ wrapf("-%s", mode_info[i].name);
+ }
+ putchar('\n');
+ current_col = 0;
+}
+
+static void display_speed(struct termios *mode, int fancy)
+{
+ unsigned long ispeed, ospeed;
+ const char *fmt_str =
+ "%lu %lu\n\0" "ispeed %lu baud; ospeed %lu baud;\0"
+ "%lu\n\0" "\0\0\0\0" "speed %lu baud;";
+
+ ospeed = ispeed = cfgetispeed(mode);
+ if (ispeed == 0 || ispeed == (ospeed = cfgetospeed(mode))) {
+ ispeed = ospeed; /* in case ispeed was 0 */
+ fmt_str += 43;
+ }
+ if (fancy) {
+ fmt_str += 9;
+ }
+ wrapf(fmt_str, bb_baud_to_value(ispeed), bb_baud_to_value(ospeed));
+ if (!fancy)
+ current_col = 0;
+}
+
+static void display_recoverable(struct termios *mode, int fd)
+{
+ int i;
+
+ printf("%lx:%lx:%lx:%lx",
+ (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
+ (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
+ for (i = 0; i < NCCS; ++i)
+ printf(":%x", (unsigned int) mode->c_cc[i]);
+ putchar('\n');
+}
+
+static int recover_mode(char *arg, struct termios *mode)
+{
+ int i, n;
+ unsigned int chr;
+ unsigned long iflag, oflag, cflag, lflag;
+
+ /* Scan into temporaries since it is too much trouble to figure out
+ the right format for `tcflag_t'. */
+ if (sscanf(arg, "%lx:%lx:%lx:%lx%n",
+ &iflag, &oflag, &cflag, &lflag, &n) != 4)
+ return 0;
+ mode->c_iflag = iflag;
+ mode->c_oflag = oflag;
+ mode->c_cflag = cflag;
+ mode->c_lflag = lflag;
+ arg += n;
+ for (i = 0; i < NCCS; ++i) {
+ if (sscanf(arg, ":%x%n", &chr, &n) != 1)
+ return 0;
+ mode->c_cc[i] = chr;
+ arg += n;
+ }
+
+ /* Fail if there are too many fields. */
+ if (*arg != '\0')
+ return 0;
+
+ return 1;
+}
+
+static speed_t string_to_baud(const char *arg)
+{
+ return bb_value_to_baud(bb_xparse_number(arg, 0));
+}
+
+static void sane_mode(struct termios *mode)
+{
+ int i;
+ tcflag_t *bitsp;
+
+ for (i = 0; i < NUM_control_info; ++i) {
+#if VMIN == VEOF
+ if (control_info[i].name == stty_min)
+ break;
+#endif
+ mode->c_cc[control_info[i].offset] = control_info[i].saneval;
+ }
+
+ for (i = 0; i < NUM_mode_info; ++i) {
+ if (mode_info[i].flags & SANE_SET) {
+ bitsp = mode_type_flag(mode_info[i].type, mode);
+ *bitsp = (*bitsp & ~((unsigned long)mode_info[i].mask))
+ | mode_info[i].bits;
+ } else if (mode_info[i].flags & SANE_UNSET) {
+ bitsp = mode_type_flag(mode_info[i].type, mode);
+ *bitsp = *bitsp & ~((unsigned long)mode_info[i].mask)
+ & ~mode_info[i].bits;
+ }
+ }
+}
+
+/* Return a string that is the printable representation of character CH. */
+/* Adapted from `cat' by Torbjorn Granlund. */
+
+static const char *visible(unsigned int ch)
+{
+ static char buf[10];
+ char *bpout = buf;
+
+ if (ch == _POSIX_VDISABLE) {
+ return "<undef>";
+ }
+
+ if (ch >= 128) {
+ ch -= 128;
+ *bpout++ = 'M';
+ *bpout++ = '-';
+ }
+
+ if (ch < 32) {
+ *bpout++ = '^';
+ *bpout++ = ch + 64;
+ } else if (ch < 127) {
+ *bpout++ = ch;
+ } else {
+ *bpout++ = '^';
+ *bpout++ = '?';
+ }
+
+ *bpout = '\0';
+ return (const char *) buf;
+}
+
+#ifdef TEST
+
+const char *bb_applet_name = "stty";
+
+#endif
diff --git a/release/src/router/busybox/coreutils/sync.c b/release/src/router/busybox/coreutils/sync.c
new file mode 100644
index 00000000..84746311
--- /dev/null
+++ b/release/src/router/busybox/coreutils/sync.c
@@ -0,0 +1,36 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini sync implementation for busybox
+ *
+ * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+extern int sync_main(int argc, char **argv)
+{
+ bb_warn_ignoring_args(argc - 1);
+
+ sync();
+
+ return(EXIT_SUCCESS);
+}
diff --git a/release/src/router/busybox/coreutils/tail.c b/release/src/router/busybox/coreutils/tail.c
new file mode 100644
index 00000000..10b5cd7a
--- /dev/null
+++ b/release/src/router/busybox/coreutils/tail.c
@@ -0,0 +1,339 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini tail implementation for busybox
+ *
+ * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant (need fancy for -c) */
+/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/tail.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Pretty much rewritten to fix numerous bugs and reduce realloc() calls.
+ * Bugs fixed (although I may have forgotten one or two... it was pretty bad)
+ * 1) mixing printf/write without fflush()ing stdout
+ * 2) no check that any open files are present
+ * 3) optstring had -q taking an arg
+ * 4) no error checking on write in some cases, and a warning even then
+ * 5) q and s interaction bug
+ * 6) no check for lseek error
+ * 7) lseek attempted when count==0 even if arg was +0 (from top)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "busybox.h"
+
+static const struct suffix_mult tail_suffixes[] = {
+ { "b", 512 },
+ { "k", 1024 },
+ { "m", 1048576 },
+ { NULL, 0 }
+};
+
+static int status
+#if EXIT_SUCCESS != 0
+ = EXIT_SUCCESS /* If it is 0 (paranoid check), let bss initialize it. */
+#endif
+ ;
+
+static void tail_xprint_header(const char *fmt, const char *filename)
+{
+ /* If we get an output error, there is really no sense in continuing. */
+ if (dprintf(STDOUT_FILENO, fmt, filename) < 0) {
+ bb_perror_nomsg_and_die();
+ }
+}
+
+/* len should probably be size_t */
+static void tail_xbb_full_write(const char *buf, size_t len)
+{
+ /* If we get a write error, there is really no sense in continuing. */
+ if (bb_full_write(STDOUT_FILENO, buf, len) < 0) {
+ bb_perror_nomsg_and_die();
+ }
+}
+
+static ssize_t tail_read(int fd, char *buf, size_t count)
+{
+ ssize_t r;
+
+ if ((r = safe_read(fd, buf, count)) < 0) {
+ bb_perror_msg("read");
+ status = EXIT_FAILURE;
+ }
+
+ return r;
+}
+
+static const char tail_opts[] =
+ "fn:"
+#ifdef CONFIG_FEATURE_FANCY_TAIL
+ "c:qs:v"
+#endif
+ ;
+
+static const char header_fmt[] = "\n==> %s <==\n";
+
+int tail_main(int argc, char **argv)
+{
+ long count = 10;
+ unsigned int sleep_period = 1;
+ int from_top = 0;
+ int follow = 0;
+ int header_threshhold = 1;
+#ifdef CONFIG_FEATURE_FANCY_TAIL
+ int count_bytes = 0;
+#endif
+
+ char *tailbuf;
+ size_t tailbufsize;
+ int taillen = 0;
+ int newline = 0;
+
+ int *fds, nfiles, nread, nwrite, seen, i, opt;
+ char *s, *buf;
+ const char *fmt;
+
+ /* Allow legacy syntax of an initial numeric option without -n. */
+ if (argc >=2 && ((argv[1][0] == '+') || ((argv[1][0] == '-')
+ /* && (isdigit)(argv[1][1]) */
+ && (((unsigned int)(argv[1][1] - '0')) <= 9))))
+ {
+ optind = 2;
+ optarg = argv[1];
+ goto GET_COUNT;
+ }
+
+ while ((opt = getopt(argc, argv, tail_opts)) > 0) {
+ switch (opt) {
+ case 'f':
+ follow = 1;
+ break;
+#ifdef CONFIG_FEATURE_FANCY_TAIL
+ case 'c':
+ count_bytes = 1;
+ /* FALLS THROUGH */
+#endif
+ case 'n':
+ GET_COUNT:
+ count = bb_xgetlarg10_sfx(optarg, tail_suffixes);
+ /* Note: Leading whitespace is an error trapped above. */
+ if (*optarg == '+') {
+ from_top = 1;
+ } else {
+ from_top = 0;
+ }
+ if (count < 0) {
+ count = -count;
+ }
+ break;
+#ifdef CONFIG_FEATURE_FANCY_TAIL
+ case 'q':
+ header_threshhold = INT_MAX;
+ break;
+ case 's':
+ sleep_period =bb_xgetularg10_bnd(optarg, 0, UINT_MAX);
+ break;
+ case 'v':
+ header_threshhold = 0;
+ break;
+#endif
+ default:
+ bb_show_usage();
+ }
+ }
+
+ /* open all the files */
+ fds = (int *)xmalloc(sizeof(int) * (argc - optind + 1));
+
+ argv += optind;
+ nfiles = i = 0;
+
+ if ((argc -= optind) == 0) {
+ struct stat statbuf;
+
+ if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) {
+ follow = 0;
+ }
+ /* --argv; */
+ *argv = (char *) bb_msg_standard_input;
+ goto DO_STDIN;
+ }
+
+ do {
+ if ((argv[i][0] == '-') && !argv[i][1]) {
+ DO_STDIN:
+ fds[nfiles] = STDIN_FILENO;
+ } else if ((fds[nfiles] = open(argv[i], O_RDONLY)) < 0) {
+ bb_perror_msg("%s", argv[i]);
+ status = EXIT_FAILURE;
+ continue;
+ }
+ argv[nfiles] = argv[i];
+ ++nfiles;
+ } while (++i < argc);
+
+ if (!nfiles) {
+ bb_error_msg_and_die("no files");
+ }
+
+ tailbufsize = BUFSIZ;
+#ifdef CONFIG_FEATURE_FANCY_TAIL
+ /* tail the files */
+ if (from_top < count_bytes) { /* Each is 0 or 1, so true iff 0 < 1. */
+ /* Hence, !from_top && count_bytes */
+ if (tailbufsize < count) {
+ tailbufsize = count + BUFSIZ;
+ }
+ }
+#endif
+ buf = tailbuf = xmalloc(tailbufsize);
+
+ fmt = header_fmt + 1; /* Skip header leading newline on first output. */
+ i = 0;
+ do {
+ /* Be careful. It would be possible to optimize the count-bytes
+ * case if the file is seekable. If you do though, remember that
+ * starting file position may not be the beginning of the file.
+ * Beware of backing up too far. See example in wc.c.
+ */
+ if ((!(count|from_top)) && (lseek(fds[i], 0, SEEK_END) >= 0)) {
+ continue;
+ }
+
+ if (nfiles > header_threshhold) {
+ tail_xprint_header(fmt, argv[i]);
+ fmt = header_fmt;
+ }
+
+ buf = tailbuf;
+ taillen = 0;
+ seen = 1;
+
+ while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
+ if (from_top) {
+ nwrite = nread;
+ if (seen < count) {
+#ifdef CONFIG_FEATURE_FANCY_TAIL
+ if (count_bytes) {
+ nwrite -= (count - seen);
+ seen = count;
+ } else
+#endif
+ {
+ s = buf;
+ do {
+ --nwrite;
+ if ((*s++ == '\n') && (++seen == count)) {
+ break;
+ }
+ } while (nwrite);
+ }
+ }
+ tail_xbb_full_write(buf + nread - nwrite, nwrite);
+ } else if (count) {
+#ifdef CONFIG_FEATURE_FANCY_TAIL
+ if (count_bytes) {
+ taillen += nread;
+ if (taillen > count) {
+ memmove(tailbuf, tailbuf + taillen - count, count);
+ taillen = count;
+ }
+ } else
+#endif
+ {
+ int k = nread;
+ int nbuf = 0;
+
+ while (k) {
+ --k;
+ if (buf[k] == '\n') {
+ ++nbuf;
+ }
+ }
+
+ if (newline + nbuf < count) {
+ newline += nbuf;
+ taillen += nread;
+
+ } else {
+ int extra = 0;
+ if (buf[nread-1] != '\n') {
+ extra = 1;
+ }
+
+ k = newline + nbuf + extra - count;
+ s = tailbuf;
+ while (k) {
+ if (*s == '\n') {
+ --k;
+ }
+ ++s;
+ }
+
+ taillen += nread - (s - tailbuf);
+ memmove(tailbuf, s, taillen);
+ newline = count - extra;
+ }
+ if (tailbufsize < taillen + BUFSIZ) {
+ tailbufsize = taillen + BUFSIZ;
+ tailbuf = xrealloc(tailbuf, tailbufsize);
+ }
+ }
+ buf = tailbuf + taillen;
+ }
+ }
+
+ if (!from_top) {
+ tail_xbb_full_write(tailbuf, taillen);
+ }
+
+ taillen = 0;
+ } while (++i < nfiles);
+
+ buf = xrealloc(tailbuf, BUFSIZ);
+
+ fmt = NULL;
+
+ while (follow) {
+ sleep(sleep_period);
+ i = 0;
+ do {
+ if (nfiles > header_threshhold) {
+ fmt = header_fmt;
+ }
+ while ((nread = tail_read(fds[i], buf, sizeof(buf))) > 0) {
+ if (fmt) {
+ tail_xprint_header(fmt, argv[i]);
+ fmt = NULL;
+ }
+ tail_xbb_full_write(buf, nread);
+ }
+ } while (++i < nfiles);
+ }
+
+ return status;
+}
diff --git a/release/src/router/busybox/coreutils/tee.c b/release/src/router/busybox/coreutils/tee.c
new file mode 100644
index 00000000..7e86f2e2
--- /dev/null
+++ b/release/src/router/busybox/coreutils/tee.c
@@ -0,0 +1,115 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tee implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include "busybox.h"
+
+int tee_main(int argc, char **argv)
+{
+ const char *mode = "w\0a";
+ FILE **files;
+ FILE **p;
+ char **filenames;
+ int flags;
+ int retval = EXIT_SUCCESS;
+#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO
+ size_t c;
+ RESERVE_CONFIG_BUFFER(buf, BUFSIZ);
+#else
+ int c;
+#endif
+
+ flags = bb_getopt_ulflags(argc, argv, "ia"); /* 'a' must be 2nd */
+
+ mode += (flags & 2); /* Since 'a' is the 2nd option... */
+
+ if (flags & 1) {
+ signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction.*/
+ }
+
+ /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
+ * that doesn't consume all its input. Good idea... */
+ signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction.*/
+
+ /* Allocate an array of FILE *'s, with one extra for a sentinal. */
+ p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2));
+ *p = stdout;
+ argv += optind - 1;
+ filenames = argv - 1;
+ *filenames = (char *) bb_msg_standard_input; /* for later */
+ goto GOT_NEW_FILE;
+
+ do {
+ if ((*p = bb_wfopen(*argv, mode)) == NULL) {
+ retval = EXIT_FAILURE;
+ continue;
+ }
+ filenames[(int)(p - files)] = *argv;
+ GOT_NEW_FILE:
+ setbuf(*p, NULL); /* tee must not buffer output. */
+ ++p;
+ } while (*++argv);
+
+ *p = NULL; /* Store the sentinal value. */
+
+#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO
+ while ((c = fread(buf, 1, BUFSIZ, stdin)) != 0) {
+ for (p=files ; *p ; p++) {
+ fwrite(buf, 1, c, *p);
+ }
+ }
+
+#ifdef CONFIG_FEATURE_CLEAN_UP
+ RELEASE_CONFIG_BUFFER(buf);
+#endif
+
+#else
+ while ((c = getchar()) != EOF) {
+ for (p=files ; *p ; p++) {
+ putc(c, *p);
+ }
+ }
+#endif
+
+ /* Now we need to check for i/o errors on stdin and the various
+ * output files. Since we know that the first entry in the output
+ * file table is stdout, we can save one "if ferror" test by
+ * setting the first entry to stdin and checking stdout error
+ * status with bb_fflush_stdout_and_exit()... although fflush()ing
+ * is unnecessary here. */
+
+ p = files;
+ *p = stdin;
+ do { /* Now check for (input and) output errors. */
+ /* Checking ferror should be sufficient, but we may want to fclose.
+ * If we do, remember not to close stdin! */
+ bb_xferror(*p, filenames[(int)(p - files)]);
+ } while (*++p);
+
+ bb_fflush_stdout_and_exit(retval);
+}
diff --git a/release/src/router/busybox/coreutils/test.c b/release/src/router/busybox/coreutils/test.c
new file mode 100644
index 00000000..2ad326ea
--- /dev/null
+++ b/release/src/router/busybox/coreutils/test.c
@@ -0,0 +1,545 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * test implementation for busybox
+ *
+ * Copyright (c) by a whole pile of folks:
+ *
+ * test(1); version 7-like -- author Erik Baalbergen
+ * modified by Eric Gisin to be used as built-in.
+ * modified by Arnold Robbins to add SVR3 compatibility
+ * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
+ * modified by J.T. Conklin for NetBSD.
+ * modified by Herbert Xu to be used as built-in in ash.
+ * modified by Erik Andersen <andersen@codepoet.org> to be used
+ * in busybox.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Original copyright notice states:
+ * "This program is in the Public Domain."
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include "busybox.h"
+
+/* test(1) accepts the following grammar:
+ oexpr ::= aexpr | aexpr "-o" oexpr ;
+ aexpr ::= nexpr | nexpr "-a" aexpr ;
+ nexpr ::= primary | "!" primary
+ primary ::= unary-operator operand
+ | operand binary-operator operand
+ | operand
+ | "(" oexpr ")"
+ ;
+ unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
+ "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
+
+ binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
+ "-nt"|"-ot"|"-ef";
+ operand ::= <any legal UNIX file name>
+*/
+
+enum token {
+ EOI,
+ FILRD,
+ FILWR,
+ FILEX,
+ FILEXIST,
+ FILREG,
+ FILDIR,
+ FILCDEV,
+ FILBDEV,
+ FILFIFO,
+ FILSOCK,
+ FILSYM,
+ FILGZ,
+ FILTT,
+ FILSUID,
+ FILSGID,
+ FILSTCK,
+ FILNT,
+ FILOT,
+ FILEQ,
+ FILUID,
+ FILGID,
+ STREZ,
+ STRNZ,
+ STREQ,
+ STRNE,
+ STRLT,
+ STRGT,
+ INTEQ,
+ INTNE,
+ INTGE,
+ INTGT,
+ INTLE,
+ INTLT,
+ UNOT,
+ BAND,
+ BOR,
+ LPAREN,
+ RPAREN,
+ OPERAND
+};
+
+enum token_types {
+ UNOP,
+ BINOP,
+ BUNOP,
+ BBINOP,
+ PAREN
+};
+
+static const struct t_op {
+ const char *op_text;
+ short op_num, op_type;
+} ops[] = {
+ {
+ "-r", FILRD, UNOP}, {
+ "-w", FILWR, UNOP}, {
+ "-x", FILEX, UNOP}, {
+ "-e", FILEXIST, UNOP}, {
+ "-f", FILREG, UNOP}, {
+ "-d", FILDIR, UNOP}, {
+ "-c", FILCDEV, UNOP}, {
+ "-b", FILBDEV, UNOP}, {
+ "-p", FILFIFO, UNOP}, {
+ "-u", FILSUID, UNOP}, {
+ "-g", FILSGID, UNOP}, {
+ "-k", FILSTCK, UNOP}, {
+ "-s", FILGZ, UNOP}, {
+ "-t", FILTT, UNOP}, {
+ "-z", STREZ, UNOP}, {
+ "-n", STRNZ, UNOP}, {
+ "-h", FILSYM, UNOP}, /* for backwards compat */
+ {
+ "-O", FILUID, UNOP}, {
+ "-G", FILGID, UNOP}, {
+ "-L", FILSYM, UNOP}, {
+ "-S", FILSOCK, UNOP}, {
+ "=", STREQ, BINOP}, {
+ "!=", STRNE, BINOP}, {
+ "<", STRLT, BINOP}, {
+ ">", STRGT, BINOP}, {
+ "-eq", INTEQ, BINOP}, {
+ "-ne", INTNE, BINOP}, {
+ "-ge", INTGE, BINOP}, {
+ "-gt", INTGT, BINOP}, {
+ "-le", INTLE, BINOP}, {
+ "-lt", INTLT, BINOP}, {
+ "-nt", FILNT, BINOP}, {
+ "-ot", FILOT, BINOP}, {
+ "-ef", FILEQ, BINOP}, {
+ "!", UNOT, BUNOP}, {
+ "-a", BAND, BBINOP}, {
+ "-o", BOR, BBINOP}, {
+ "(", LPAREN, PAREN}, {
+ ")", RPAREN, PAREN}, {
+ 0, 0, 0}
+};
+
+static char **t_wp;
+static struct t_op const *t_wp_op;
+static gid_t *group_array = NULL;
+static int ngroups;
+
+static enum token t_lex(char *s);
+static int oexpr(enum token n);
+static int aexpr(enum token n);
+static int nexpr(enum token n);
+static int binop(void);
+static int primary(enum token n);
+static int filstat(char *nm, enum token mode);
+static int getn(const char *s);
+static int newerf(const char *f1, const char *f2);
+static int olderf(const char *f1, const char *f2);
+static int equalf(const char *f1, const char *f2);
+static void syntax(const char *op, const char *msg);
+static int test_eaccess(char *path, int mode);
+static int is_a_group_member(gid_t gid);
+static void initialize_group_array(void);
+
+extern int test_main(int argc, char **argv)
+{
+ int res;
+
+ if (strcmp(bb_applet_name, "[") == 0) {
+ if (strcmp(argv[--argc], "]"))
+ bb_error_msg_and_die("missing ]");
+ argv[argc] = NULL;
+ }
+ /* Implement special cases from POSIX.2, section 4.62.4 */
+ switch (argc) {
+ case 1:
+ exit(1);
+ case 2:
+ exit(*argv[1] == '\0');
+ case 3:
+ if (argv[1][0] == '!' && argv[1][1] == '\0') {
+ exit(!(*argv[2] == '\0'));
+ }
+ break;
+ case 4:
+ if (argv[1][0] != '!' || argv[1][1] != '\0') {
+ if (t_lex(argv[2]), t_wp_op && t_wp_op->op_type == BINOP) {
+ t_wp = &argv[1];
+ exit(binop() == 0);
+ }
+ }
+ break;
+ case 5:
+ if (argv[1][0] == '!' && argv[1][1] == '\0') {
+ if (t_lex(argv[3]), t_wp_op && t_wp_op->op_type == BINOP) {
+ t_wp = &argv[2];
+ exit(!(binop() == 0));
+ }
+ }
+ break;
+ }
+
+ t_wp = &argv[1];
+ res = !oexpr(t_lex(*t_wp));
+
+ if (*t_wp != NULL && *++t_wp != NULL)
+ syntax(*t_wp, "unknown operand");
+
+ return (res);
+}
+
+static void syntax(const char *op, const char *msg)
+{
+ if (op && *op) {
+ bb_error_msg_and_die("%s: %s", op, msg);
+ } else {
+ bb_error_msg_and_die("%s", msg);
+ }
+}
+
+static int oexpr(enum token n)
+{
+ int res;
+
+ res = aexpr(n);
+ if (t_lex(*++t_wp) == BOR) {
+ return oexpr(t_lex(*++t_wp)) || res;
+ }
+ t_wp--;
+ return res;
+}
+
+static int aexpr(enum token n)
+{
+ int res;
+
+ res = nexpr(n);
+ if (t_lex(*++t_wp) == BAND)
+ return aexpr(t_lex(*++t_wp)) && res;
+ t_wp--;
+ return res;
+}
+
+static int nexpr(enum token n)
+{
+ if (n == UNOT)
+ return !nexpr(t_lex(*++t_wp));
+ return primary(n);
+}
+
+static int primary(enum token n)
+{
+ int res;
+
+ if (n == EOI) {
+ syntax(NULL, "argument expected");
+ }
+ if (n == LPAREN) {
+ res = oexpr(t_lex(*++t_wp));
+ if (t_lex(*++t_wp) != RPAREN)
+ syntax(NULL, "closing paren expected");
+ return res;
+ }
+ if (t_wp_op && t_wp_op->op_type == UNOP) {
+ /* unary expression */
+ if (*++t_wp == NULL)
+ syntax(t_wp_op->op_text, "argument expected");
+ switch (n) {
+ case STREZ:
+ return strlen(*t_wp) == 0;
+ case STRNZ:
+ return strlen(*t_wp) != 0;
+ case FILTT:
+ return isatty(getn(*t_wp));
+ default:
+ return filstat(*t_wp, n);
+ }
+ }
+
+ if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) {
+ return binop();
+ }
+
+ return strlen(*t_wp) > 0;
+}
+
+static int binop()
+{
+ const char *opnd1, *opnd2;
+ struct t_op const *op;
+
+ opnd1 = *t_wp;
+ (void) t_lex(*++t_wp);
+ op = t_wp_op;
+
+ if ((opnd2 = *++t_wp) == (char *) 0)
+ syntax(op->op_text, "argument expected");
+
+ switch (op->op_num) {
+ case STREQ:
+ return strcmp(opnd1, opnd2) == 0;
+ case STRNE:
+ return strcmp(opnd1, opnd2) != 0;
+ case STRLT:
+ return strcmp(opnd1, opnd2) < 0;
+ case STRGT:
+ return strcmp(opnd1, opnd2) > 0;
+ case INTEQ:
+ return getn(opnd1) == getn(opnd2);
+ case INTNE:
+ return getn(opnd1) != getn(opnd2);
+ case INTGE:
+ return getn(opnd1) >= getn(opnd2);
+ case INTGT:
+ return getn(opnd1) > getn(opnd2);
+ case INTLE:
+ return getn(opnd1) <= getn(opnd2);
+ case INTLT:
+ return getn(opnd1) < getn(opnd2);
+ case FILNT:
+ return newerf(opnd1, opnd2);
+ case FILOT:
+ return olderf(opnd1, opnd2);
+ case FILEQ:
+ return equalf(opnd1, opnd2);
+ }
+ /* NOTREACHED */
+ return 1;
+}
+
+static int filstat(char *nm, enum token mode)
+{
+ struct stat s;
+ unsigned int i;
+
+ if (mode == FILSYM) {
+#ifdef S_IFLNK
+ if (lstat(nm, &s) == 0) {
+ i = S_IFLNK;
+ goto filetype;
+ }
+#endif
+ return 0;
+ }
+
+ if (stat(nm, &s) != 0)
+ return 0;
+
+ switch (mode) {
+ case FILRD:
+ return test_eaccess(nm, R_OK) == 0;
+ case FILWR:
+ return test_eaccess(nm, W_OK) == 0;
+ case FILEX:
+ return test_eaccess(nm, X_OK) == 0;
+ case FILEXIST:
+ return 1;
+ case FILREG:
+ i = S_IFREG;
+ goto filetype;
+ case FILDIR:
+ i = S_IFDIR;
+ goto filetype;
+ case FILCDEV:
+ i = S_IFCHR;
+ goto filetype;
+ case FILBDEV:
+ i = S_IFBLK;
+ goto filetype;
+ case FILFIFO:
+#ifdef S_IFIFO
+ i = S_IFIFO;
+ goto filetype;
+#else
+ return 0;
+#endif
+ case FILSOCK:
+#ifdef S_IFSOCK
+ i = S_IFSOCK;
+ goto filetype;
+#else
+ return 0;
+#endif
+ case FILSUID:
+ i = S_ISUID;
+ goto filebit;
+ case FILSGID:
+ i = S_ISGID;
+ goto filebit;
+ case FILSTCK:
+ i = S_ISVTX;
+ goto filebit;
+ case FILGZ:
+ return s.st_size > 0L;
+ case FILUID:
+ return s.st_uid == geteuid();
+ case FILGID:
+ return s.st_gid == getegid();
+ default:
+ return 1;
+ }
+
+ filetype:
+ return ((s.st_mode & S_IFMT) == i);
+
+ filebit:
+ return ((s.st_mode & i) != 0);
+}
+
+static enum token t_lex(char *s)
+{
+ struct t_op const *op = ops;
+
+ if (s == 0) {
+ t_wp_op = (struct t_op *) 0;
+ return EOI;
+ }
+ while (op->op_text) {
+ if (strcmp(s, op->op_text) == 0) {
+ t_wp_op = op;
+ return op->op_num;
+ }
+ op++;
+ }
+ t_wp_op = (struct t_op *) 0;
+ return OPERAND;
+}
+
+/* atoi with error detection */
+static int getn(const char *s)
+{
+ char *p;
+ long r;
+
+ errno = 0;
+ r = strtol(s, &p, 10);
+
+ if (errno != 0)
+ bb_error_msg_and_die("%s: out of range", s);
+
+ /* p = bb_skip_whitespace(p); avoid const warning */
+ if (*(bb_skip_whitespace(p)))
+ bb_error_msg_and_die("%s: bad number", s);
+
+ return (int) r;
+}
+
+static int newerf(const char *f1, const char *f2)
+{
+ struct stat b1, b2;
+
+ return (stat(f1, &b1) == 0 &&
+ stat(f2, &b2) == 0 && b1.st_mtime > b2.st_mtime);
+}
+
+static int olderf(const char *f1, const char *f2)
+{
+ struct stat b1, b2;
+
+ return (stat(f1, &b1) == 0 &&
+ stat(f2, &b2) == 0 && b1.st_mtime < b2.st_mtime);
+}
+
+static int equalf(const char *f1, const char *f2)
+{
+ struct stat b1, b2;
+
+ return (stat(f1, &b1) == 0 &&
+ stat(f2, &b2) == 0 &&
+ b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino);
+}
+
+/* Do the same thing access(2) does, but use the effective uid and gid,
+ and don't make the mistake of telling root that any file is
+ executable. */
+static int test_eaccess(char *path, int mode)
+{
+ struct stat st;
+ unsigned int euid = geteuid();
+
+ if (stat(path, &st) < 0)
+ return (-1);
+
+ if (euid == 0) {
+ /* Root can read or write any file. */
+ if (mode != X_OK)
+ return (0);
+
+ /* Root can execute any file that has any one of the execute
+ bits set. */
+ if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
+ return (0);
+ }
+
+ if (st.st_uid == euid) /* owner */
+ mode <<= 6;
+ else if (is_a_group_member(st.st_gid))
+ mode <<= 3;
+
+ if (st.st_mode & mode)
+ return (0);
+
+ return (-1);
+}
+
+static void initialize_group_array()
+{
+ ngroups = getgroups(0, NULL);
+ group_array = xrealloc(group_array, ngroups * sizeof(gid_t));
+ getgroups(ngroups, group_array);
+}
+
+/* Return non-zero if GID is one that we have in our groups list. */
+static int is_a_group_member(gid_t gid)
+{
+ register int i;
+
+ /* Short-circuit if possible, maybe saving a call to getgroups(). */
+ if (gid == getgid() || gid == getegid())
+ return (1);
+
+ if (ngroups == 0)
+ initialize_group_array();
+
+ /* Search through the list looking for GID. */
+ for (i = 0; i < ngroups; i++)
+ if (gid == group_array[i])
+ return (1);
+
+ return (0);
+}
diff --git a/release/src/router/busybox/coreutils/touch.c b/release/src/router/busybox/coreutils/touch.c
new file mode 100644
index 00000000..3d780e16
--- /dev/null
+++ b/release/src/router/busybox/coreutils/touch.c
@@ -0,0 +1,76 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini touch implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 _NOT_ compliant -- options -a, -m, -r, -t not supported. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/touch.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Previous version called open() and then utime(). While this will be
+ * be necessary to implement -r and -t, it currently only makes things bigger.
+ * Also, exiting on a failure was a bug. All args should be processed.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <utime.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+extern int touch_main(int argc, char **argv)
+{
+ int fd;
+ int flags;
+ int status = EXIT_SUCCESS;
+
+ flags = bb_getopt_ulflags(argc, argv, "c");
+
+ argv += optind;
+
+ if (!*argv) {
+ bb_show_usage();
+ }
+
+ do {
+ if (utime(*argv, NULL)) {
+ if (errno == ENOENT) { /* no such file*/
+ if (flags & 1) { /* Creation is disabled, so ignore. */
+ continue;
+ }
+ /* Try to create the file. */
+ fd = open(*argv, O_RDWR | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
+ );
+ if ((fd >= 0) && !close(fd)) {
+ continue;
+ }
+ }
+ status = EXIT_FAILURE;
+ bb_perror_msg("%s", *argv);
+ }
+ } while (*++argv);
+
+ return status;
+}
diff --git a/release/src/router/busybox/coreutils/tr.c b/release/src/router/busybox/coreutils/tr.c
new file mode 100644
index 00000000..4e69dc89
--- /dev/null
+++ b/release/src/router/busybox/coreutils/tr.c
@@ -0,0 +1,248 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini tr implementation for busybox
+ *
+ * Copyright (c) Michiel Huisjes
+ *
+ * This version of tr is adapted from Minix tr and was modified
+ * by Erik Andersen <andersen@codepoet.org> to be used in busybox.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Original copyright notice is retained at the end of this file.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "busybox.h"
+
+/* This must be a #define, since when CONFIG_DEBUG and BUFFERS_GO_IN_BSS are
+ * enabled, we otherwise get a "storage size isn't constant error. */
+#define ASCII 0377
+
+/* some "globals" shared across this file */
+static char com_fl, del_fl, sq_fl;
+static short in_index, out_index;
+/* these last are pointers to static buffers declared in tr_main */
+static unsigned char *poutput, *pinput;
+static unsigned char *pvector;
+static char *pinvec, *poutvec;
+
+
+static void convert(void)
+{
+ short read_chars = 0;
+ short c, coded;
+ short last = -1;
+
+ for (;;) {
+ if (in_index == read_chars) {
+ if ((read_chars = read(0, (char *) pinput, BUFSIZ)) <= 0) {
+ if (write(1, (char *) poutput, out_index) != out_index)
+ bb_error_msg(bb_msg_write_error);
+ exit(0);
+ }
+ in_index = 0;
+ }
+ c = pinput[in_index++];
+ coded = pvector[c];
+ if (del_fl && pinvec[c])
+ continue;
+ if (sq_fl && last == coded && (pinvec[c] || poutvec[coded]))
+ continue;
+ poutput[out_index++] = last = coded;
+ if (out_index == BUFSIZ) {
+ if (write(1, (char *) poutput, out_index) != out_index)
+ bb_error_msg_and_die(bb_msg_write_error);
+ out_index = 0;
+ }
+ }
+
+ /* NOTREACHED */
+}
+
+static void map(register unsigned char *string1, unsigned int string1_len,
+ register unsigned char *string2, unsigned int string2_len)
+{
+ unsigned char last = '0';
+ unsigned int i, j;
+
+ for (j = 0, i = 0; i < string1_len; i++) {
+ if (string2_len <= j)
+ pvector[string1[i]] = last;
+ else
+ pvector[string1[i]] = last = string2[j++];
+ }
+}
+
+/* supported constructs:
+ * Ranges, e.g., [0-9] ==> 0123456789
+ * Escapes, e.g., \a ==> Control-G
+ */
+static unsigned int expand(const char *arg, register unsigned char *buffer)
+{
+ unsigned char *buffer_start = buffer;
+ int i, ac;
+
+ while (*arg) {
+ if (*arg == '\\') {
+ arg++;
+ *buffer++ = bb_process_escape_sequence(&arg);
+ } else if (*(arg+1) == '-') {
+ ac = *(arg+2);
+ if(ac == 0) {
+ *buffer++ = *arg++;
+ continue;
+ }
+ i = *arg;
+ while (i <= ac)
+ *buffer++ = i++;
+ arg += 3; /* Skip the assumed a-z */
+ } else if (*arg == '[') {
+ arg++;
+ i = *arg++;
+ if (*arg++ != '-') {
+ *buffer++ = '[';
+ arg -= 2;
+ continue;
+ }
+ ac = *arg++;
+ while (i <= ac)
+ *buffer++ = i++;
+ arg++; /* Skip the assumed ']' */
+ } else
+ *buffer++ = *arg++;
+ }
+
+ return (buffer - buffer_start);
+}
+
+static int complement(unsigned char *buffer, int buffer_len)
+{
+ register short i, j, ix;
+ char conv[ASCII + 2];
+
+ ix = 0;
+ for (i = 0; i <= ASCII; i++) {
+ for (j = 0; j < buffer_len; j++)
+ if (buffer[j] == i)
+ break;
+ if (j == buffer_len)
+ conv[ix++] = i & ASCII;
+ }
+ memcpy(buffer, conv, ix);
+ return ix;
+}
+
+extern int tr_main(int argc, char **argv)
+{
+ register unsigned char *ptr;
+ int output_length=0, input_length;
+ int idx = 1;
+ int i;
+ RESERVE_CONFIG_BUFFER(output, BUFSIZ);
+ RESERVE_CONFIG_BUFFER(input, BUFSIZ);
+ RESERVE_CONFIG_UBUFFER(vector, ASCII+1);
+ RESERVE_CONFIG_BUFFER(invec, ASCII+1);
+ RESERVE_CONFIG_BUFFER(outvec, ASCII+1);
+
+ /* ... but make them available globally */
+ poutput = output;
+ pinput = input;
+ pvector = vector;
+ pinvec = invec;
+ poutvec = outvec;
+
+ if (argc > 1 && argv[idx][0] == '-') {
+ for (ptr = (unsigned char *) &argv[idx][1]; *ptr; ptr++) {
+ switch (*ptr) {
+ case 'c':
+ com_fl = TRUE;
+ break;
+ case 'd':
+ del_fl = TRUE;
+ break;
+ case 's':
+ sq_fl = TRUE;
+ break;
+ default:
+ bb_show_usage();
+ }
+ }
+ idx++;
+ }
+ for (i = 0; i <= ASCII; i++) {
+ vector[i] = i;
+ invec[i] = outvec[i] = FALSE;
+ }
+
+ if (argv[idx] != NULL) {
+ input_length = expand(argv[idx++], input);
+ if (com_fl)
+ input_length = complement(input, input_length);
+ if (argv[idx] != NULL) {
+ if (*argv[idx] == '\0')
+ bb_error_msg_and_die("STRING2 cannot be empty");
+ output_length = expand(argv[idx], output);
+ map(input, input_length, output, output_length);
+ }
+ for (i = 0; i < input_length; i++)
+ invec[(int)input[i]] = TRUE;
+ for (i = 0; i < output_length; i++)
+ outvec[(int)output[i]] = TRUE;
+ }
+ convert();
+ return (0);
+}
+
+/*
+ * Copyright (c) 1987,1997, Prentice Hall
+ * All rights reserved.
+ *
+ * Redistribution and use of the MINIX operating system in source and
+ * binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Prentice Hall nor the names of the software
+ * authors or contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, 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 PRENTICE HALL OR ANY AUTHORS 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.
+ *
+ */
+
diff --git a/release/src/router/busybox/coreutils/true.c b/release/src/router/busybox/coreutils/true.c
new file mode 100644
index 00000000..d19e749a
--- /dev/null
+++ b/release/src/router/busybox/coreutils/true.c
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini true implementation for busybox
+ *
+ * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/true.html */
+
+#include <stdlib.h>
+#include "busybox.h"
+
+extern int true_main(int argc, char **argv)
+{
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/coreutils/tty.c b/release/src/router/busybox/coreutils/tty.c
new file mode 100644
index 00000000..cd2c784f
--- /dev/null
+++ b/release/src/router/busybox/coreutils/tty.c
@@ -0,0 +1,58 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tty implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/tty.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+extern int tty_main(int argc, char **argv)
+{
+ const char *s;
+ int silent; /* Note: No longer relevant in SUSv3. */
+ int retval;
+
+ bb_default_error_retval = 2; /* SUSv3 requires > 1 for error. */
+
+ silent = bb_getopt_ulflags(argc, argv, "s");
+
+ /* gnu tty outputs a warning that it is ignoring all args. */
+ bb_warn_ignoring_args(argc - optind);
+
+ retval = 0;
+
+ if ((s = ttyname(0)) == NULL) {
+ /* According to SUSv3, ttyname can on fail with EBADF or ENOTTY.
+ * We know the file descriptor is good, so failure means not a tty. */
+ s = "not a tty";
+ retval = 1;
+ }
+
+ if (!silent) {
+ puts(s);
+ }
+
+ bb_fflush_stdout_and_exit(retval);
+}
diff --git a/release/src/router/busybox/coreutils/uname.c b/release/src/router/busybox/coreutils/uname.c
new file mode 100644
index 00000000..a3e52e39
--- /dev/null
+++ b/release/src/router/busybox/coreutils/uname.c
@@ -0,0 +1,118 @@
+/* vi: set sw=4 ts=4: */
+/* uname -- print system information
+ Copyright (C) 1989-1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/uname.html */
+
+/* Option Example
+
+ -s, --sysname SunOS
+ -n, --nodename rocky8
+ -r, --release 4.0
+ -v, --version
+ -m, --machine sun
+ -a, --all SunOS rocky8 4.0 sun
+
+ The default behavior is equivalent to `-s'.
+
+ David MacKenzie <djm@gnu.ai.mit.edu> */
+
+/* Busyboxed by Erik Andersen */
+
+/* Further size reductions by Glenn McGrath and Manuel Novoa III. */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Now does proper error checking on i/o. Plus some further space savings.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include "busybox.h"
+
+typedef struct {
+ struct utsname name;
+ char processor[8]; /* for "unknown" */
+} uname_info_t;
+
+static const char options[] = "snrvmpa";
+static const unsigned short int utsname_offset[] = {
+ offsetof(uname_info_t,name.sysname),
+ offsetof(uname_info_t,name.nodename),
+ offsetof(uname_info_t,name.release),
+ offsetof(uname_info_t,name.version),
+ offsetof(uname_info_t,name.machine),
+ offsetof(uname_info_t,processor)
+};
+
+int uname_main(int argc, char **argv)
+{
+ uname_info_t uname_info;
+#if defined(__sparc__) && defined(__linux__)
+ char *fake_sparc = getenv("FAKE_SPARC");
+#endif
+ const unsigned short int *delta;
+ char toprint;
+
+ toprint = bb_getopt_ulflags(argc, argv, options);
+
+ if (argc != optind) {
+ bb_show_usage();
+ }
+
+ if (toprint & (1 << 6)) {
+ toprint = 0x3f;
+ }
+
+ if (toprint == 0) {
+ toprint = 1; /* sysname */
+ }
+
+ if (uname(&uname_info.name) == -1) {
+ bb_error_msg_and_die("cannot get system name");
+ }
+
+#if defined(__sparc__) && defined(__linux__)
+ if ((fake_sparc != NULL)
+ && ((fake_sparc[0] == 'y')
+ || (fake_sparc[0] == 'Y'))) {
+ strcpy(uname_info.name.machine, "sparc");
+ }
+#endif
+
+ strcpy(uname_info.processor, "unknown");
+
+ delta=utsname_offset;
+ do {
+ if (toprint & 1) {
+ bb_printf(((char *)(&uname_info)) + *delta);
+ if (toprint > 1) {
+ putchar(' ');
+ }
+ }
+ ++delta;
+ } while (toprint >>= 1);
+ putchar('\n');
+
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}
diff --git a/release/src/router/busybox/coreutils/uniq.c b/release/src/router/busybox/coreutils/uniq.c
new file mode 100644
index 00000000..90686c9a
--- /dev/null
+++ b/release/src/router/busybox/coreutils/uniq.c
@@ -0,0 +1,112 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * uniq implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+static const char uniq_opts[] = "f:s:cdu\0\7\3\5\1\2\4";
+
+int uniq_main(int argc, char **argv)
+{
+ FILE *in, *out;
+ /* Note: Ignore the warning about dups and e0 possibly being uninitialized.
+ * They will be initialized on the fist pass of the loop (since s0 is NULL). */
+ unsigned long dups, skip_fields, skip_chars, i;
+ const char *s0, *e0, *s1, *e1, *input_filename;
+ int opt;
+ int uniq_flags = 6; /* -u */
+
+ skip_fields = skip_chars = 0;
+
+ while ((opt = getopt(argc, argv, uniq_opts)) > 0) {
+ if (opt == 'f') {
+ skip_fields = bb_xgetularg10(optarg);
+ } else if (opt == 's') {
+ skip_chars = bb_xgetularg10(optarg);
+ } else if ((s0 = strchr(uniq_opts, opt)) != NULL) {
+ uniq_flags &= s0[4];
+ uniq_flags |= s0[7];
+ } else {
+ bb_show_usage();
+ }
+ }
+
+ input_filename = *(argv += optind);
+
+ in = xgetoptfile_sort_uniq(argv, "r");
+ if (*argv) {
+ ++argv;
+ }
+ out = xgetoptfile_sort_uniq(argv, "w");
+ if (*argv && argv[1]) {
+ bb_show_usage();
+ }
+
+ s0 = NULL;
+
+ /* gnu uniq ignores newlines */
+ while ((s1 = bb_get_chomped_line_from_file(in)) != NULL) {
+ e1 = s1;
+ for (i=skip_fields ; i ; i--) {
+ e1 = bb_skip_whitespace(e1);
+ while (*e1 && !isspace(*e1)) {
+ ++e1;
+ }
+ }
+ for (i = skip_chars ; *e1 && i ; i--) {
+ ++e1;
+ }
+ if (s0) {
+ if (strcmp(e0, e1) == 0) {
+ ++dups; /* Note: Testing for overflow seems excessive. */
+ continue;
+ }
+ DO_LAST:
+ if ((dups && (uniq_flags & 2)) || (!dups && (uniq_flags & 4))) {
+ bb_fprintf(out, "\0%7d\t" + (uniq_flags & 1), dups + 1);
+ bb_fprintf(out, "%s\n", s0);
+ }
+ free((void *)s0);
+ }
+
+ s0 = s1;
+ e0 = e1;
+ dups = 0;
+ }
+
+ if (s0) {
+ e1 = NULL;
+ goto DO_LAST;
+ }
+
+ bb_xferror(in, input_filename);
+
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}
diff --git a/release/src/router/busybox/coreutils/usleep.c b/release/src/router/busybox/coreutils/usleep.c
new file mode 100644
index 00000000..f570f273
--- /dev/null
+++ b/release/src/router/busybox/coreutils/usleep.c
@@ -0,0 +1,41 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * usleep implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Apparently a busybox extension. */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include "busybox.h"
+
+extern int usleep_main(int argc, char **argv)
+{
+ if (argc != 2) {
+ bb_show_usage();
+ }
+
+ if (usleep(bb_xgetularg10_bnd(argv[1], 0, UINT_MAX))) {
+ bb_perror_nomsg_and_die();
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/coreutils/uudecode.c b/release/src/router/busybox/coreutils/uudecode.c
new file mode 100644
index 00000000..4f9270c1
--- /dev/null
+++ b/release/src/router/busybox/coreutils/uudecode.c
@@ -0,0 +1,353 @@
+/* uudecode.c -- uudecode utility.
+ * Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ *
+ * This product is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This product is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this product; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Reworked to GNU style by Ian Lance Taylor, ian@airs.com, August 93.
+ *
+ * Original copyright notice is retained at the end of this file.
+ */
+
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdlib.h>
+#include "busybox.h"
+#include "pwd_.h"
+#include "grp_.h"
+
+/*struct passwd *getpwnam();*/
+
+/* Single character decode. */
+#define DEC(Char) (((Char) - ' ') & 077)
+
+static int read_stduu (const char *inname)
+{
+ char buf[2 * BUFSIZ];
+
+ while (1) {
+ int n;
+ char *p;
+
+ if (fgets (buf, sizeof(buf), stdin) == NULL) {
+ bb_error_msg("%s: Short file", inname);
+ return FALSE;
+ }
+ p = buf;
+
+ /* N is used to avoid writing out all the characters at the end of
+ the file. */
+ n = DEC (*p);
+ if (n <= 0)
+ break;
+ for (++p; n > 0; p += 4, n -= 3) {
+ char ch;
+
+ if (n >= 3) {
+ ch = DEC (p[0]) << 2 | DEC (p[1]) >> 4;
+ putchar (ch);
+ ch = DEC (p[1]) << 4 | DEC (p[2]) >> 2;
+ putchar (ch);
+ ch = DEC (p[2]) << 6 | DEC (p[3]);
+ putchar (ch);
+ } else {
+ if (n >= 1) {
+ ch = DEC (p[0]) << 2 | DEC (p[1]) >> 4;
+ putchar (ch);
+ }
+ if (n >= 2) {
+ ch = DEC (p[1]) << 4 | DEC (p[2]) >> 2;
+ putchar (ch);
+ }
+ }
+ }
+ }
+
+ if (fgets (buf, sizeof(buf), stdin) == NULL
+ || strcmp (buf, "end\n")) {
+ bb_error_msg("%s: No `end' line", inname);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int read_base64 (const char *inname)
+{
+ static const char b64_tab[256] = {
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*000-007*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*010-017*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*020-027*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*030-037*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*040-047*/
+ '\177', '\177', '\177', '\76', '\177', '\177', '\177', '\77', /*050-057*/
+ '\64', '\65', '\66', '\67', '\70', '\71', '\72', '\73', /*060-067*/
+ '\74', '\75', '\177', '\177', '\177', '\100', '\177', '\177', /*070-077*/
+ '\177', '\0', '\1', '\2', '\3', '\4', '\5', '\6', /*100-107*/
+ '\7', '\10', '\11', '\12', '\13', '\14', '\15', '\16', /*110-117*/
+ '\17', '\20', '\21', '\22', '\23', '\24', '\25', '\26', /*120-127*/
+ '\27', '\30', '\31', '\177', '\177', '\177', '\177', '\177', /*130-137*/
+ '\177', '\32', '\33', '\34', '\35', '\36', '\37', '\40', /*140-147*/
+ '\41', '\42', '\43', '\44', '\45', '\46', '\47', '\50', /*150-157*/
+ '\51', '\52', '\53', '\54', '\55', '\56', '\57', '\60', /*160-167*/
+ '\61', '\62', '\63', '\177', '\177', '\177', '\177', '\177', /*170-177*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*200-207*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*210-217*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*220-227*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*230-237*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*240-247*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*250-257*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*260-267*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*270-277*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*300-307*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*310-317*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*320-327*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*330-337*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*340-347*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*350-357*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*360-367*/
+ '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*370-377*/
+ };
+ unsigned char buf[2 * BUFSIZ];
+
+ while (1) {
+ int last_data = 0;
+ unsigned char *p;
+
+ if (fgets (buf, sizeof(buf), stdin) == NULL) {
+ bb_error_msg("%s: Short file", inname);
+ return FALSE;
+ }
+ p = buf;
+
+ if (memcmp (buf, "====", 4) == 0)
+ break;
+ if (last_data != 0) {
+ bb_error_msg("%s: data following `=' padding character", inname);
+ return FALSE;
+ }
+
+ /* The following implementation of the base64 decoding might look
+ a bit clumsy but I only try to follow the POSIX standard:
+ ``All line breaks or other characters not found in the table
+ [with base64 characters] shall be ignored by decoding
+ software.'' */
+ while (*p != '\n') {
+ char c1, c2, c3;
+
+ while ((b64_tab[*p] & '\100') != 0)
+ if (*p == '\n' || *p++ == '=')
+ break;
+ if (*p == '\n')
+ /* This leaves the loop. */
+ continue;
+ c1 = b64_tab[*p++];
+
+ while ((b64_tab[*p] & '\100') != 0)
+ if (*p == '\n' || *p++ == '=') {
+ bb_error_msg("%s: illegal line", inname);
+ return FALSE;
+ }
+ c2 = b64_tab[*p++];
+
+ while (b64_tab[*p] == '\177')
+ if (*p++ == '\n') {
+ bb_error_msg("%s: illegal line", inname);
+ return FALSE;
+ }
+ if (*p == '=') {
+ putchar (c1 << 2 | c2 >> 4);
+ last_data = 1;
+ break;
+ }
+ c3 = b64_tab[*p++];
+
+ while (b64_tab[*p] == '\177')
+ if (*p++ == '\n') {
+ bb_error_msg("%s: illegal line", inname);
+ return FALSE;
+ }
+ putchar (c1 << 2 | c2 >> 4);
+ putchar (c2 << 4 | c3 >> 2);
+ if (*p == '=') {
+ last_data = 1;
+ break;
+ }
+ else
+ putchar (c3 << 6 | b64_tab[*p++]);
+ }
+ }
+
+ return TRUE;
+}
+
+static int decode (const char *inname,
+ const char *forced_outname)
+{
+ struct passwd *pw;
+ register char *p;
+ int mode;
+ char buf[2 * BUFSIZ];
+ char *outname;
+ int do_base64 = 0;
+ int res;
+ int dofre;
+
+ /* Search for header line. */
+
+ while (1) {
+ if (fgets (buf, sizeof (buf), stdin) == NULL) {
+ bb_error_msg("%s: No `begin' line", inname);
+ return FALSE;
+ }
+
+ if (strncmp (buf, "begin", 5) == 0) {
+ if (sscanf (buf, "begin-base64 %o %s", &mode, buf) == 2) {
+ do_base64 = 1;
+ break;
+ } else if (sscanf (buf, "begin %o %s", &mode, buf) == 2)
+ break;
+ }
+ }
+
+ /* If the output file name is given on the command line this rules. */
+ dofre = FALSE;
+ if (forced_outname != NULL)
+ outname = (char *) forced_outname;
+ else {
+ /* Handle ~user/file format. */
+ if (buf[0] != '~')
+ outname = buf;
+ else {
+ p = buf + 1;
+ while (*p != '/')
+ ++p;
+ if (*p == '\0') {
+ bb_error_msg("%s: Illegal ~user", inname);
+ return FALSE;
+ }
+ *p++ = '\0';
+ pw = getpwnam (buf + 1);
+ if (pw == NULL) {
+ bb_error_msg("%s: No user `%s'", inname, buf + 1);
+ return FALSE;
+ }
+ outname = concat_path_file(pw->pw_dir, p);
+ dofre = TRUE;
+ }
+ }
+
+ /* Create output file and set mode. */
+ if (strcmp (outname, "/dev/stdout") != 0 && strcmp (outname, "-") != 0
+ && (freopen (outname, "w", stdout) == NULL
+ || chmod (outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO))
+ )) {
+ bb_perror_msg("%s", outname); /* */
+ if (dofre)
+ free(outname);
+ return FALSE;
+ }
+
+ /* We differenciate decoding standard UU encoding and base64. A
+ common function would only slow down the program. */
+
+ /* For each input line: */
+ if (do_base64)
+ res = read_base64 (inname);
+ else
+ res = read_stduu (inname);
+ if (dofre)
+ free(outname);
+ return res;
+}
+
+int uudecode_main (int argc,
+ char **argv)
+{
+ int opt;
+ int exit_status;
+ const char *outname;
+ outname = NULL;
+
+ while ((opt = getopt(argc, argv, "o:")) != EOF) {
+ switch (opt) {
+ case 0:
+ break;
+
+ case 'o':
+ outname = optarg;
+ break;
+
+ default:
+ bb_show_usage();
+ }
+ }
+
+ if (optind == argc)
+ exit_status = decode ("stdin", outname) == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ else {
+ exit_status = EXIT_SUCCESS;
+ do {
+ if (freopen (argv[optind], "r", stdin) != NULL) {
+ if (decode (argv[optind], outname) != 0)
+ exit_status = FALSE;
+ } else {
+ bb_perror_msg("%s", argv[optind]);
+ exit_status = EXIT_FAILURE;
+ }
+ optind++;
+ }
+ while (optind < argc);
+ }
+ return(exit_status);
+}
+
+/* Copyright (c) 1983 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. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
+ *
+ * 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.
+ */
+
+
diff --git a/release/src/router/busybox/coreutils/uuencode.c b/release/src/router/busybox/coreutils/uuencode.c
new file mode 100644
index 00000000..fd3326d8
--- /dev/null
+++ b/release/src/router/busybox/coreutils/uuencode.c
@@ -0,0 +1,149 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2000 by Glenn McGrath
+ *
+ * based on the function base64_encode from http.c in wget v1.6
+ * Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <getopt.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "busybox.h"
+
+/* Conversion table. for base 64 */
+static const char tbl_base64[65] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/',
+ '=' /* termination character */
+};
+
+static const char tbl_std[65] = {
+ '`', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`' /* termination character */
+};
+
+/*
+ * Encode the string S of length LENGTH to base64 format and place it
+ * to STORE. STORE will be 0-terminated, and must point to a writable
+ * buffer of at least 1+BASE64_LENGTH(length) bytes.
+ * where BASE64_LENGTH(len) = (4 * ((LENGTH + 2) / 3))
+ */
+static void uuencode (const char *s, const char *store, const int length, const char *tbl)
+{
+ int i;
+ unsigned char *p = (unsigned char *)store;
+
+ /* Transform the 3x8 bits to 4x6 bits, as required by base64. */
+ for (i = 0; i < length; i += 3) {
+ *p++ = tbl[s[0] >> 2];
+ *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
+ *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
+ *p++ = tbl[s[2] & 0x3f];
+ s += 3;
+ }
+ /* Pad the result if necessary... */
+ if (i == length + 1) {
+ *(p - 1) = tbl[64];
+ }
+ else if (i == length + 2) {
+ *(p - 1) = *(p - 2) = tbl[64];
+ }
+ /* ...and zero-terminate it. */
+ *p = '\0';
+}
+
+#define SRC_BUF_SIZE 45 // This *MUST* be a multiple of 3
+#define DST_BUF_SIZE 4 * ((SRC_BUF_SIZE + 2) / 3)
+int uuencode_main(int argc, char **argv)
+{
+ const int src_buf_size = SRC_BUF_SIZE;
+ const int dst_buf_size = DST_BUF_SIZE;
+ int write_size = dst_buf_size;
+ struct stat stat_buf;
+ FILE *src_stream = stdin;
+ const char *tbl;
+ size_t size;
+ mode_t mode;
+ RESERVE_CONFIG_BUFFER(src_buf, SRC_BUF_SIZE + 1);
+ RESERVE_CONFIG_BUFFER(dst_buf, DST_BUF_SIZE + 1);
+
+ tbl = tbl_std;
+ if (bb_getopt_ulflags(argc, argv, "m") & 1) {
+ tbl = tbl_base64;
+ }
+
+ switch (argc - optind) {
+ case 2:
+ src_stream = bb_xfopen(argv[optind], "r");
+ if (stat(argv[optind], &stat_buf) < 0) {
+ bb_perror_msg_and_die("stat");
+ }
+ mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ if (src_stream == stdout) {
+ puts("NULL");
+ }
+ break;
+ case 1:
+ mode = 0666 & ~umask(0666);
+ break;
+ default:
+ bb_show_usage();
+ }
+
+ bb_printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
+
+ while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) {
+ if (size != src_buf_size) {
+ /* write_size is always 60 until the last line */
+ write_size=(4 * ((size + 2) / 3));
+ /* pad with 0s so we can just encode extra bits */
+ memset(&src_buf[size], 0, src_buf_size - size);
+ }
+ /* Encode the buffer we just read in */
+ uuencode(src_buf, dst_buf, size, tbl);
+
+ putchar('\n');
+ if (tbl == tbl_std) {
+ putchar(tbl[size]);
+ }
+ if (fwrite(dst_buf, 1, write_size, stdout) != write_size) {
+ bb_perror_msg_and_die(bb_msg_write_error);
+ }
+ }
+ bb_printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
+
+ bb_xferror(src_stream, "source"); /* TODO - Fix this! */
+
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}
diff --git a/release/src/router/busybox/coreutils/watch.c b/release/src/router/busybox/coreutils/watch.c
new file mode 100644
index 00000000..f9f40189
--- /dev/null
+++ b/release/src/router/busybox/coreutils/watch.c
@@ -0,0 +1,110 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini watch implementation for busybox
+ *
+ * Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A */
+/* BB_AUDIT GNU defects -- only option -n is supported. */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Removed dependency on date_main(), added proper error checking, and
+ * reduced size.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include "busybox.h"
+
+extern int watch_main(int argc, char **argv)
+{
+ const int header_len = 40;
+ time_t t;
+ pid_t pid;
+ unsigned period = 2;
+ int old_stdout;
+ int len, len2;
+ char **watched_argv;
+ char header[header_len + 1];
+
+ if (argc < 2) {
+ bb_show_usage();
+ }
+
+ /* don't use getopt, because it permutes the arguments */
+ ++argv;
+ if ((argc > 3) && !strcmp(*argv, "-n")
+ ) {
+ period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX);
+ argv += 2;
+ }
+ watched_argv = argv;
+
+ /* create header */
+
+ len = snprintf(header, header_len, "Every %ds:", period);
+ /* Don't bother checking for len < 0, as it should never happen.
+ * But, just to be prepared... */
+ assert(len >= 0);
+ do {
+ len2 = strlen(*argv);
+ if (len + len2 >= header_len-1) {
+ break;
+ }
+ header[len] = ' ';
+ memcpy(header+len+1, *argv, len2);
+ len += len2+1;
+ } while (*++argv);
+
+ header[len] = 0;
+
+ /* thanks to lye, who showed me how to redirect stdin/stdout */
+ old_stdout = dup(1);
+
+ while (1) {
+ time(&t);
+ /* Use dprintf to avoid fflush()ing stdout. */
+ if (dprintf(1, "\033[H\033[J%-*s%s\n", header_len, header, ctime(&t)) < 0) {
+ bb_perror_msg_and_die("printf");
+ }
+
+ pid = vfork(); /* vfork, because of ucLinux */
+ if (pid > 0) {
+ //parent
+ wait(0);
+ sleep(period);
+ } else if (0 == pid) {
+ //child
+ close(1);
+ dup(old_stdout);
+ if (execvp(*watched_argv, watched_argv)) {
+ bb_error_msg_and_die("Couldn't run command\n");
+ }
+ } else {
+ bb_error_msg_and_die("Couldn't vfork\n");
+ }
+ }
+}
diff --git a/release/src/router/busybox/coreutils/wc.c b/release/src/router/busybox/coreutils/wc.c
new file mode 100644
index 00000000..77990152
--- /dev/null
+++ b/release/src/router/busybox/coreutils/wc.c
@@ -0,0 +1,227 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * wc implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 _NOT_ compliant -- option -m is not currently supported. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/wc.html */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Rewritten to fix a number of problems and do some size optimizations.
+ * Problems in the previous busybox implementation (besides bloat) included:
+ * 1) broken 'wc -c' optimization (read note below)
+ * 2) broken handling of '-' args
+ * 3) no checking of ferror on EOF returns
+ * 4) isprint() wasn't considered when word counting.
+ *
+ * TODO:
+ *
+ * When locale support is enabled, count multibyte chars in the '-m' case.
+ *
+ * NOTES:
+ *
+ * The previous busybox wc attempted an optimization using stat for the
+ * case of counting chars only. I omitted that because it was broken.
+ * It didn't take into account the possibility of input coming from a
+ * pipe, or input from a file with file pointer not at the beginning.
+ *
+ * To implement such a speed optimization correctly, not only do you
+ * need the size, but also the file position. Note also that the
+ * file position may be past the end of file. Consider the example
+ * (adapted from example in gnu wc.c)
+ *
+ * echo hello > /tmp/testfile &&
+ * (dd ibs=1k skip=1 count=0 &> /dev/null ; wc -c) < /tmp/testfile
+ *
+ * for which 'wc -c' should output '0'.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "busybox.h"
+
+#ifdef CONFIG_LOCALE_SUPPORT
+#include <locale.h>
+#include <ctype.h>
+#define isspace_given_isprint(c) isspace(c)
+#else
+#undef isspace
+#undef isprint
+#define isspace(c) ((((c) == ' ') || (((unsigned int)((c) - 9)) <= (13 - 9))))
+#define isprint(c) (((unsigned int)((c) - 0x20)) <= (0x7e - 0x20))
+#define isspace_given_isprint(c) ((c) == ' ')
+#endif
+
+enum {
+ WC_LINES = 0,
+ WC_WORDS = 1,
+ WC_CHARS = 2,
+ WC_LENGTH = 3
+};
+
+/* Note: If this changes, remember to change the initialization of
+ * 'name' in wc_main. It needs to point to the terminating nul. */
+static const char wc_opts[] = "lwcL"; /* READ THE WARNING ABOVE! */
+
+enum {
+ OP_INC_LINE = 1, /* OP_INC_LINE must be 1. */
+ OP_SPACE = 2,
+ OP_NEWLINE = 4,
+ OP_TAB = 8,
+ OP_NUL = 16,
+};
+
+/* Note: If fmt_str changes, the offsets to 's' in the OUTPUT section
+ * will need to be updated. */
+static const char fmt_str[] = " %7u\0 %s\n";
+static const char total_str[] = "total";
+
+int wc_main(int argc, char **argv)
+{
+ FILE *fp;
+ const char *s;
+ unsigned int *pcounts;
+ unsigned int counts[4];
+ unsigned int totals[4];
+ unsigned int linepos;
+ unsigned int u;
+ int num_files = 0;
+ int c;
+ char status = EXIT_SUCCESS;
+ char in_word;
+ char print_type;
+
+ print_type = bb_getopt_ulflags(argc, argv, wc_opts);
+
+ if (print_type == 0) {
+ print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS);
+ }
+
+ argv += optind;
+ if (!*argv) {
+ *--argv = (char *) bb_msg_standard_input;
+ }
+
+ memset(totals, 0, sizeof(totals));
+
+ pcounts = counts;
+
+ do {
+ ++num_files;
+ if (!(fp = bb_wfopen_input(*argv))) {
+ status = EXIT_FAILURE;
+ continue;
+ }
+
+ memset(counts, 0, sizeof(counts));
+ linepos = 0;
+ in_word = 0;
+
+ do {
+ ++counts[WC_CHARS];
+ c = getc(fp);
+ if (isprint(c)) {
+ ++linepos;
+ if (!isspace_given_isprint(c)) {
+ in_word = 1;
+ continue;
+ }
+ } else if (((unsigned int)(c - 9)) <= 4) {
+ /* \t 9
+ * \n 10
+ * \v 11
+ * \f 12
+ * \r 13
+ */
+ if (c == '\t') {
+ linepos = (linepos | 7) + 1;
+ } else { /* '\n', '\r', '\f', or '\v' */
+ DO_EOF:
+ if (linepos > counts[WC_LENGTH]) {
+ counts[WC_LENGTH] = linepos;
+ }
+ if (c == '\n') {
+ ++counts[WC_LINES];
+ }
+ if (c != '\v') {
+ linepos = 0;
+ }
+ }
+ } else if (c == EOF) {
+ if (ferror(fp)) {
+ bb_perror_msg("%s", *argv);
+ status = EXIT_FAILURE;
+ }
+ --counts[WC_CHARS];
+ goto DO_EOF; /* Treat an EOF as '\r'. */
+ } else {
+ continue;
+ }
+
+ counts[WC_WORDS] += in_word;
+ in_word = 0;
+ if (c == EOF) {
+ break;
+ }
+ } while (1);
+
+ if (totals[WC_LENGTH] < counts[WC_LENGTH]) {
+ totals[WC_LENGTH] = counts[WC_LENGTH];
+ }
+ totals[WC_LENGTH] -= counts[WC_LENGTH];
+
+ bb_fclose_nonstdin(fp);
+
+ OUTPUT:
+ s = fmt_str + 1; /* Skip the leading space on 1st pass. */
+ u = 0;
+ do {
+ if (print_type & (1 << u)) {
+ bb_printf(s, pcounts[u]);
+ s = fmt_str; /* Ok... restore the leading space. */
+ }
+ totals[u] += pcounts[u];
+ } while (++u < 4);
+
+ s += 8; /* Set the format to the empty string. */
+
+ if (*argv != bb_msg_standard_input) {
+ s -= 3; /* We have a name, so do %s conversion. */
+ }
+ bb_printf(s, *argv);
+
+ } while (*++argv);
+
+ /* If more than one file was processed, we want the totals. To save some
+ * space, we set the pcounts ptr to the totals array. This has the side
+ * effect of trashing the totals array after outputting it, but that's
+ * irrelavent since we no longer need it. */
+ if (num_files > 1) {
+ num_files = 0; /* Make sure we don't get here again. */
+ *--argv = (char *) total_str;
+ pcounts = totals;
+ goto OUTPUT;
+ }
+
+ bb_fflush_stdout_and_exit(status);
+}
diff --git a/release/src/router/busybox/coreutils/who.c b/release/src/router/busybox/coreutils/who.c
new file mode 100644
index 00000000..1bf55205
--- /dev/null
+++ b/release/src/router/busybox/coreutils/who.c
@@ -0,0 +1,83 @@
+/* vi: set sw=4 ts=4: */
+/*----------------------------------------------------------------------
+ * Mini who is used to display user name, login time,
+ * idle time and host name.
+ *
+ * Author: Da Chen <dchen@ayrnetworks.com>
+ *
+ * This is a free document; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation:
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Copyright (c) 2002 AYR Networks, Inc.
+ *----------------------------------------------------------------------
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <utmp.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include "busybox.h"
+
+extern int who_main(int argc, char **argv)
+{
+ struct utmp *ut;
+ struct stat st;
+ int devlen, len;
+ time_t now, idle;
+
+ if (argc > 1)
+ bb_show_usage();
+
+ setutent();
+ devlen = sizeof("/dev/") - 1;
+ printf("USER TTY IDLE FROM HOST\n");
+
+ while ((ut = getutent()) != NULL) {
+ char name[40];
+
+ if (ut->ut_user[0] && ut->ut_type == USER_PROCESS) {
+ len = strlen(ut->ut_line);
+ if (ut->ut_line[0] == '/') {
+ strncpy(name, ut->ut_line, len);
+ name[len] = '\0';
+ strcpy(ut->ut_line, ut->ut_line + devlen);
+ } else {
+ strcpy(name, "/dev/");
+ strncpy(name+devlen, ut->ut_line, len);
+ name[devlen+len] = '\0';
+ }
+
+ printf("%-10s %-8s ", ut->ut_user, ut->ut_line);
+
+ if (stat(name, &st) == 0) {
+ now = time(NULL);
+ idle = now - st.st_atime;
+
+ if (idle < 60)
+ printf("00:00m ");
+ else if (idle < (60 * 60))
+ printf("00:%02dm ", (int)(idle / 60));
+ else if (idle < (24 * 60 * 60))
+ printf("%02d:%02dm ", (int)(idle / (60 * 60)),
+ (int)(idle % (60 * 60)) / 60);
+ else if (idle < (24 * 60 * 60 * 365))
+ printf("%03ddays ", (int)(idle / (24 * 60 * 60)));
+ else
+ printf("%02dyears ", (int) (idle / (24 * 60 * 60 * 365)));
+ } else
+ printf("%-8s ", "?");
+
+ printf("%-12.12s %s\n", ctime(&(ut->ut_tv.tv_sec)) + 4, ut->ut_host);
+ }
+ }
+ endutent();
+
+ return 0;
+}
diff --git a/release/src/router/busybox/coreutils/whoami.c b/release/src/router/busybox/coreutils/whoami.c
new file mode 100644
index 00000000..f93034d3
--- /dev/null
+++ b/release/src/router/busybox/coreutils/whoami.c
@@ -0,0 +1,44 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini whoami implementation for busybox
+ *
+ * Copyright (C) 2000 Edward Betts <edward@debian.org>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+extern int whoami_main(int argc, char **argv)
+{
+ char user[9];
+ uid_t uid;
+
+ if (argc > 1)
+ bb_show_usage();
+
+ uid = geteuid();
+ if (my_getpwuid(user, uid)) {
+ puts(user);
+ bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+ }
+ bb_error_msg_and_die("cannot find username for UID %u", (unsigned) uid);
+}
diff --git a/release/src/router/busybox/coreutils/yes.c b/release/src/router/busybox/coreutils/yes.c
new file mode 100644
index 00000000..74f7571c
--- /dev/null
+++ b/release/src/router/busybox/coreutils/yes.c
@@ -0,0 +1,56 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * yes implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+ *
+ * Size reductions and removed redundant applet name prefix from error messages.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+extern int yes_main(int argc, char **argv)
+{
+ static const char fmt_str[] = " %s";
+ const char *fmt;
+ char **first_arg;
+
+ *argv = "y";
+ if (argc != 1) {
+ ++argv;
+ }
+
+ first_arg = argv;
+ do {
+ fmt = fmt_str + 1;
+ do {
+ bb_printf(fmt, *argv);
+ fmt = fmt_str;
+ } while (*++argv);
+ argv = first_arg;
+ } while (putchar('\n') != EOF);
+
+ bb_perror_nomsg_and_die();
+}