changeset 653:2986aa63a021

Move commands into "posix", "lsb", and "other" menus/directories.
author Rob Landley <rob@landley.net>
date Sat, 25 Aug 2012 14:25:22 -0500
parents 2d7c56913fda
children 04feab07416c
files Config.in Makefile scripts/genconfig.sh scripts/make.sh toys/basename.c toys/bzcat.c toys/cal.c toys/cat.c toys/catv.c toys/chgrp.c toys/chmod.c toys/chroot.c toys/chvt.c toys/cksum.c toys/clear.c toys/cmp.c toys/comm.c toys/count.c toys/cp.c toys/date.c toys/df.c toys/dirname.c toys/dmesg.c toys/dos2unix.c toys/echo.c toys/env.c toys/false.c toys/free.c toys/head.c toys/hello.c toys/help.c toys/hostname.c toys/id.c toys/insmod.c toys/kill.c toys/killall.c toys/link.c toys/ln.c toys/login.c toys/logname.c toys/ls.c toys/lsb/dmesg.c toys/lsb/hostname.c toys/lsb/killall.c toys/lsb/mknod.c toys/lsb/mktemp.c toys/lsb/passwd.c toys/lsb/pidof.c toys/lsb/seq.c toys/lsb/sync.c toys/lsmod.c toys/mdev.c toys/mkdir.c toys/mke2fs.c toys/mkfifo.c toys/mknod.c toys/mkswap.c toys/mktemp.c toys/modinfo.c toys/mountpoint.c toys/netcat.c toys/nice.c toys/nohup.c toys/od.c toys/oneit.c toys/other/bzcat.c toys/other/catv.c toys/other/chroot.c toys/other/chvt.c toys/other/clear.c toys/other/count.c toys/other/dos2unix.c toys/other/free.c toys/other/hello.c toys/other/help.c toys/other/insmod.c toys/other/login.c toys/other/lsmod.c toys/other/mdev.c toys/other/mke2fs.c toys/other/mkswap.c toys/other/modinfo.c toys/other/mountpoint.c toys/other/netcat.c toys/other/oneit.c toys/other/printenv.c toys/other/readlink.c toys/other/realpath.c toys/other/rmmod.c toys/other/setsid.c toys/other/sha1sum.c toys/other/swapoff.c toys/other/swapon.c toys/other/tac.c toys/other/taskset.c toys/other/toysh.c toys/other/truncate.c toys/other/unshare.c toys/other/uptime.c toys/other/usleep.c toys/other/vmstat.c toys/other/w.c toys/other/which.c toys/other/whoami.c toys/other/yes.c toys/passwd.c toys/patch.c toys/pidof.c toys/posix/basename.c toys/posix/cal.c toys/posix/cat.c toys/posix/chgrp.c toys/posix/chmod.c toys/posix/cksum.c toys/posix/cmp.c toys/posix/comm.c toys/posix/cp.c toys/posix/date.c toys/posix/df.c toys/posix/dirname.c toys/posix/echo.c toys/posix/env.c toys/posix/false.c toys/posix/head.c toys/posix/id.c toys/posix/kill.c toys/posix/link.c toys/posix/ln.c toys/posix/logname.c toys/posix/ls.c toys/posix/mkdir.c toys/posix/mkfifo.c toys/posix/nice.c toys/posix/nohup.c toys/posix/od.c toys/posix/patch.c toys/posix/pwd.c toys/posix/rmdir.c toys/posix/sed.c toys/posix/sleep.c toys/posix/sort.c toys/posix/tail.c toys/posix/tee.c toys/posix/true.c toys/posix/tty.c toys/posix/uname.c toys/posix/uniq.c toys/posix/unlink.c toys/posix/wc.c toys/posix/who.c toys/posix/xargs.c toys/printenv.c toys/pwd.c toys/readlink.c toys/realpath.c toys/rmdir.c toys/rmmod.c toys/sed.c toys/seq.c toys/setsid.c toys/sha1sum.c toys/sleep.c toys/sort.c toys/swapoff.c toys/swapon.c toys/sync.c toys/tac.c toys/tail.c toys/taskset.c toys/tee.c toys/toysh.c toys/true.c toys/truncate.c toys/tty.c toys/uname.c toys/uniq.c toys/unlink.c toys/unshare.c toys/uptime.c toys/usleep.c toys/vmstat.c toys/w.c toys/wc.c toys/which.c toys/who.c toys/whoami.c toys/xargs.c toys/yes.c
diffstat 188 files changed, 9049 insertions(+), 9023 deletions(-) [+]
line wrap: on
line diff
--- a/Config.in	Sat Aug 25 14:24:24 2012 -0500
+++ b/Config.in	Sat Aug 25 14:25:22 2012 -0500
@@ -1,6 +1,6 @@
 mainmenu "ToyBox Configuration"
 
-menu "Global settings"
+menu "Toybox global settings"
 
 config TOYBOX
 	bool
@@ -46,6 +46,6 @@
 
 source generated/Config.probed
 
-menu "Toys"
+comment ""
+
 source generated/Config.in
-endmenu
--- a/Makefile	Sat Aug 25 14:24:24 2012 -0500
+++ b/Makefile	Sat Aug 25 14:25:22 2012 -0500
@@ -3,7 +3,7 @@
 
 all: toybox
 
-toybox toybox_unstripped: .config *.[ch] lib/*.[ch] toys/*.[ch] scripts/*.sh
+toybox toybox_unstripped: .config *.[ch] lib/*.[ch] toys/*.h toys/*/*.c scripts/*.sh
 	scripts/make.sh
 
 .PHONY: clean distclean baseline bloatcheck install install_flat \
@@ -12,7 +12,7 @@
 include kconfig/Makefile
 
 $(KCONFIG_TOP): generated/Config.in
-generated/Config.in: toys/*.c scripts/genconfig.sh
+generated/Config.in: toys/*/*.c scripts/genconfig.sh
 	scripts/genconfig.sh
 
 HOSTCC?=cc
--- a/scripts/genconfig.sh	Sat Aug 25 14:24:24 2012 -0500
+++ b/scripts/genconfig.sh	Sat Aug 25 14:25:22 2012 -0500
@@ -26,14 +26,25 @@
 
 genconfig()
 {
-  # extract config stanzas from each command source file, in alphabetical order
-
-  for i in $(ls -1 toys/*.c)
+  # I could query the directory here, but I want to control the order
+  # and capitalization in the menu
+  for j in Posix LSB Other
   do
-    # Grab the config block for Config.in
-    echo "# $i"
-    sed -n '/^\*\//q;/^config [A-Z]/,$p' $i || return 1
+    echo "menu \"$j commands\""
     echo
+
+    DIR=$(echo $j | tr A-Z a-z)
+
+    # extract config stanzas from each source file, in alphabetical order
+    for i in $(ls -1 toys/$DIR/*.c)
+    do
+      # Grab the config block for Config.in
+      echo "# $i"
+      sed -n '/^\*\//q;/^config [A-Z]/,$p' $i || return 1
+      echo
+    done
+
+    echo endmenu
   done
 }
 
--- a/scripts/make.sh	Sat Aug 25 14:24:24 2012 -0500
+++ b/scripts/make.sh	Sat Aug 25 14:25:22 2012 -0500
@@ -4,19 +4,27 @@
 
 source ./configure
 
+if [ -z ".config" ]
+then
+  echo "No .config (see "make help" for configuration options)."
+  exit 1
+fi
+
 echo "Extract configuration information from toys/*.c files..."
 scripts/genconfig.sh
 
-echo "Generate headers from toys/*.c..."
+echo "Generate headers from toys/*/*.c..."
 
 # Create a list of all the applets toybox can provide.  Note that the first
 # entry is out of order on purpose (the toybox multiplexer applet must be the
 # first element of the array).  The rest must be sorted in alphabetical order
 # for fast binary search.
 
+echo "generated/newtoys.h"
+
 function newtoys()
 {
-  for i in toys/*.c
+  for i in toys/*/*.c
   do
     sed -n -e '1,/^config [A-Z]/s/^USE_/&/p' $i || exit 1
   done
@@ -25,13 +33,13 @@
 newtoys | sed 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -k 1,1 \
 	| sed 's/[^ ]* //'  >> generated/newtoys.h
 
-# Extract global structure definitions and flag definitions from toys/*.c
+# Extract global structure definitions and flag definitions from toys/*/*.c
 
 function getglobals()
 {
-  for i in toys/*.c
+  for i in toys/*/*.c
   do
-    NAME="$(echo $i | sed 's@toys/\(.*\)\.c@\1@')"
+    NAME="$(echo $i | sed 's@.*/\(.*\)\.c@\1@')"
 
     echo -e "// $i\n"
     sed -n -e '/^DEFINE_GLOBALS(/,/^)/b got;b;:got' \
@@ -58,6 +66,8 @@
   done
 }
 
+echo "generated/globals.h"
+
 GLOBSTRUCT="$(getglobals)"
 (
   echo "$GLOBSTRUCT"
@@ -67,6 +77,7 @@
   echo "} this;"
 ) > generated/globals.h
 
+echo "generated/help.h"
 # Only recreate generated/help.h if python is installed
 if [ ! -z "$(which python)" ] && [ ! -z "$(grep 'CONFIG_HELP=y' .config)" ]
 then
@@ -100,20 +111,24 @@
   -e 's/.*/#define USE_&(...) __VA_ARGS__/p' \
   .config > generated/config.h || exit 1
 
-# Extract a list of toys/*.c files to compile from the data in ".config" with
-# sed, sort, and tr:
+# Extract a list of toys/*/*.c files to compile from the data in ".config":
 
 # 1) Grab the XXX part of all CONFIG_XXX entries, removing everything after the
 # second underline
 # 2) Sort the list, keeping only one of each entry.
 # 3) Convert to lower case.
 # 4) Remove toybox itself from the list (as that indicates global symbols).
-# 5) Add "toys/" prefix and ".c" suffix.
+# 5) Add "toys/*/" prefix and ".c" suffix.
 
-TOYFILES=$(cat .config | sed -nre 's/^CONFIG_(.*)=y/\1/;t skip;b;:skip;s/_.*//;p' | sort -u | tr A-Z a-z | grep -v '^toybox$' | sed 's@\(.*\)@toys/\1.c@' )
+TOYFILES=$(sed -nre 's/^CONFIG_(.*)=y/\1/;t skip;b;:skip;s/_.*//;p' < .config | sort -u | tr A-Z a-z | grep -v '^toybox$' | sed 's@\(.*\)@toys/\*/\1.c@')
 
 echo "Library probe..."
 
+# We trust --as-needed to remove each library if we don't use any symbols
+# out of it, this loop is because the compiler has no way to ignore a library
+# that doesn't exist, so we have to detect and skip nonexistent libraries
+# for it.
+
 OPTLIBS="$(for i in util crypt m; do echo "int main(int argc, char *argv[]) {return 0;}" | ${CROSS_COMPILE}${CC} -xc - -o /dev/null -Wl,--as-needed -l$i > /dev/null 2>/dev/null && echo -l$i; done)"
 
 echo "Compile toybox..."
--- a/toys/basename.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * basename.c - Return non-directory portion of a pathname
- *
- * Copyright 2012 Tryn Mirell <tryn@mirell.org>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/basename.html
-
-
-USE_BASENAME(NEWTOY(basename, "<1>2", TOYFLAG_USR|TOYFLAG_BIN))
-
-config BASENAME
-	bool "basename"
-	default y
-	help
-        usage: basename string [suffix]
-
-        Return non-directory portion of a pathname removing suffix
-*/
-
-#include "toys.h"
-
-void basename_main(void)
-{
-    char *arg = toys.optargs[0], *suffix = toys.optargs[1], *base;
-
-    while ((base = strrchr(arg, '/'))) {
-        if (base == arg) break;
-        if (!base[1]) *base = 0;
-        else {
-            base++;
-            break;
-        }
-    }
-
-    if (!base) base = arg;
-    
-    // chop off the suffix if provided
-    if (suffix) {
-        arg = base + strlen(base) - strlen(suffix);
-        if (arg > base && !strcmp(arg, suffix)) *arg = 0;
-    }
- 
-    puts(base);
-}
--- a/toys/bzcat.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * bzcat.c - decompress stdin to stdout using bunzip2.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3.
-
-USE_BZCAT(NEWTOY(bzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-
-config BZCAT
-	bool "bzcat"
-	default y
-	help
-	  usage: bzcat [filename...]
-
-	  Decompress listed files to stdout.  Use stdin if no files listed.
-*/
-
-#include "toys.h"
-
-static void do_bzcat(int fd, char *name)
-{
-    bunzipStream(fd, 1);
-}
-
-void bzcat_main(void)
-{
-    loopfiles(toys.optargs, do_bzcat);
-}
--- a/toys/cal.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * cal.c - show calendar.
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/cal.html
-
-USE_CAL(NEWTOY(cal, ">2", TOYFLAG_USR|TOYFLAG_BIN))
-
-config CAL
-	bool "cal"
-	default y
-	help
-	  usage: cal [[month] year]
-	  Print a calendar.
-
-	  With one argument, prints all months of the specified year.
-	  With two arguments, prints calendar for month and year.
-*/
-
-#include "toys.h"
-
-// Write calendar into buffer: each line is 20 chars wide, end indicated
-// by empty string.
-
-static char *calstrings(char *buf, struct tm *tm)
-{
-	char temp[21];
-	int wday, mday, start, len, line;
-
-	// header
-	len = strftime(temp, 21, "%B %Y", tm);
-	len += (20-len)/2;
-	buf += sprintf(buf, "%*s%*s ", len, temp, 20-len, "");
-	buf++;
-	buf += sprintf(buf, "Su Mo Tu We Th Fr Sa ");
-	buf++;
-
-	// What day of the week does this month start on?
-	if (tm->tm_mday>1)
-		start = (36+tm->tm_wday-tm->tm_mday)%7;
-	else start = tm->tm_wday;
-
-	// What day does this month end on?  Alas, libc doesn't tell us...
-	len = 31;
-	if (tm->tm_mon == 1) {
-		int year = tm->tm_year;
-		len = 28;
-		if (!(year & 3) && !((year&100) && !(year&400))) len++;
-	} else if ((tm->tm_mon+(tm->tm_mon>6 ? 1 : 0)) & 1) len = 30;
-
-	for (mday=line=0;line<6;line++) {
-		for (wday=0; wday<7; wday++) {
-			char *pat = "   ";
-			if (!mday ? wday==start : mday<len) {
-				pat = "%2d ";
-				mday++;
-			}
-			buf += sprintf(buf, pat, mday);
-		}
-		buf++;
-	}
-
-	return buf;
-}
-
-void xcheckrange(long val, long low, long high)
-{
-	char *err = "%ld %s than %ld";
-
-	if (val < low) error_exit(err, val, "less", low);
-	if (val > high) error_exit(err, val, "greater", high);
-}
-
-// Worst case scenario toybuf usage: sizeof(struct tm) plus 21 bytes/line
-// plus 8 lines/month plus 12 months, comes to a bit over 2k of our 4k buffer.
-
-void cal_main(void)
-{
-	struct tm *tm;
-	char *buf = toybuf;
-
-	if (toys.optc) {
-		// Conveniently starts zeroed
-		tm = (struct tm *)toybuf;
-		buf += sizeof(struct tm);
-
-		// Last argument is year, one before that (if any) is month.
-		xcheckrange(tm->tm_year = atol(toys.optargs[--toys.optc]),1,9999);
-		tm->tm_year -= 1900;
-		tm->tm_mday = 1;
-		tm->tm_hour = 12;  // noon to avoid timezone weirdness
-		if (toys.optc) {
-			xcheckrange(tm->tm_mon = atol(toys.optargs[--toys.optc]),1,12);
-			tm->tm_mon--;
-
-		// Print 12 months of the year
-
-		} else {
-			char *bufs[12];
-			int i, j, k;
-
-			for (i=0; i<12; i++) {
-				tm->tm_mon=i;
-				mktime(tm);
-				buf = calstrings(bufs[i]=buf, tm);
-			}
-
-			// 4 rows, 6 lines each, 3 columns
-			for (i=0; i<4; i++) {
-				for (j=0; j<8; j++) {
-					for(k=0; k<3; k++) {
-						char **b = bufs+(k+i*3);
-						*b += printf("%s ", *b);
-					}
-					puts("");
-				}
-			}
-			return;
-		}
-
-		// What day of the week does that start on?
-		mktime(tm);
-
-	} else {
-		time_t now;
-		time(&now);
-		tm = localtime(&now);
-	}
-
-	calstrings(buf, tm);
-	while (*buf) buf += printf("%s\n", buf);
-}
--- a/toys/cat.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * cat.c - copy inputs to stdout.
- *
- * Copyright 2006 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/cat.html
-
-USE_CAT(NEWTOY(cat, "u", TOYFLAG_BIN))
-
-config CAT
-	bool "cat"
-	default y
-	help
-	  usage: cat [-u] [file...]
-	  Copy (concatenate) files to stdout.  If no files listed, copy from stdin.
-	  Filename "-" is a synonym for stdin.
-
-	  -u	Copy one byte at a time (slow).
-*/
-
-#include "toys.h"
-
-static void do_cat(int fd, char *name)
-{
-	int len, size=toys.optflags ? 1 : sizeof(toybuf);
-
-	for (;;) {
-		len = read(fd, toybuf, size);
-		if (len<0) {
-			perror_msg("%s",name);
-			toys.exitval = EXIT_FAILURE;
-		}
-		if (len<1) break;
-		xwrite(1, toybuf, len);
-	}
-}
-
-void cat_main(void)
-{
-	loopfiles(toys.optargs, do_cat);
-}
--- a/toys/catv.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * cat -v implementation for toybox
- *
- * Copyright (C) 2006, 2007 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3, but see "Cat -v considered harmful" at
- *   http://cm.bell-labs.com/cm/cs/doc/84/kp.ps.gz
-
-USE_CATV(NEWTOY(catv, "vte", TOYFLAG_USR|TOYFLAG_BIN))
-
-config CATV
-	bool "catv"
-	default y
-	help
-	  usage: catv [-evt] [filename...]
-
-	  Display nonprinting characters as escape sequences.  Use M-x for
-	  high ascii characters (>127), and ^x for other nonprinting chars.
-
-	  -e	Mark each newline with $
-	  -t	Show tabs as ^I
-	  -v	Don't use ^x or M-x escapes.
-*/
-
-#include "toys.h"
-
-// Callback function for loopfiles()
-
-static void do_catv(int fd, char *name)
-{
-	for(;;) {
-		int i, len;
-
-		len = read(fd, toybuf, sizeof(toybuf));
-		if (len < 0) toys.exitval = EXIT_FAILURE;
-		if (len < 1) break;
-		for (i=0; i<len; i++) {
-			char c=toybuf[i];
-
-			if (c > 126 && (toys.optflags & 4)) {
-				if (c == 127) {
-					printf("^?");
-					continue;
-				} else {
-					printf("M-");
-					c -= 128;
-				}
-			}
-			if (c < 32) {
-				if (c == 10) {
-					if (toys.optflags & 1) xputc('$');
-				} else if (toys.optflags & (c==9 ? 2 : 4)) {
-					printf("^%c", c+'@');
-					continue;
-				}
-			}
-			xputc(c);
-		}
-	}
-}
-
-void catv_main(void)
-{
-	toys.optflags^=4;
-	loopfiles(toys.optargs, do_catv);
-}
--- a/toys/chgrp.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * chown.c - Change ownership
- *
- * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
- *
- * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/chown.html
- * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/chgrp.html
- *
- * TODO: group only one of [HLP]
-
-USE_CHGRP(NEWTOY(chgrp, "<2hPLHRfv", TOYFLAG_BIN))
-USE_CHGRP(OLDTOY(chown, chgrp, "<2hPLHRfv", TOYFLAG_BIN))
-
-config CHGRP
-	bool "chgrp/chown"
-	default y
-	help
-	  usage: chown [-RHLP] [-fvh] [owner][:group] file...
-	  usage: chgrp [-RHLP] [-fvh] group file...
-
-	  Change ownership of one or more files.
-
-	  -f	suppress most error messages.
-	  -h	change symlinks instead of what they point to
-	  -R	recurse into subdirectories (implies -h).
-  	  -H	with -R change target of symlink, follow command line symlinks
-	  -L	with -R change target of symlink, follow all symlinks
-	  -P	with -R change symlink, do not follow symlinks (default)
-	  -v	verbose output.
-*/
-
-#include "toys.h"
-
-#define FLAG_v 1
-#define FLAG_f 2
-#define FLAG_R 4
-#define FLAG_H 8
-#define FLAG_L 16
-#define FLAG_P 32
-#define FLAG_h 64
-
-DEFINE_GLOBALS(
-	uid_t owner;
-	gid_t group;
-	char *owner_name, *group_name;
-	int symfollow;
-)
-
-#define TT this.chgrp
-
-static int do_chgrp(struct dirtree *node)
-{
-	int fd, ret, flags = toys.optflags;
-
-	// Depth first search
-	if (!dirtree_notdotdot(node)) return 0;
-	if ((flags & FLAG_R) && node->data != -1 && S_ISDIR(node->st.st_mode))
-		return DIRTREE_COMEAGAIN|((flags&FLAG_L) ? DIRTREE_SYMFOLLOW : 0);
-
-	fd = dirtree_parentfd(node);
-	ret = fchownat(fd, node->name, TT.owner, TT.group,
-		(flags&(FLAG_L|FLAG_H)) || !(flags&(FLAG_h|FLAG_R))
-			? 0 : AT_SYMLINK_NOFOLLOW);
-
-	if (ret || (flags & FLAG_v)) {
-		char *path = dirtree_path(node, 0);
-		if (flags & FLAG_v)
-			xprintf("%s %s%s%s %s\n", toys.which->name,
-				TT.owner_name ? TT.owner_name : "",
-				toys.which->name[2]=='o' && TT.group_name ? ":" : "",
-				TT.group_name ? TT.group_name : "", path);
-		if (ret == -1 && !(toys.optflags & FLAG_f))
-			perror_msg("changing owner:group of '%s' to '%s:%s'", path,
-				TT.owner_name, TT.group_name);
-		free(path);
-	}
-	toys.exitval |= ret;
-
-	return 0;
-}
-
-void chgrp_main(void)
-{
-	int ischown = toys.which->name[2] == 'o';
-	char **s, *own;
-
-	// Distinguish chown from chgrp
-	if (ischown) {
-		char *grp;
-		struct passwd *p;
-
-		own = xstrdup(*toys.optargs);
-		if ((grp = strchr(own, ':')) || (grp = strchr(own, '.'))) {
-			*(grp++) = 0;
-			TT.group_name = grp;
-		}
-		if (*own) {
-			TT.owner_name = own;
-			p = getpwnam(own);
-			// TODO: trailing garbage?
-			if (!p && isdigit(*own)) p=getpwuid(atoi(own));
-			if (!p) error_exit("no user '%s'", own);
-			TT.owner = p->pw_uid;
-		}
-	} else TT.group_name = *toys.optargs;
-
-	if (TT.group_name) {
-		struct group *g;
-		g = getgrnam(TT.group_name);
-		if (!g) g=getgrgid(atoi(TT.group_name));
-		if (!g) error_exit("no group '%s'", TT.group_name);
-		TT.group = g->gr_gid;
-	}
-
-	for (s=toys.optargs+1; *s; s++) {
-		struct dirtree *new = dirtree_add_node(AT_FDCWD, *s,
-			toys.optflags&(FLAG_H|FLAG_L));
-		if (new) handle_callback(new, do_chgrp);
-		else toys.exitval = 1;
-	}
-
-	if (CFG_TOYBOX_FREE) free(own);
-}
--- a/toys/chmod.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * chmod.c - Change file mode bits
- *
- * Copyright 2012 Rob Landley <rob@landley.net>
- *
- * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/chmod.html
- *
-
-USE_CHMOD(NEWTOY(chmod, "<2?vR", TOYFLAG_BIN))
-
-config CHMOD
-    bool "chmod"
-    default y
-    help
-        usage: chmod [-R] MODE FILE...
-
-        Change mode of listed file[s] (recursively with -R).
-
-        MODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo]
-
-        Stanzas are applied in order: For each category (u = user,
-        g = group, o = other, a = all three, if none specified default is a),
-        set (+), clear (-), or copy (=), r = read, w = write, x = execute.
-        s = u+s = suid, g+s = sgid, o+s = sticky. (+t is an alias for o+s).
-        suid/sgid: execute as the user/group who owns the file.
-        sticky: can't delete files you don't own out of this directory
-        X = x for directories or if any category already has x set.
-
-        Or MODE can be an octal value up to 7777	ug uuugggooo	top +
-        bit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1	sstrwxrwxrwx	bottom
-
-        Examples:
-        chmod u+w file - allow owner of "file" to write to it.
-        chmod 744 file - user can read/write/execute, everyone else read only
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-    char *mode;
-)
-
-#define TT this.chmod
-
-#define FLAG_R 1
-#define FLAG_v 2
-
-int do_chmod(struct dirtree *try)
-{
-    mode_t mode;
-
-    if (!dirtree_notdotdot(try)) return 0;
-
-    mode = string_to_mode(TT.mode, try->st.st_mode);
-    if (toys.optflags & FLAG_v) {
-        char *s = dirtree_path(try, 0);
-        printf("chmod '%s' to %04o\n", s, mode);
-        free(s);
-    }
-    wfchmodat(dirtree_parentfd(try), try->name, mode);
-
-    return (toys.optflags & FLAG_R) ? DIRTREE_RECURSE : 0;
-}
-
-void chmod_main(void)
-{
-    TT.mode = *toys.optargs;
-    char **file;
-
-    for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chmod);
-}
--- a/toys/chroot.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * chroot.c - Run command in new root directory.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3.
-
-USE_CHROOT(NEWTOY(chroot, "^<1", TOYFLAG_USR|TOYFLAG_SBIN))
-
-config CHROOT
-	bool "chroot"
-	default y
-	help
-	  usage: chroot NEWPATH [commandline...]
-
-	  Run command within a new root directory.  If no command, run /bin/sh.
-*/
-
-#include "toys.h"
-
-void chroot_main(void)
-{
-	char *binsh[] = {"/bin/sh", "-i", 0};
-	if (chdir(*toys.optargs) || chroot("."))
-		perror_exit("%s", *toys.optargs);
-	xexec(toys.optargs[1] ? toys.optargs+1 : binsh);
-}
--- a/toys/chvt.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * chvt.c - switch virtual terminals
- *
- * Copyright (C) 2008 David Anders <danders@amltd.com>
- *
- * Not in SUSv3.
-
-USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_SBIN))
-
-config CHVT
-	bool "chvt"
-	default y
-	help
-	  usage: chvt N
-
-	  Change to virtual terminal number N.  (This only works in text mode.)
-
-	  Virtual terminals are the Linux VGA text mode displays, ordinarily
-	  switched between via alt-F1, alt-F2, etc.  Use ctrl-alt-F1 to switch
-	  from X to a virtual terminal, and alt-F6 (or F7, or F8) to get back.
-*/
-
-#include "toys.h"
-
-/* Note: get_console_fb() will need to be moved into a seperate lib section */
-int get_console_fd()
-{
-	int fd;
-	char *consoles[]={"/dev/console", "/dev/vc/0", "/dev/tty", NULL}, **cc;
-
-	cc = consoles;
-	while (*cc) {
-		fd = open(*cc++, O_RDWR);
-		if (fd >= 0) return fd;
-	}
-
-	return -1;
-}
-
-void chvt_main(void)
-{
-	int vtnum, fd;
-
-	vtnum=atoi(*toys.optargs);
-
-	fd=get_console_fd();
-	// These numbers are VT_ACTIVATE and VT_WAITACTIVE from linux/vt.h
-	if (fd < 0 || ioctl(fd, 0x5606, vtnum) || ioctl(fd, 0x5607, vtnum))
-		perror_exit(NULL);
-}
--- a/toys/cksum.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * cksum.c - produce crc32 checksum value for each input
- *
- * Copyright 2008 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/cksum.html
-
-USE_CKSUM(NEWTOY(cksum, "IPLN", TOYFLAG_BIN))
-
-config CKSUM
-	bool "cksum"
-	default y
-	help
-	  usage: cksum [-IPLN] [file...]
-
-	  For each file, output crc32 checksum value, length and name of file.
-	  If no files listed, copy from stdin.  Filename "-" is a synonym for stdin.
-
-	  -L	Little endian (defaults to big endian)
-	  -P	Pre-inversion
-	  -I	Skip post-inversion
-	  -N	Do not include length in CRC calculation
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	unsigned crc_table[256];
-)
-
-#define TT this.cksum
-
-static unsigned cksum_be(unsigned crc, unsigned char c)
-{
-	return (crc<<8)^TT.crc_table[(crc>>24)^c];
-}
-
-static unsigned cksum_le(unsigned crc, unsigned char c)
-{
-	return TT.crc_table[(crc^c)&0xff] ^ (crc>>8);
-}
-
-static void do_cksum(int fd, char *name)
-{
-	unsigned crc = (toys.optflags&4) ? 0xffffffff : 0;
-	uint64_t llen = 0, llen2;
-	unsigned (*cksum)(unsigned crc, unsigned char c);
-
-
-	cksum = (toys.optflags&2) ? cksum_le : cksum_be;
-	// CRC the data
-
-	for (;;) {
-		int len, i;
-
-		len = read(fd, toybuf, sizeof(toybuf));
-		if (len<0) {
-			perror_msg("%s",name);
-			toys.exitval = EXIT_FAILURE;
-		}
-		if (len<1) break;
-
-		llen += len;
-		for (i=0; i<len; i++) crc=cksum(crc, toybuf[i]);
-	}
-
-	// CRC the length
-
-	llen2 = llen;
-	if (!(toys.optflags&1)) {
-		while (llen) {
-			crc = cksum(crc, llen);
-			llen >>= 8;
-		}
-	}
-
-	printf("%u %"PRIu64, (toys.optflags&8) ? crc : ~crc, llen2);
-	if (strcmp("-", name)) printf(" %s", name);
-	xputc('\n');
-}
-
-void cksum_main(void)
-{
-	crc_init(TT.crc_table, toys.optflags&2);
-	loopfiles(toys.optargs, do_cksum);
-}
--- a/toys/clear.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * clear.c - clear the screen
- *
- * Copyright 2012 Rob Landley <rob@landley.net>
- *
- * Not in SUSv4.
-
-USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-
-config CLEAR
-	bool "clear"
-	default y
-	help
-	  Clear the screen.
-*/
-
-#include "toys.h"
-
-void clear_main(void)
-{
-	write(1, "\e[2J\e[H", 7);
-}
--- a/toys/cmp.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * cmp.c - Compare two files.
- *
- * Copyright 2012 Timothy Elliott <tle@holymonkey.com>
- *
- * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cmp.html
-
-USE_CMP(NEWTOY(cmp, "<2>2ls", TOYFLAG_USR|TOYFLAG_BIN))
-
-config CMP
-	bool "cmp"
-	default y
-	help
-	  usage: cmp [-l] [-s] FILE1 FILE2
-
-	  Compare the contents of two files.
-
-	  -l show all differing bytes
-	  -s silent
-*/
-
-#include "toys.h"
-
-#define FLAG_s	1
-#define FLAG_l	2
-
-DEFINE_GLOBALS(
-	int fd;
-	char *name;
-)
-
-#define TT this.cmp
-
-// This handles opening the file and 
-
-void do_cmp(int fd, char *name)
-{
-	int i, len1, len2, min_len, size = sizeof(toybuf)/2;
-	long byte_no = 1, line_no = 1;
-	char *buf2 = toybuf+size;
-
-	// First time through, cache the data and return.
-	if (!TT.fd) {
-		TT.name = name;
-		// On return the old filehandle is closed, and this assures that even
-		// if we were called with stdin closed, the new filehandle != 0.
-		TT.fd = dup(fd);
-		return;
-	}
-
-	for (;;) {
-		len1 = readall(TT.fd, toybuf, size);
-		len2 = readall(fd, buf2, size);
-
-		min_len = len1 < len2 ? len1 : len2;
-		for (i=0; i<min_len; i++) {
-			if (toybuf[i] != buf2[i]) {
-				toys.exitval = 1;
-				if (toys.optflags & FLAG_l)
-					printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]);
-				else {
-					if (!(toys.optflags & FLAG_s)) {
-						printf("%s %s differ: char %ld, line %ld\n",
-							TT.name, name, byte_no, line_no);
-						toys.exitval++;
-					}
-					goto out;
-				}
-			}
-			byte_no++;
-			if (toybuf[i] == '\n') line_no++;
-		}
-		if (len1 != len2) {
-			if (!(toys.optflags & FLAG_s)) {
-				fprintf(stderr, "cmp: EOF on %s\n",
-					len1 < len2 ? TT.name : name);
-			}
-			toys.exitval = 1;
-			break;
-		}
-		if (len1 < 1) break;
-	}
-out:
-	if (CFG_TOYBOX_FREE) close(TT.fd);
-}
-
-void cmp_main(void)
-{
-	loopfiles_rw(toys.optargs, O_RDONLY, 0, toys.optflags&FLAG_s, do_cmp);
-}
-
--- a/toys/comm.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * comm.c - select or reject lines common to two files
- *
- * Copyright 2012 Ilya Kuzmich <ikv@safe-mail.net>
- *
- * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/comm.html
-
-// <# and ># take single digit, so 321 define flags
-USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
-
-config COMM
-	bool "comm"
-	default y
-	help
-	  usage: comm [-123] FILE1 FILE2
-
-	  Reads FILE1 and FILE2, which should be ordered, and produces three text
-	  columns as output: lines only in FILE1; lines only in FILE2; and lines
-	  in both files. Filename "-" is a synonym for stdin.
-
-	  -1 suppress the output column of lines unique to FILE1
-	  -2 suppress the output column of lines unique to FILE2
-	  -3 suppress the output column of lines duplicated in FILE1 and FILE2
-*/
-
-#include "toys.h"
-
-#define FLAG_1 1
-#define FLAG_2 2
-#define FLAG_3 4
-
-static void writeline(const char *line, int col)
-{
-	if (col == 0 && toys.optflags & FLAG_1) return;
-	else if (col == 1) {
-		if (toys.optflags & FLAG_2) return;
-		if (!(toys.optflags & FLAG_1)) putchar('\t');
-	} else if (col == 2) {
-		if (toys.optflags & FLAG_3) return;
-		if (!(toys.optflags & FLAG_1)) putchar('\t');
-		if (!(toys.optflags & FLAG_2)) putchar('\t');
-	}
-	puts(line);
-}
-
-void comm_main(void)
-{
-	int file[2];
-	char *line[2];
-	int i;
-
-	if (toys.optflags == 7) return;
-
-	for (i = 0; i < 2; i++) {
-		file[i] = strcmp("-", toys.optargs[i]) ? xopen(toys.optargs[i], O_RDONLY) : 0;
-		line[i] = get_line(file[i]);
-	}
-
-	while (line[0] && line[1]) {
-		int order = strcmp(line[0], line[1]);
-
-		if (order == 0) {
-			writeline(line[0], 2);
-			for (i = 0; i < 2; i++) {
-				free(line[i]);
-				line[i] = get_line(file[i]);
-			}
-		} else {
-			i = order < 0 ? 0 : 1;
-			writeline(line[i], i);
-			free(line[i]);
-			line[i] = get_line(file[i]);
-		}
-	}
-
-	/* print rest of the longer file */
-	for (i = line[0] ? 0 : 1; line[i];) {
-		writeline(line[i], i);
-		free(line[i]);
-		line[i] = get_line(file[i]);
-	}
-
-	if (CFG_TOYBOX_FREE) for (i = 0; i < 2; i--) xclose(file[i]);
-}
--- a/toys/count.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * count.c - Progress indicator from stdin to stdout
- *
- * Copyright 2002 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3.
-
-USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-
-config COUNT
-	bool "count"
-	default y
-	help
-	  usage: count
-
-	  Copy stdin to stdout, displaying simple progress indicator to stderr.
-*/
-
-#include "toys.h"
-
-void count_main(void)
-{
-	uint64_t size = 0;
-	int len;
-	char buf[32];
-
-	for (;;) {
-		len = xread(0, toybuf, sizeof(toybuf));
-		if (!len) break;
-		size += len;
-		xwrite(1, toybuf, len);
-		xwrite(2, buf, sprintf(buf, "%"PRIu64" bytes\r", size));
-	}
-	xwrite(2, "\n", 1);
-}
--- a/toys/cp.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,224 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * cp.c - Copy files.
- *
- * Copyright 2008 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/cp.html
- *
- * "R+ra+d+p+r"
-USE_CP(NEWTOY(cp, "<2vslrRdpaHLPif", TOYFLAG_BIN))
-
-config CP
-	bool "cp (broken by dirtree changes)"
-	default n
-	help
-	  usage: cp -fiprdal SOURCE... DEST
-
-	  Copy files from SOURCE to DEST.  If more than one SOURCE, DEST must
-	  be a directory.
-
-		-f	force copy by deleting destination file
-		-i	interactive, prompt before overwriting existing DEST
-		-p	preserve timestamps, ownership, and permissions
-		-r	recurse into subdirectories (DEST must be a directory)
-		-d	don't dereference symlinks
-		-a	same as -dpr
-		-l	hard link instead of copying
-		-v	verbose
-*/
-
-#include "toys.h"
-
-#define FLAG_f 1
-#define FLAG_i 2
-#define FLAG_P 4	// todo
-#define FLAG_L 8	// todo
-#define FLAG_H 16	// todo
-#define FLAG_a 32
-#define FLAG_p 64
-#define FLAG_d 128	// todo
-#define FLAG_R 256
-#define FLAG_r 512
-#define FLAG_l 1024	// todo
-#define FLAG_s 2048	// todo
-#define FLAG_v 4098
-
-DEFINE_GLOBALS(
-	char *destname;
-	int destisdir;
-	int destisnew;
-	int keep_symlinks;
-)
-
-#define TT this.cp
-
-// Copy an individual file or directory to target.
-
-void cp_file(char *src, char *dst, struct stat *srcst)
-{
-	int fdout = -1;
-
-	// -i flag is specified and dst file exists.
-	if ((toys.optflags&FLAG_i) && !access(dst, R_OK)
-		&& !yesno("cp: overwrite", 1))
-			return;
-
-	if (toys.optflags & FLAG_v)
-		printf("'%s' -> '%s'\n", src, dst);
-
-	// Copy directory or file to destination.
-
-	if (S_ISDIR(srcst->st_mode)) {
-		struct stat st2;
-
-		// Always make directory writeable to us, so we can create files in it.
-		//
-		// Yes, there's a race window between mkdir() and open() so it's
-		// possible that -p can be made to chown a directory other than the one
-		// we created.  The closest we can do to closing this is make sure
-		// that what we open _is_ a directory rather than something else.
-
-		if ((mkdir(dst, srcst->st_mode | 0200) && errno != EEXIST)
-			|| 0>(fdout=open(dst, 0)) || fstat(fdout, &st2)
-			|| !S_ISDIR(st2.st_mode))
-		{
-			perror_exit("mkdir '%s'", dst);
-		}
-	} else if (TT.keep_symlinks && S_ISLNK(srcst->st_mode)) {
-		char *link = xreadlink(src);
-
-		// Note: -p currently has no effect on symlinks.  How do you get a
-		// filehandle to them?  O_NOFOLLOW causes the open to fail.
-		if (!link || symlink(link, dst)) perror_msg("link '%s'", dst);
-		free(link);
-		return;
-	} else if (toys.optflags & FLAG_l) {
-		if (link(src, dst)) perror_msg("link '%s'");
-		return;
-	} else {
-		int fdin, i;
-
-		fdin = xopen(src, O_RDONLY);
-		for (i=2 ; i; i--) {
-			fdout = open(dst, O_RDWR|O_CREAT|O_TRUNC, srcst->st_mode);
-			if (fdout>=0 || !(toys.optflags & FLAG_f)) break;
-			unlink(dst);
-		}
-		if (fdout<0) perror_exit("%s", dst);
-		xsendfile(fdin, fdout);
-		close(fdin);
-	}
-
-	// Inability to set these isn't fatal, some require root access.
-	// Can't do fchmod() etc here because -p works on mkdir, too.
-
-	if (toys.optflags & (FLAG_p|FLAG_a)) {
-		int mask = umask(0);
-		struct utimbuf ut;
-
-		(void) fchown(fdout,srcst->st_uid, srcst->st_gid);
-		ut.actime = srcst->st_atime;
-		ut.modtime = srcst->st_mtime;
-		utime(dst, &ut);
-		umask(mask);
-	}
-	xclose(fdout);
-}
-
-// Callback from dirtree_read() for each file/directory under a source dir.
-
-int cp_node(struct dirtree *node)
-{
-	char *path = dirtree_path(node, 0); // TODO: use openat() instead
-	char *s = path+strlen(path);
-	struct dirtree *n;
-
-	// Find appropriate chunk of path for destination.
-
-	n = node;
-	if (!TT.destisdir) n = n->parent;
-	for (;;n = n->parent) {
-		while (s!=path) {
-			if (*(--s)=='/') break;
-		}
-		if (!n) break;
-	}
-	if (s != path) s++;
-
-	s = xmsprintf("%s/%s", TT.destname, s);
-	cp_file(path, s, &(node->st));
-	free(s);
-	free(path); // redo this whole darn function.
-
-	return 0;
-}
-
-void cp_main(void)
-{
-	struct stat st;
-	int i;
-
-	// Grab target argument.  (Guaranteed to be there due to "<2" above.)
-
-	TT.destname = toys.optargs[--toys.optc];
-
-	// If destination doesn't exist, are we ok with that?
-
-	if (stat(TT.destname, &st)) {
-		if (toys.optc>1) goto error_notdir;
-		TT.destisnew++;
-
-	// If destination exists...
-
-	} else {
-		if (S_ISDIR(st.st_mode)) TT.destisdir++;
-		else if (toys.optc > 1) goto error_notdir;
-	}
-
-	// Handle sources
-
-	for (i=0; i<toys.optc; i++) {
-		char *src = toys.optargs[i];
-		char *dst;
-
-		// Skip src==dest (TODO check inodes to catch "cp blah ./blah").
-
-		if (!strcmp(src, TT.destname)) continue;
-
-		// Skip nonexistent sources.
-
-		TT.keep_symlinks = toys.optflags & (FLAG_d|FLAG_a);
-		if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st))
-		{
-			perror_msg("'%s'", src);
-			toys.exitval = 1;
-			continue;
-		}
-
-		// Copy directory or file.
-
-		if (TT.destisdir) {
-			dst = strrchr(src, '/');
-			if (dst) dst++;
-			else dst=src;
-			dst = xmsprintf("%s/%s", TT.destname, dst);
-		} else dst = TT.destname;
-		if (S_ISDIR(st.st_mode)) {
-			if (toys.optflags & (FLAG_r|FLAG_R|FLAG_a)) {
-				cp_file(src, dst, &st);
-
-				TT.keep_symlinks++;
-				strncpy(toybuf, src, sizeof(toybuf)-1);
-				toybuf[sizeof(toybuf)-1]=0;
-				dirtree_read(toybuf, cp_node);
-			} else error_msg("Skipped dir '%s'", src);
-		} else cp_file(src, dst, &st);
-		if (TT.destisdir) free(dst);
-	}
-
-	return;
-
-error_notdir:
-	error_exit("'%s' isn't a directory", TT.destname);
-}
--- a/toys/date.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * date.c - set/get the date
- *
- * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
- *
- * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/date.html
-
-USE_DATE(NEWTOY(date, "r:u", TOYFLAG_BIN))
-
-config DATE
-	bool "date"
-	default y
-	help
-	  usage: date [-u] [-r file] [+format] | mmddhhmm[[cc]yy]
-
-	  Set/get the current date/time
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-    char *file;
-)
-
-#define TT this.date
-
-#define FLAG_u 1
-#define FLAG_r 2
-
-void date_main(void)
-{
-    const char *format_string = "%a %b %e %H:%M:%S %Z %Y";
-    time_t now = time(NULL);
-    struct tm tm;
-
-    if (TT.file) {
-        struct stat st;
-
-        xstat(TT.file, &st);
-        now = st.st_mtim.tv_sec;
-    }
-    ((toys.optflags & FLAG_u) ? gmtime_r : localtime_r)(&now, &tm);
-
-    // Display the date?
-    if (!toys.optargs[0] || toys.optargs[0][0] == '+') {
-        if (toys.optargs[0]) format_string = toys.optargs[0]+1;
-        if (!strftime(toybuf, sizeof(toybuf), format_string, &tm))
-            perror_msg("bad format `%s'", format_string);
-
-        puts(toybuf);
-
-    // Set the date
-    } else {
-        struct timeval tv;
-        char *s = *toys.optargs;
-        int len = strlen(s);
-
-        if (len < 8 || len > 12 || (len & 1)) error_msg("bad date `%s'", s);
-
-        // Date format: mmddhhmm[[cc]yy]
-        memset(&tm, 0, sizeof(tm));
-        len = sscanf(s, "%2u%2u%2u%2u", &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
-               &tm.tm_min);
-        tm.tm_mon--;
-
-        // If year specified, overwrite one we fetched earlier
-        if (len > 8) {
-            sscanf(s, "%u", &tm.tm_year);
-            if (len == 12) tm.tm_year -= 1900;
-            /* 69-99 = 1969-1999, 0 - 68 = 2000-2068 */
-            else if (tm.tm_year < 69) tm.tm_year += 100;
-        }
-
-        if (toys.optflags & FLAG_u) {
-            // Get the UTC version of a struct tm
-            char *tz = CFG_TOYBOX_FREE ? getenv("TZ") : 0;
-            setenv("TZ", "UTC", 1);
-            tzset();
-            tv.tv_sec = mktime(&tm);
-            if (CFG_TOYBOX_FREE) {
-                if (tz) setenv("TZ", tz, 1);
-                else unsetenv("TZ");
-                tzset();
-            }
-        } else tv.tv_sec = mktime(&tm);
-
-        if (tv.tv_sec == (time_t)-1) error_msg("bad `%s'", toys.optargs[0]);
-        tv.tv_usec = 0;
-        if (!strftime(toybuf, sizeof(toybuf), format_string, &tm))
-            perror_msg("bad format `%s'", format_string);
-        puts(toybuf);
-        if (settimeofday(&tv, NULL) < 0) perror_msg("cannot set date");
-    }
-}
--- a/toys/df.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * df.c - report free disk space.
- *
- * Copyright 2006 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/df.html
-
-USE_DF(NEWTOY(df, "Pkt*a", TOYFLAG_USR|TOYFLAG_SBIN))
-
-config DF
-	bool "df (disk free)"
-	default y
-	help
-	  usage: df [-t type] [FILESYSTEM ...]
-
-	  The "disk free" command, df shows total/used/available disk space for
-	  each filesystem listed on the command line, or all currently mounted
-	  filesystems.
-
-	  -t type
-		Display only filesystems of this type.
-
-config DF_PEDANTIC
-	bool "options -P and -k"
-	default y
-	depends on DF
-	help
-	  usage: df [-Pk]
-
-	  -P	The SUSv3 "Pedantic" option
-
-		Provides a slightly less useful output format dictated by
-		the Single Unix Specification version 3, and sets the
-		units to 512 bytes instead of the default 1024 bytes.
-
-	  -k	Sets units back to 1024 bytes (the default without -P)
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	struct arg_list *fstype;
-
-	long units;
-)
-
-#define TT this.df
-
-static void show_mt(struct mtab_list *mt)
-{
-	int len;
-	long size, used, avail, percent;
-	uint64_t block;
-
-	// Return if it wasn't found (should never happen, but with /etc/mtab...)
-	if (!mt) return;
-
-	// If we have -t, skip other filesystem types
-	if (TT.fstype) {
-		struct arg_list *al;
-
-		for (al = TT.fstype; al; al = al->next) {
-			if (!strcmp(mt->type, al->arg)) break;
-		}
-		if (!al) return;
-	}
-
-	// If we don't have -a, skip synthetic filesystems
-	if (!(toys.optflags & 1) && !mt->statvfs.f_blocks) return;
-
-	// Figure out how much total/used/free space this filesystem has,
-	// forcing 64-bit math because filesystems are big now.
-	block = mt->statvfs.f_bsize ? mt->statvfs.f_bsize : 1;
-	size = (long)((block * mt->statvfs.f_blocks) / TT.units);
-	used = (long)((block * (mt->statvfs.f_blocks-mt->statvfs.f_bfree))
-			/ TT.units);
-	avail = (long)((block
-				* (getuid() ? mt->statvfs.f_bavail : mt->statvfs.f_bfree))
-			/ TT.units);
-	percent = size ? 100-(long)((100*(uint64_t)avail)/size) : 0;
-
-	// Figure out appropriate spacing
-	len = 25 - strlen(mt->device);
-	if (len < 1) len = 1;
-	if (CFG_DF_PEDANTIC && (toys.optflags & 8)) {
-		printf("%s %ld %ld %ld %ld%% %s\n", mt->device, size, used, avail,
-				percent, mt->dir);
-	} else {
-		printf("%s% *ld % 10ld % 9ld % 3ld%% %s\n",mt->device, len,
-			size, used, avail, percent, mt->dir);
-	}
-}
-
-void df_main(void)
-{
-	struct mtab_list *mt, *mt2, *mtlist;
-
-	// Handle -P and -k
-	TT.units = 1024;
-	if (CFG_DF_PEDANTIC && (toys.optflags & 8)) {
-		// Units are 512 bytes if you select "pedantic" without "kilobytes".
-		if ((toys.optflags&3) == 1) TT.units = 512;
-		printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n",
-			TT.units);
-	} else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on");
-
-	mtlist = getmountlist(1);
-
-	// If we have a list of filesystems on the command line, loop through them.
-	if (*toys.optargs) {
-		char **next;
-
-		for(next = toys.optargs; *next; next++) {
-			struct stat st;
-
-			// Stat it (complain if we can't).
-			if(stat(*next, &st)) {
-				perror_msg("`%s'", *next);
-				toys.exitval = 1;
-				continue;
-			}
-
-			// Find and display this filesystem.  Use _last_ hit in case of
-			// -- bind mounts.
-			mt2 = NULL;
-			for (mt = mtlist; mt; mt = mt->next)
-				if (st.st_dev == mt->stat.st_dev) mt2 = mt;
-			show_mt(mt2);
-		}
-	} else {
-		// Get and loop through mount list.
-
-		for (mt = mtlist; mt; mt = mt->next) {
-			struct mtab_list *mt2, *mt3;
-
-			if (!mt->stat.st_dev) continue;
-
-			// Filter out overmounts.
-			mt3 = mt;
-			for (mt2 = mt->next; mt2; mt2 = mt2->next) {
-				if (mt->stat.st_dev == mt2->stat.st_dev) {
-					// For --bind mounts, take last match
-					if (!strcmp(mt->device, mt2->device)) mt3 = mt2;
-					// Filter out overmounts
-					mt2->stat.st_dev = 0;
-				}
-			}
-			show_mt(mt3);
-		}
-	}
-
-	if (CFG_TOYBOX_FREE) llist_traverse(mtlist, free);
-}
--- a/toys/dirname.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * dirname.c - show directory portion of path
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/dirname.html
-
-USE_DIRNAME(NEWTOY(dirname, "<1", TOYFLAG_USR|TOYFLAG_BIN))
-
-config DIRNAME
-	bool "dirname"
-	default y
-	help
-	  usage: dirname PATH
-
-	  Show directory portion of path.
-*/
-
-#include "toys.h"
-
-void dirname_main(void)
-{
-	puts(dirname(*toys.optargs));
-}
--- a/toys/dmesg.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * dmesg.c - display/control kernel ring buffer.
- *
- * Copyright 2006, 2007 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3.
-
-USE_DMESG(NEWTOY(dmesg, "s#n#c", TOYFLAG_BIN))
-
-config DMESG
-	bool "dmesg"
-	default y
-	help
-	  usage: dmesg [-n level] [-s bufsize] | -c
-
-	  Print or control the kernel ring buffer.
-
-	  -n	Set kernel logging level (1-9).
-	  -s	Size of buffer to read (in bytes), default 16384.
-	  -c	Clear the ring buffer after printing.
-*/
-
-#include "toys.h"
-#include <sys/klog.h>
-
-DEFINE_GLOBALS(
-	long level;
-	long size;
-)
-
-#define TT this.dmesg
-
-void dmesg_main(void)
-{
-	// For -n just tell kernel to which messages to keep.
-	if (toys.optflags & 2) {
-		if (klogctl(8, NULL, TT.level))
-			error_exit("klogctl");
-	} else {
-		int size, i, last = '\n';
-		char *data;
-
-		// Figure out how much data we need, and fetch it.
-		size = TT.size;
-		if (size<2) size = 16384;
-		data = xmalloc(size);
-		size = klogctl(3 + (toys.optflags&1), data, size);
-		if (size < 0) error_exit("klogctl");
-
-		// Display data, filtering out level markers.
-		for (i=0; i<size; ) {
-			if (last=='\n' && data[i]=='<') i += 3;
-			else xputc(last = data[i++]);
-		}
-		if (last!='\n') xputc('\n');
-		if (CFG_TOYBOX_FREE) free(data);
-	}
-}
--- a/toys/dos2unix.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * dos2unix.c - convert newline format
- *
- * Copyright 2012 Rob Landley <rob@landley.net>
- *
- * No standard
-
-USE_DOS2UNIX(NEWTOY(dos2unix, NULL, TOYFLAG_BIN))
-USE_DOS2UNIX(OLDTOY(unix2dos, dos2unix, NULL, TOYFLAG_BIN))
-
-config DOS2UNIX
-	bool "dos2unix/unix2dos"
-	default y
-	help
-	  usage: dos2unix/unix2dos [file...]
-
-	  Convert newline format between dos (\r\n) and unix (just \n)
-	  If no files listed copy from stdin, "-" is a synonym for stdin.
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	char *tempfile;
-)
-
-#define TT this.dos2unix
-
-static void do_dos2unix(int fd, char *name)
-{
-	char c = toys.which->name[0];
-	int outfd = 1, catch = 0;
-
-	if (fd) outfd = copy_tempfile(fd, name, &TT.tempfile);
-
-	for (;;) {
-		int len, in, out;
-
-		len = read(fd, toybuf+(sizeof(toybuf)/2), sizeof(toybuf)/2);
-		if (len<0) {
-			perror_msg("%s",name);
-			toys.exitval = 1;
-		}
-		if (len<1) break;
-
-		for (in = out = 0; in < len; in++) {
-			char x = toybuf[in+sizeof(toybuf)/2];
-
-			// Drop \r only if followed by \n in dos2unix mode
-			if (catch) {
-				if (c == 'u' || x != '\n') toybuf[out++] = '\r';
-				catch = 0;
-			// Add \r only if \n not after \r in unix2dos mode
-			} else if (c == 'u' && x == '\n') toybuf[out++] = '\r';
-
-			if (x == '\r') catch++;
-			else toybuf[out++] = x;
-		}
-		xwrite(outfd, toybuf, out);
-	}
-	if (catch) xwrite(outfd, "\r", 1);
-
-	if (fd) replace_tempfile(-1, outfd, &TT.tempfile);
-}
-
-void dos2unix_main(void)
-{
-	loopfiles(toys.optargs, do_dos2unix);
-}
--- a/toys/echo.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * echo.c - echo supporting -n and -e.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/echo.html
-
-USE_ECHO(NEWTOY(echo, "^?en", TOYFLAG_BIN))
-
-config ECHO
-	bool "echo"
-	default y
-	help
-	  usage: echo [-ne] [args...]
-
-	  Write each argument to stdout, with one space between each, followed
-	  by a newline.
-
-	  -n	No trailing newline.
-	  -e	Process the following escape sequences:
-	   \\	 backslash
-	   \0NNN octal values (1 to 3 digits)
-	   \a	 alert (beep/flash)
-	   \b	 backspace
-	   \c	 stop output here (avoids trailing newline)
-	   \f	 form feed
-	   \n	 newline
-	   \r	 carriage return
-	   \t	 horizontal tab
-	   \v	 vertical tab
-	   \xHH	 hexadecimal values (1 to 2 digits)
-*/
-
-#define THIS echo
-#include "toys.h"
-
-#define FLAG_e (1<<1)
-#define FLAG_n (1<<0)
-
-void echo_main(void)
-{
-	int i = 0, out;
-	char *arg, *from = "\\abfnrtv", *to = "\\\a\b\f\n\r\t\v", *c;
-
-	for (;;) {
-		arg = toys.optargs[i];
-		if (!arg) break;
-		if (i++) xputc(' ');
-
-		// Should we output arg verbatim?
-
-		if (!(toys.optflags&FLAG_e)) {
-			xprintf("%s", arg);
-			continue;
-		}
-
-		// Handle -e
-
-		for (c=arg;;) {
-			if (!(out = *(c++))) break;
-
-			// handle \escapes
-			if (out == '\\' && *c) {
-				int n = 0, slash = *(c++);
-				char *found = strchr(from, slash);
-				if (found) out = to[found-from];
-				else if (slash == 'c') goto done;
-				else if (slash == '0') {
-					out = 0;
-					while (*c>='0' && *c<='7' && n++<3)
-						out = (out*8)+*(c++)-'0';
-				} else if (slash == 'x') {
-					out = 0;							
-					while (n++<2) {
-						if (*c>='0' && *c<='9')
-							out = (out*16)+*(c++)-'0';
-						else {
-							int temp = tolower(*c);
-							if (temp>='a' && temp<='f') {
-								out = (out*16)+temp-'a'+10;
-								c++;
-							} else break;
-						}
-					}
-				// Slash in front of unknown character, print literal.
-				} else c--;
-			}
-			xputc(out);
-		}
-	}
-
-	// Output "\n" if no -n
-	if (!(toys.optflags&FLAG_n)) xputc('\n');
-done:
-	xflush();
-}
--- a/toys/env.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * env.c - Set the environment for command invocation.
- *
- * Copyright 2012 Tryn Mirell <tryn@mirell.org>
- * env.c
-
-USE_ENV(NEWTOY(env, "^i", TOYFLAG_USR|TOYFLAG_BIN))
-
-config ENV
-	bool "env"
-	default y
-	help
-          usage: env [-i] [NAME=VALUE...] [command [option...]]
-
-          Set the environment for command invocation.
-
-	  -i	Clear existing environment.
-*/
-
-#include "toys.h"
-
-extern char **environ;
-
-void env_main(void)
-{
-    char **ev;
-    char **command = NULL;
-    char *del = "=";
-    
-    if (toys.optflags & 1) clearenv();
-    
-    for (ev = toys.optargs; *ev != NULL; ev++) {
-        char *env, *val = NULL;
-        
-        env = strtok(*ev, del);
-        
-        if (env) val = strtok(NULL, del);
-        
-        if (val) setenv(env, val, 1);
-        else {
-            command = ev;
-            break;
-        }
-    }
-    
-    if (!command) {
-        char **ep;
-        for (ep = environ; *ep; ep++) xputs(*ep);
-        return;
-    } else xexec(command);
-}
--- a/toys/false.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * false.c - Return nonzero.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/false.html
-
-USE_FALSE(NEWTOY(false, NULL, TOYFLAG_BIN))
-
-config FALSE
-	bool "false"
-	default y
-	help
-	  Return nonzero.
-*/
-
-#include "toys.h"
-
-void false_main(void)
-{
-	toys.exitval = 1;
-}
--- a/toys/free.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * free.c - Display amount of free and used memory in the system.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
-
-USE_FREE(NEWTOY(free, "gmkb", TOYFLAG_USR|TOYFLAG_BIN))
-
-config FREE
-	bool "free"
-	default y
-	help
-	  usage: free [-bkmg]
-
-	  Display the total, free and used amount of physical memory and
-	  swap space.
-
-	  -bkmg    Output in bytes (default), KB, MB or GB
-*/
-
-#include "toys.h"
-
-static unsigned long long convert(unsigned long d, unsigned int iscale,
-				unsigned int oscale)
-{
-	return ((unsigned long long)d*iscale)>>oscale;
-}
-
-void free_main(void)
-{
-	struct sysinfo info;
-	unsigned int iscale = 1;
-	unsigned int oscale = 0;
-
-	sysinfo(&info);
-	if (info.mem_unit) iscale = info.mem_unit;
-	if (toys.optflags & 1) oscale = 0;
-	if (toys.optflags & 2) oscale = 10;
-	if (toys.optflags & 4) oscale = 20;
-	if (toys.optflags & 8) oscale = 30;
-
-	xprintf("\t\ttotal        used        free      shared     buffers\n");
-	xprintf("Mem:%17llu%12llu%12llu%12llu%12llu\n",
-		convert(info.totalram, iscale, oscale),
-		convert(info.totalram-info.freeram, iscale, oscale),
-		convert(info.freeram, iscale, oscale),
-		convert(info.sharedram, iscale, oscale),
-		convert(info.bufferram, iscale, oscale));
-
-	xprintf("-/+ buffers/cache:%15llu%12llu\n",
-		convert(info.totalram - info.freeram - info.bufferram, iscale, oscale),
-		convert(info.freeram + info.bufferram, iscale, oscale));
-
-	xprintf("Swap:%16llu%12llu%12llu\n",
-		convert(info.totalswap, iscale, oscale),
-		convert(info.totalswap - info.freeswap, iscale, oscale),
-		convert(info.freeswap, iscale, oscale));
-}
--- a/toys/head.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * head.c - copy first lines from input to stdout.
- *
- * Copyright 2006 Timothy Elliott <tle@holymonkey.com>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/head.html
-
-USE_HEAD(NEWTOY(head, "n#<0=10", TOYFLAG_BIN))
-
-config HEAD
-	bool "head"
-	default y
-	help
-	  usage: head [-n number] [file...]
-
-	  Copy first lines from files to stdout. If no files listed, copy from
-	  stdin. Filename "-" is a synonym for stdin.
-
-	  -n	Number of lines to copy.
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	long lines;
-	int file_no;
-)
-
-#define TT this.head
-
-static void do_head(int fd, char *name)
-{
-	int i, len, lines=TT.lines, size=sizeof(toybuf);
-
-	if (toys.optc > 1) {
-		// Print an extra newline for all but the first file
-		if (TT.file_no++) xprintf("\n");
-		xprintf("==> %s <==\n", name);
-		xflush();
-	}
-
-	while (lines) {
-		len = read(fd, toybuf, size);
-		if (len<0) {
-			perror_msg("%s",name);
-			toys.exitval = EXIT_FAILURE;
-		}
-		if (len<1) break;
-		
-		for(i=0; i<len;)
-			if (toybuf[i++] == '\n' && !--lines) break;
-
-		xwrite(1, toybuf, i);
-	}
-}
-
-void head_main(void)
-{
-	loopfiles(toys.optargs, do_head);
-}
--- a/toys/hello.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * hello.c - A hello world program.
- *
- * Copyright 2012 Rob Landley <rob@landley.net>
- *
- * Not in SUSv4/LSB.
- * See http://opengroup.org/onlinepubs/9699919799/utilities/
- * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html
-
-USE_HELLO(NEWTOY(hello, "e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
-
-config HELLO
-	bool "hello"
-	default n
-	help
-	  usage: hello [-a] [-b string] [-c number] [-d list] [-e count] [...]
-
-	  A hello world program.  You don't need this.
-
-	  Mostly used as an example/skeleton file for adding new commands,
-	  occasionally nice to test kernel booting via "init=/bin/hello".
-*/
-
-#include "toys.h"
-
-// Hello doesn't use these globals, they're here for example/skeleton purposes.
-
-DEFINE_GLOBALS(
-	char *b_string;
-	long c_number;
-	struct arg_list *d_list;
-	long e_count;
-
-	int more_globals;
-)
-
-#define TT this.hello
-
-#define FLAG_a	1
-#define FLAG_b	2
-#define FLAG_c	4
-#define FLAG_d	8
-#define FLAG_e	16
-
-void hello_main(void)
-{
-	printf("Hello world\n");
-
-	if (toys.optflags & FLAG_a) printf("Saw a\n");
-	if (toys.optflags & FLAG_b) printf("b=%s\n", TT.b_string);
-	if (toys.optflags & FLAG_c) printf("c=%ld\n", TT.c_number);
-	while (TT.d_list) {
-		printf("d=%s\n", TT.d_list->arg);
-		TT.d_list = TT.d_list->next;
-	}
-	if (TT.e_count) printf("e was seen %ld times", TT.e_count);
-
-	while (*toys.optargs) printf("optarg=%s\n", *(toys.optargs++));
-}
--- a/toys/help.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * help.c - Show help for toybox
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3, but exists as a bash builtin.
-
-USE_HELP(NEWTOY(help, "<1", TOYFLAG_BIN))
-
-config HELP
-	bool "help"
-	default y
-	help
-	  usage: help [command]
-
-	  Show usage information for toybox commands.
-	  Run "toybox" with no arguments for a list of available commands.
-*/
- 
-
-#include "toys.h"
-#include "generated/help.h"
-
-#undef NEWTOY
-#undef OLDTOY
-#define NEWTOY(name,opt,flags) help_##name "\0"
-#define OLDTOY(name,oldname,opts,flags) "\xff" #oldname "\0"
-static char *help_data =
-#include "generated/newtoys.h"
-;
-
-void help_main(void)
-{
-	struct toy_list *t = toy_find(*toys.optargs);
-	int i = t-toy_list;
-	char *s = help_data;
-
-	if (!t) error_exit("Unknown command '%s'", *toys.optargs);
-	for (;;) {
-		while (i--) s += strlen(s) + 1;
-		if (*s != 255) break;
-		i = toy_find(++s)-toy_list;
-		s = help_data;
-	}
-
-	fprintf(toys.exithelp ? stderr : stdout, "%s", s);
-}
--- a/toys/hostname.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * hostname.c - Get/Set the hostname
- *
- * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
- *
- * Not in SUSv4.
-
-USE_HOSTNAME(NEWTOY(hostname, NULL, TOYFLAG_BIN))
-
-config HOSTNAME
-	bool "hostname"
-	default n
-	help
-	  usage: hostname [newname]
-
-	  Get/Set the current hostname
-*/
-
-#include "toys.h"
-
-void hostname_main(void)
-{
-	const char *hostname = toys.optargs[0];
-        if (hostname) {
-            if (sethostname(hostname, strlen(hostname)))
-                perror_exit("cannot set hostname to '%s'", hostname);
-        } else {
-            if (gethostname(toybuf, sizeof(toybuf)))
-                perror_exit("cannot get hostname");
-            xputs(toybuf);
-        }
-}
--- a/toys/id.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * id.c - print real and effective user and group IDs
- *
- * Copyright 2012 Sony Network Entertainment, Inc.
- *
- * by Tim Bird <tim.bird@am.sony.com>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/id.html
-
-USE_ID(NEWTOY(id, "nGgru", TOYFLAG_BIN))
-
-config ID
-	bool "id"
-	default y
-	help
-	  usage: id [-nGgru]
-
-	  Print user and group ID.
-
-	  -n	print names instead of numeric IDs (to be used with -Ggu)
-	  -G	Show only the group IDs
-	  -g    Show only the effective group ID
-	  -r	Show real ID instead of effective ID
-	  -u    Show only the effective user ID
-*/
-
-#include "toys.h"
-
-#define FLAG_n (1<<4)
-#define FLAG_G (1<<3)
-#define FLAG_g (1<<2)
-#define FLAG_r (1<<1)
-#define FLAG_u 1
-
-static void s_or_u(char *s, unsigned u, int done)
-{
-	if (toys.optflags & FLAG_n) printf("%s", s);
-	else printf("%u", u);
-	if (done) {
-		xputc('\n');
-		exit(0);
-	}
-}
-
-static void showid(char *header, unsigned u, char *s)
-{
-	printf("%s%u(%s)", header, u, s);
-}
-
-struct passwd *xgetpwuid(uid_t uid)
-{
-	struct passwd *pwd = getpwuid(uid);
-	if (!pwd) error_exit(NULL);
-	return pwd;
-}
-
-struct group *xgetgrgid(gid_t gid)
-{
-	struct group *group = getgrgid(gid);
-	if (!group) error_exit(NULL);
-	return group;
-}
-
-void id_main(void)
-{
-	int flags = toys.optflags, i, ngroups;
-	struct passwd *pw;
-	struct group *grp;
-	uid_t uid = getuid(), euid = geteuid();
-	gid_t gid = getgid(), egid = getegid(), *groups;
-
-	/* check if a username is given */
-	if (*toys.optargs) {
-		if (!(pw = getpwnam(*toys.optargs)))
-			error_exit("no such user '%s'", *toys.optargs);
-		uid = euid = pw->pw_uid;
-		gid = egid = pw->pw_gid;
-	}
-
-	i = toys.optflags & FLAG_r;
-	pw = xgetpwuid(i ? uid : euid);
-	if (flags & FLAG_u) s_or_u(pw->pw_name, pw->pw_uid, 1);
-
-	grp = xgetgrgid(i ? gid : egid);
-	if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1);
-
-	if (!(flags & FLAG_G)) {
-		showid("uid=", pw->pw_uid, pw->pw_name);
-		showid(" gid=", grp->gr_gid, grp->gr_name);
-
-		if (!i) {
-			if (uid != euid) {
-				pw = xgetpwuid(euid);
-				showid(" euid=", pw->pw_uid, pw->pw_name);
-			}
-			if (gid != egid) {
-				grp = xgetgrgid(egid);
-				showid(" egid=", grp->gr_gid, grp->gr_name);
-			}
-		}
-
-		showid(" groups=", grp->gr_gid, grp->gr_name);
-	}
-
-
-	groups = (gid_t *)toybuf;
-	if (0 >= (ngroups = getgroups(sizeof(toybuf)/sizeof(gid_t), groups)))
-		perror_exit(0);
-
-	for (i = 0; i < ngroups; i++) {
-		xputc(' ');
-		if (!(grp = getgrgid(groups[i]))) perror_msg(0);
-		else if (flags & FLAG_G)
-			s_or_u(grp->gr_name, grp->gr_gid, 0);
-		else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name);
-	}
-	xputc('\n');
-}
--- a/toys/insmod.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * insmod.c - Load a module into the Linux kernel.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
-
-USE_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
-
-config INSMOD
-	bool "insmod"
-	default y
-	help
-	  usage: insmod MODULE [MODULE_OPTIONS]
-
-	  Load the module named MODULE passing options if given.
-*/
-
-#include "toys.h"
-
-#include <sys/syscall.h>
-#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
-
-void insmod_main(void)
-{
-	char * buf = NULL;
-	int len, res, i;
-	int fd = xopen(toys.optargs[0], O_RDONLY);
-
-	len = fdlength(fd);
-	buf = xmalloc(len);
-	xreadall(fd, buf, len);
-
-	i = 1;
-	while(toys.optargs[i] &&
-		strlen(toybuf) + strlen(toys.optargs[i]) + 2 < sizeof(toybuf)) {
-		strcat(toybuf, toys.optargs[i++]);
-		strcat(toybuf, " ");
-	}
-
-	res = init_module(buf, len, toybuf);
-	if (CFG_TOYBOX_FREE && buf != toybuf) free(buf);
-
-	if (res)
-		perror_exit("failed to load %s", toys.optargs[0]);
-}
--- a/toys/kill.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * kill.c - a program to send signals to processes
- *
- * Copyright 2012 Daniel Walter <d.walter@0x90.at>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/kill.html
-
-USE_KILL(NEWTOY(kill, "?s: l", TOYFLAG_BIN))
-
-config KILL
-	bool "kill"
-	default y
-	help
-	  usage: kill [-l [SIGNAL] | -s SIGNAL | -SIGNAL] pid...
-
-	  Send a signal to a process
-
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	char *signame;
-)
-
-#define TT this.kill
-
-void kill_main(void)
-{
-	int signum;
-	char *tmp, **args = toys.optargs;
-	pid_t pid;
-
-	// list signal(s)
-	if (toys.optflags & 1) {
-		if (*args) {
-			int signum = sig_to_num(*args);
-			char *s = NULL;
-
-			if (signum>=0) s = num_to_sig(signum&127);
-			puts(s ? s : "UNKNOWN");
-		} else sig_to_num(NULL);
-		return;
-	}
-
-	// signal must come before pids, so "kill -9 -1" isn't confusing.
-
-	if (!TT.signame && *args && **args=='-') TT.signame=*(args++)+1;
-	if (TT.signame) {
-		char *arg;
-		int i = strtol(TT.signame, &arg, 10);
-		if (!*arg) arg = num_to_sig(i);
-		else arg = TT.signame;
-
-		if (!arg || -1 == (signum = sig_to_num(arg)))
-			error_exit("Unknown signal '%s'", arg);
-	} else signum = SIGTERM;
-
-	if (!*args) {
-		toys.exithelp++;
-		error_exit("missing argument");
-	}
-
-	while (*args) {
-		char *arg = *(args++);
-
-		pid = strtol(arg, &tmp, 10);
-		if (*tmp || kill(pid, signum) < 0) {
-			error_msg("unknown pid '%s'", arg);
-			toys.exitval = EXIT_FAILURE;
-		}
-	}
-}
--- a/toys/killall.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * killall.c - Send signal (default: TERM) to all processes with given names.
- *
- * Copyright 2012 Andreas Heck <aheck@gmx.de>
- *
- * Not in SUSv4.
-
-USE_KILLALL(NEWTOY(killall, "<1?lq", TOYFLAG_USR|TOYFLAG_BIN))
-
-config KILLALL
-	bool "killall"
-	default y
-	help
-	  usage: killall [-l] [-q] [-SIG] PROCESS_NAME...
-
-	  Send a signal (default: TERM) to all processes with the given names.
-
-		-l	print list of all available signals
-		-q	don't print any warnings or error messages
-*/
-
-#include "toys.h"
-
-#define FLAG_q	1
-#define FLAG_l	2
-
-DEFINE_GLOBALS(
-	int signum;
-)
-#define TT this.killall
-
-static void kill_process(pid_t pid)
-{
-	int ret;
-
-	toys.exitval = 0;
-	ret = kill(pid, TT.signum);
-
-	if (ret == -1 && !(toys.optflags & FLAG_q)) perror("kill");
-}
-
-void killall_main(void)
-{
-	char **names;
-
-	if (toys.optflags & FLAG_l) {
-		sig_to_num(NULL);
-		return;
-	}
-
-	TT.signum = SIGTERM;
-	toys.exitval++;
-
-	if (!*toys.optargs) {
-		toys.exithelp = 1;
-		error_exit("Process name missing!");
-	}
-
-	names = toys.optargs;
-
-	if (**names == '-') {
-		if (0 > (TT.signum = sig_to_num((*names)+1))) {
-			if (toys.optflags & FLAG_q) exit(1);
-			error_exit("Invalid signal");
-		}
-		names++;
-
-		if (!*names) {
-			toys.exithelp++;
-			error_exit("Process name missing!");
-		}
-	}
-
-	for_each_pid_with_name_in(names, kill_process);
-
-	if (toys.exitval && !(toys.optflags & FLAG_q))
-		error_exit("No such process");
-}
--- a/toys/link.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * link.c - hardlink a file
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/link.html
-
-USE_LINK(NEWTOY(link, "<2>2", TOYFLAG_USR|TOYFLAG_BIN))
-
-config LINK
-	bool "link"
-	default y
-	help
-	  usage: link FILE NEWLINK
-
-	  Create hardlink to a file.
-*/
-
-#include "toys.h"
-
-void link_main(void)
-{
-	if (link(toys.optargs[0], toys.optargs[1]))
-		perror_exit("couldn't link '%s' to '%s'", toys.optargs[1],
-			toys.optargs[0]);
-}
--- a/toys/ln.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * ln.c - Create filesystem links
- *
- * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
- *
- * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ln.html
-
-USE_LN(NEWTOY(ln, "<1nfs", TOYFLAG_BIN))
-
-config LN
-	bool "ln"
-	default y
-	help
-	  usage: ln [-sf] [FROM...] TO
-
-	  Create a link between FROM and TO.
-	  With only one argument, create link in current directory.
-
-	  -s	Create a symbolic link
-	  -f	Force the creation of the link, even if TO already exists
-          -n	Symlink at destination treated as file
-*/
-
-#include "toys.h"
-
-#define FLAG_s	1
-#define FLAG_f	2
-#define FLAG_n	4
-
-void ln_main(void)
-{
-    char *dest = toys.optargs[--toys.optc], *new;
-    struct stat buf;
-    int i;
-
-    // With one argument, create link in current directory.
-    if (!toys.optc) {
-        toys.optc++;
-        dest=".";
-    }
-
-    // Is destination a directory?
-    if (((toys.optflags&FLAG_n) ? lstat : stat)(dest, &buf)
-        || !S_ISDIR(buf.st_mode))
-    {
-        if (toys.optc>1) error_exit("'%s' not a directory");
-        buf.st_mode = 0;
-    }
-
-    for (i=0; i<toys.optc; i++) {
-        int rc;
-        char *try = toys.optargs[i];
-
-        if (S_ISDIR(buf.st_mode)) {
-            new = strrchr(try, '/');
-            if (!new) new = try;
-            new = xmsprintf("%s/%s", dest, new);
-        } else new = dest;
-        /* Silently unlink the existing target. If it doesn't exist,
-         * then we just move on */
-        if (toys.optflags & FLAG_f) unlink(new);
-
-        rc = (toys.optflags & FLAG_s) ? symlink(try, new) : link(try, new);
-        if (rc)
-            perror_exit("cannot create %s link from '%s' to '%s'",
-                (toys.optflags & FLAG_s) ? "symbolic" : "hard", try, new);
-        if (new != dest) free(new);
-    }
-}
--- a/toys/login.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * login.c - Start a session on the system.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
- * No support for PAM/securetty/selinux/login script/issue/utmp
- * Relies on libcrypt for hash calculation.
-
-USE_LOGIN(NEWTOY(login, ">1fph:", TOYFLAG_BIN))
-
-config LOGIN
-	bool "login"
-	default y
-	help
-	  usage: login [-p] [-h host] [[-f] username]
-
-	  Establish a new session with the system.
-	  -p    Preserve environment
-	  -h    The name of the remote host for this login
-	  -f    Do not perform authentication
-*/
-
-#include "toys.h"
-
-#define LOGIN_TIMEOUT 60
-#define LOGIN_FAIL_TIMEOUT 3
-#define USER_NAME_MAX_SIZE 32
-#define HOSTNAME_SIZE 32
-
-DEFINE_GLOBALS(
-	char *hostname;
-)
-#define TT this.login
-
-static void login_timeout_handler(int sig __attribute__((unused)))
-{
-	printf("\nLogin timed out after %d seconds.\n", LOGIN_TIMEOUT);
-	exit(0);
-}
-
-static char *forbid[] = {
-	"BASH_ENV",
-	"ENV",
-	"HOME",
-	"IFS",
-	"LD_LIBRARY_PATH",
-	"LD_PRELOAD",
-	"LD_TRACE_LOADED_OBJECTS",
-	"LD_BIND_NOW",
-	"LD_AOUT_LIBRARY_PATH",
-	"LD_AOUT_PRELOAD",
-	"LD_NOWARN",
-	"LD_KEEPDIR",
-	"SHELL",
-	NULL
-};
-
-int verify_password(char * pwd)
-{
-	char *pass;
-
-	if (read_password(toybuf, sizeof(toybuf), "Password: ")) return 1;
-	if (!pwd) return 1;
-	if (pwd[0] == '!' || pwd[0] == '*') return 1;
-
-	pass = crypt(toybuf, pwd);
-	if (pass && !strcmp(pass, pwd)) return 0;
-
-	return 1;
-}
-
-void read_user(char * buff, int size)
-{
-	char hostname[HOSTNAME_SIZE+1];
-	int i = 0;
-	hostname[HOSTNAME_SIZE] = 0;
-	if(!gethostname(hostname, HOSTNAME_SIZE)) fputs(hostname, stdout);
-
-	fputs(" login: ", stdout);
-	fflush(stdout);
-
-	do {
-		buff[0] = getchar();
-		if (buff[0] == EOF)
-			exit(EXIT_FAILURE);
-	} while (isblank(buff[0]));
-
-	if (buff[0] != '\n')
-		if(!fgets(&buff[1], HOSTNAME_SIZE-1, stdin))
-			_exit(1);
-
-	while(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) i++;
-	buff[i] = 0;
-}
-
-void handle_nologin(void)
-{
-	int fd = open("/etc/nologin", O_RDONLY);
-	int size;
-	if (fd == -1) return;
-
-	size = readall(fd, toybuf,sizeof(toybuf)-1);
-	toybuf[size] = 0;
-	if (!size) puts("System closed for routine maintenance\n");
-	else puts(toybuf);
-
-	close(fd);
-	fflush(stdout);
-	exit(EXIT_FAILURE);
-}
-
-void handle_motd(void)
-{
-	int fd = open("/etc/motd", O_RDONLY);
-	int size;
-	if (fd == -1) return;
-
-	size = readall(fd, toybuf,sizeof(toybuf)-1);
-	toybuf[size] = 0;
-	puts(toybuf);
-
-	close(fd);
-	fflush(stdout);
-}
-
-int change_identity(const struct passwd *pwd)
-{
-	if (initgroups(pwd->pw_name,pwd->pw_gid)) return 1;
-	if (setgid(pwd->pw_uid)) return 1;
-	if (setuid(pwd->pw_uid)) return 1;
-
-	return 0;
-}
-
-void spawn_shell(const char *shell)
-{
-	const char * exec_name = strrchr(shell,'/');
-	if (exec_name) exec_name++;
-	else exec_name = shell;
-
-	snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell);
-	execl(shell, toybuf, NULL);
-	error_exit("Failed to spawn shell");
-}
-
-void setup_environment(const struct passwd *pwd, int clear_env)
-{
-	if (chdir(pwd->pw_dir)) printf("bad home dir: %s\n", pwd->pw_dir);
-
-	if (clear_env) {
-		const char * term = getenv("TERM");
-		clearenv();
-		if (term) setenv("TERM", term, 1);
-	}
-
-	setenv("USER", pwd->pw_name, 1);
-	setenv("LOGNAME", pwd->pw_name, 1);
-	setenv("HOME", pwd->pw_dir, 1);
-	setenv("SHELL", pwd->pw_shell, 1);
-}
-
-void login_main(void)
-{
-	int f_flag = (toys.optflags & 4) >> 2;
-	int p_flag = (toys.optflags & 2) >> 1;
-	int h_flag = toys.optflags & 1;
-	char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss;
-	struct passwd * pwd = NULL;
-	struct spwd * spwd = NULL;
-	int auth_fail_cnt = 0;
-
-	if (f_flag && toys.optc != 1)
-		error_exit("-f requires username");
-
-	if (geteuid()) error_exit("not root");
-
-	if (!isatty(0) || !isatty(1) || !isatty(2)) error_exit("no tty");
-
-	openlog("login", LOG_PID | LOG_CONS, LOG_AUTH);
-	signal(SIGALRM, login_timeout_handler);
-	alarm(LOGIN_TIMEOUT);
-
-	for (ss = forbid; *ss; ss++) unsetenv(*ss);
-
-	while (1) {
-		tcflush(0, TCIFLUSH);
-
-		username[USER_NAME_MAX_SIZE] = 0;
-		if (toys.optargs[0])
-			strncpy(username, toys.optargs[0], USER_NAME_MAX_SIZE);
-		else {
-			read_user(username, USER_NAME_MAX_SIZE+1);
-			if (username[0] == 0) continue;
-		}
-
-		pwd = getpwnam(username);
-		if (!pwd) goto query_pass; // Non-existing user
-
-		if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*')
-			goto query_pass;  // Locked account
-
-		if (f_flag) break; // Pre-authenticated
-
-		if (!pwd->pw_passwd[0]) break; // Password-less account
-
-		pass = pwd->pw_passwd;
-		if (pwd->pw_passwd[0] == 'x') {
-			spwd = getspnam (username);
-			if (spwd) pass = spwd->sp_pwdp;
-		}
-
-query_pass:
-		if (!verify_password(pass)) break;
-
-		f_flag = 0;
-		syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username,
-			ttyname(0), (h_flag)?"from":"", (h_flag)?TT.hostname:"");
-
-		sleep(LOGIN_FAIL_TIMEOUT);
-		puts("Login incorrect");
-
-		if (++auth_fail_cnt == 3)
-			error_exit("Maximum number of tries exceeded (%d)\n", auth_fail_cnt);
-
-		username[0] = 0;
-		pwd = NULL;
-		spwd = NULL;
-	}
-
-	alarm(0);
-
-	if (pwd->pw_uid) handle_nologin();
-
-	if (change_identity(pwd)) error_exit("Failed to change identity");
-
-	setup_environment(pwd, !p_flag);
-
-	handle_motd();
-
-	syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name,
-		ttyname(0), (h_flag)?"from":"", (h_flag)?TT.hostname:"");
-
-	spawn_shell(pwd->pw_shell);
-}
--- a/toys/logname.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * logname.c - Print user's login name.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/logname.html
-
-USE_LOGNAME(NEWTOY(logname, ">0", TOYFLAG_BIN))
-
-config LOGNAME
-	bool "logname"
-	default y
-	help
-	  usage: logname
-
-	  Prints the calling user's name or an error when this cannot be
-	  determined.
-*/
-
-#include "toys.h"
-
-void logname_main(void)
-{
-	if (getlogin_r(toybuf, sizeof(toybuf))){
-		error_exit("no login name");
-	}
-	xputs(toybuf);
-}
--- a/toys/ls.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,493 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * ls.c - list files
- *
- * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
- * Copyright 2012 Rob Landley <rob@landley.net>
- *
- * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html
-
-// "[-Cl]"
-USE_LS(NEWTOY(ls, "goACFHLRSacdfiklmnpqrstux1", TOYFLAG_BIN))
-
-config LS
-	bool "ls"
-	default y
-	help
-	  usage: ls [-ACFHLRSacdfiklmnpqrstux1] [directory...]
-	  list files
-
-	  what to show:
-	  -a    all files including .hidden
-	  -c	use ctime for timestamps
-	  -d	directory, not contents
-	  -i	inode number
-	  -k	block sizes in kilobytes
-	  -p	put a '/' after directory names
-	  -q	unprintable chars as '?'
-	  -s	size (in blocks)
-	  -u	use access time for timestamps
-	  -A	list all files except . and ..
-	  -H	follow command line symlinks
-	  -L	follow symlinks
-	  -R	recursively list files in subdirectories
-	  -F    append file type indicator (/=dir, *=exe, @=symlink, |=FIFO)
-
-	  output formats:
-	  -1    list one file per line
-	  -C	columns (sorted vertically)
-	  -g	like -l but no owner
-	  -l	long (show full details for each file)
-	  -m	comma separated
-	  -n	like -l but numeric uid/gid
-	  -o	like -l but no group
-	  -x	columns (sorted horizontally)
-
-	  sorting (default is alphabetical):
-	  -f	unsorted
-	  -r	reverse
-	  -t	timestamp
-	  -S	size
-*/
-
-#include "toys.h"
-
-#define FLAG_1 (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_u (1<<2)
-#define FLAG_t (1<<3)
-#define FLAG_s (1<<4)
-#define FLAG_r (1<<5)
-#define FLAG_q (1<<6)
-#define FLAG_p (1<<7)
-#define FLAG_n (1<<8)
-#define FLAG_m (1<<9)
-#define FLAG_l (1<<10)
-#define FLAG_k (1<<11)
-#define FLAG_i (1<<12)
-#define FLAG_f (1<<13)
-#define FLAG_d (1<<14)
-#define FLAG_c (1<<15)
-#define FLAG_a (1<<16)
-#define FLAG_S (1<<17)
-#define FLAG_R (1<<18)
-#define FLAG_L (1<<19)
-#define FLAG_H (1<<20)
-#define FLAG_F (1<<21)
-#define FLAG_C (1<<22)
-#define FLAG_A (1<<23)
-#define FLAG_o (1<<24)
-#define FLAG_g (1<<25)
-
-// test sst output (suid/sticky in ls flaglist)
-
-// ls -lR starts .: then ./subdir:
-
-DEFINE_GLOBALS(
-    struct dirtree *files;
-
-    unsigned screen_width;
-    int nl_title;
-
-    // group and user can make overlapping use of the utoa() buf, so move it
-    char uid_buf[12];
-)
-
-#define TT this.ls
-
-void dlist_to_dirtree(struct dirtree *parent)
-{
-    // Turn double_list into dirtree
-    struct dirtree *dt = parent->child;
-    if (dt) {
-        dt->parent->next = NULL;
-        while (dt) {
-            dt->parent = parent;
-            dt = dt->next;
-        }
-    }
-}
-
-static char endtype(struct stat *st)
-{
-    mode_t mode = st->st_mode;
-    if ((toys.optflags&(FLAG_F|FLAG_p)) && S_ISDIR(mode)) return '/';
-    if (toys.optflags & FLAG_F) {
-        if (S_ISLNK(mode)) return '@';
-        if (S_ISREG(mode) && (mode&0111)) return '*';
-        if (S_ISFIFO(mode)) return '|';
-        if (S_ISSOCK(mode)) return '=';
-    }
-    return 0;
-}
-
-static char *getusername(uid_t uid)
-{
-    struct passwd *pw = getpwuid(uid);
-    utoa_to_buf(uid, TT.uid_buf, 12);
-    return pw ? pw->pw_name : TT.uid_buf;
-}
-
-static char *getgroupname(gid_t gid)
-{
-    struct group *gr = getgrgid(gid);
-    return gr ? gr->gr_name : utoa(gid);
-}
-
-// Figure out size of printable entry fields for display indent/wrap
-
-static void entrylen(struct dirtree *dt, unsigned *len)
-{
-    struct stat *st = &(dt->st);
-    unsigned flags = toys.optflags;
-
-    *len = strlen(dt->name);
-    if (endtype(st)) ++*len;
-    if (flags & FLAG_m) ++*len;
-
-    if (flags & FLAG_i) *len += (len[1] = numlen(st->st_ino));
-    if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) {
-        unsigned fn = flags & FLAG_n;
-        len[2] = numlen(st->st_nlink);
-        len[3] = strlen(fn ? utoa(st->st_uid) : getusername(st->st_uid));
-        len[4] = strlen(fn ? utoa(st->st_gid) : getgroupname(st->st_gid));
-        len[5] = numlen(st->st_size);
-    }
-    if (flags & FLAG_s) *len += (len[6] = numlen(st->st_blocks));
-}
-
-static int compare(void *a, void *b)
-{
-    struct dirtree *dta = *(struct dirtree **)a;
-    struct dirtree *dtb = *(struct dirtree **)b;
-    int ret = 0, reverse = (toys.optflags & FLAG_r) ? -1 : 1;
-
-    if (toys.optflags & FLAG_S) {
-        if (dta->st.st_size > dtb->st.st_size) ret = -1;
-        else if (dta->st.st_size < dtb->st.st_size) ret = 1;
-    }
-    if (toys.optflags & FLAG_t) {
-        if (dta->st.st_mtime > dtb->st.st_mtime) ret = -1;
-        else if (dta->st.st_mtime < dtb->st.st_mtime) ret = 1;
-    }
-    if (!ret) ret = strcmp(dta->name, dtb->name);
-    return ret * reverse;
-}
-
-// callback from dirtree_recurse() determining how to handle this entry.
-
-static int filter(struct dirtree *new)
-{
-    int flags = toys.optflags;
-
-    // Special case to handle enormous dirs without running out of memory.
-    if (flags == (FLAG_1|FLAG_f)) {
-        xprintf("%s\n", new->name);
-        return 0;
-    }
-
-    if (!(flags&FLAG_f)) { 
-        if (flags & FLAG_a) return 0;
-        if (!(flags & FLAG_A) && new->name[0]=='.') return 0;
-    }
-
-    if (flags & FLAG_u) new->st.st_mtime = new->st.st_atime;
-    if (flags & FLAG_c) new->st.st_mtime = new->st.st_ctime;
-    if (flags & FLAG_k) new->st.st_blocks = (new->st.st_blocks + 1) / 2;
-    return dirtree_notdotdot(new);
-}
-
-// For column view, calculate horizontal position (for padding) and return
-// index of next entry to display.
-
-static unsigned long next_column(unsigned long ul, unsigned long dtlen,
-    unsigned columns, unsigned *xpos)
-{
-    unsigned long transition;
-    unsigned height, widecols;
-
-    // Horizontal sort is easy
-    if (!(toys.optflags & FLAG_C)) {
-        *xpos = ul % columns;
-        return ul;
-    }
-
-    // vertical sort
-
-    // For -x, calculate height of display, rounded up
-    height = (dtlen+columns-1)/columns;
-
-    // Sanity check: does wrapping render this column count impossible
-    // due to the right edge wrapping eating a whole row?
-    if (height*columns - dtlen >= height) {
-        *xpos = columns;
-        return 0;
-    }
-
-    // Uneven rounding goes along right edge
-    widecols = dtlen % height;
-    if (!widecols) widecols = height;
-    transition = widecols * columns;
-    if (ul < transition) {
-        *xpos =  ul % columns;
-        return (*xpos*height) + (ul/columns);
-    }
-
-    ul -= transition;
-    *xpos = ul % (columns-1);
-
-    return (*xpos*height) + widecols + (ul/(columns-1));
-}
-
-// Display a list of dirtree entries, according to current format
-// Output types -1, -l, -C, or stream
-
-static void listfiles(int dirfd, struct dirtree *indir)
-{
-    struct dirtree *dt, **sort = 0;
-    unsigned long dtlen = 0, ul = 0;
-    unsigned width, flags = toys.optflags, totals[7], len[7],
-        *colsizes = (unsigned *)(toybuf+260), columns = (sizeof(toybuf)-260)/4;
-    
-    memset(totals, 0, sizeof(totals));
-
-    // Silently descend into single directory listed by itself on command line.
-    // In this case only show dirname/total header when given -R.
-    if (!indir->parent) {
-        if (!(dt = indir->child)) return;
-        if (S_ISDIR(dt->st.st_mode) && !dt->next && !(flags & FLAG_d)) {
-            dt->extra = 1;
-            listfiles(open(dt->name, 0), dt);
-            return;
-        }
-    } else {
-        // Read directory contents. We dup() the fd because this will close it.
-        indir->data = dup(dirfd);
-        dirtree_recurse(indir, filter, (flags&FLAG_L));
-    }
-
-    // Copy linked list to array and sort it. Directories go in array because
-    // we visit them in sorted order.
-
-    for (;;) {
-        for (dt = indir->child; dt; dt = dt->next) {
-            if (sort) sort[dtlen] = dt;
-            dtlen++;
-        }
-        if (sort) break;
-        sort = xmalloc(dtlen * sizeof(void *));
-        dtlen = 0;
-        continue;
-    }
-
-    // Label directory if not top of tree, or if -R
-    if (indir->parent && (!indir->extra || (flags & FLAG_R)))
-    {
-        char *path = dirtree_path(indir, 0);
-
-        if (TT.nl_title++) xputc('\n');
-        xprintf("%s:\n", path);
-        free(path);
-    }
-
-    if (!(flags & FLAG_f)) qsort(sort, dtlen, sizeof(void *), (void *)compare);
-
-    // Find largest entry in each field for display alignment
-    if (flags & (FLAG_C|FLAG_x)) {
-
-        // columns can't be more than toybuf can hold, or more than files,
-        // or > 1/2 screen width (one char filename, one space).
-        if (columns > TT.screen_width/2) columns = TT.screen_width/2;
-        if (columns > dtlen) columns = dtlen;
-
-        // Try to fit as many columns as we can, dropping down by one each time
-        for (;columns > 1; columns--) {
-            unsigned c, totlen = columns;
-
-            memset(colsizes, 0, columns*sizeof(unsigned));
-            for (ul=0; ul<dtlen; ul++) {
-                entrylen(sort[next_column(ul, dtlen, columns, &c)], len);
-                if (c == columns) break;
-                // Does this put us over budget?
-                if (*len > colsizes[c]) {
-                    totlen += *len-colsizes[c];
-                    colsizes[c] = *len;
-                    if (totlen > TT.screen_width) break;
-                }
-            }
-            // If it fit, stop here
-            if (ul == dtlen) break;
-        }
-    } else if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g|FLAG_s)) {
-        unsigned long blocks = 0;
-
-        for (ul = 0; ul<dtlen; ul++)
-        {
-            entrylen(sort[ul], len);
-            for (width=0; width<6; width++)
-                if (len[width] > totals[width]) totals[width] = len[width];
-            blocks += sort[ul]->st.st_blocks;
-        }
-
-        if (indir->parent) xprintf("total %lu\n", blocks);
-    }
-
-    // Loop through again to produce output.
-    memset(toybuf, ' ', 256);
-    width = 0;
-    for (ul = 0; ul<dtlen; ul++) {
-        unsigned curcol;
-        unsigned long next = next_column(ul, dtlen, columns, &curcol);
-        struct stat *st = &(sort[next]->st);
-        mode_t mode = st->st_mode;
-        char et = endtype(st);
-
-        // Skip directories at the top of the tree when -d isn't set
-        if (S_ISDIR(mode) && !indir->parent && !(flags & FLAG_d)) continue;
-        TT.nl_title=1;
-
-        // Handle padding and wrapping for display purposes
-        entrylen(sort[next], len);
-        if (ul) {
-            if (flags & FLAG_m) xputc(',');
-            if (flags & (FLAG_C|FLAG_x)) {
-                if (!curcol) xputc('\n');
-            } else if ((flags & FLAG_1) || width+1+*len > TT.screen_width) {
-                xputc('\n');
-                width = 0;
-            } else {
-                xputc(' ');
-                width++;
-            }
-        }
-        width += *len;
-
-        if (flags & FLAG_i)
-            xprintf("% *lu ", len[1], (unsigned long)st->st_ino);
-        if (flags & FLAG_s)
-            xprintf("% *lu ", len[6], (unsigned long)st->st_blocks);
-
-        if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) {
-            struct tm *tm;
-            char perm[11], thyme[64], c, d, *usr, *upad, *grp, *grpad;
-            int i, bit;
-
-            perm[10]=0;
-            for (i=0; i<9; i++) {
-                bit = mode & (1<<i);
-                c = i%3;
-                if (!c && (mode & (1<<((d=i/3)+9)))) {
-                    c = "tss"[d];
-                    if (!bit) c &= ~0x20;
-                } else c = bit ? "xwr"[c] : '-';
-                perm[9-i] = c;
-            }
-
-            if (S_ISDIR(mode)) c = 'd';
-            else if (S_ISBLK(mode)) c = 'b';
-            else if (S_ISCHR(mode)) c = 'c';
-            else if (S_ISLNK(mode)) c = 'l';
-            else if (S_ISFIFO(mode)) c = 'p';
-            else if (S_ISSOCK(mode)) c = 's';
-            else c = '-';
-            *perm = c;
-
-            tm = localtime(&(st->st_mtime));
-            strftime(thyme, sizeof(thyme), "%F %H:%M", tm);
-
-            if (flags&FLAG_o) grp = grpad = toybuf+256;
-            else {
-                grp = (flags&FLAG_n) ? utoa(st->st_gid)
-                      : getgroupname(st->st_gid);
-                grpad = toybuf+256-(totals[4]-len[4]);
-            }
-
-            if (flags&FLAG_g) usr = upad = toybuf+256;
-            else {
-                upad = toybuf+255-(totals[3]-len[3]);
-                if (flags&FLAG_n) {
-                    usr = TT.uid_buf;
-                    utoa_to_buf(st->st_uid, TT.uid_buf, 12);
-                } else usr = getusername(st->st_uid);
-            }
-
-            // Coerce the st types into something we know we can print.
-            xprintf("%s% *ld %s%s%s%s% *"PRId64" %s ", perm, totals[2]+1,
-                (long)st->st_nlink, usr, upad, grp, grpad, totals[5]+1,
-                (int64_t)st->st_size, thyme);
-        }
-
-        if (flags & FLAG_q) {
-            char *p;
-            for (p=sort[next]->name; *p; p++) xputc(isprint(*p) ? *p : '?');
-        } else xprintf("%s", sort[next]->name);
-        if ((flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) && S_ISLNK(mode))
-            xprintf(" -> %s", sort[next]->symlink);
-
-        if (et) xputc(et);
-
-        // Pad columns
-        if (flags & (FLAG_C|FLAG_x)) {
-            curcol = colsizes[curcol] - *len;
-            if (curcol >= 0) xprintf("%s", toybuf+255-curcol);
-        }
-    }
-
-    if (width) xputc('\n');
-
-    // Free directory entries, recursing first if necessary.
-
-    for (ul = 0; ul<dtlen; free(sort[ul++])) {
-        if ((flags & FLAG_d) || !S_ISDIR(sort[ul]->st.st_mode)
-            || !dirtree_notdotdot(sort[ul])) continue;
-
-        // Recurse into dirs if at top of the tree or given -R
-        if (!indir->parent || (flags & FLAG_R))
-            listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]);
-    }
-    free(sort);
-    if (dirfd != AT_FDCWD) close(indir->data);
-}
-
-void ls_main(void)
-{
-    char **s, *noargs[] = {".", 0};
-    struct dirtree *dt;
-
-    // Do we have an implied -1
-    if (!isatty(1) || (toys.optflags&(FLAG_l|FLAG_o|FLAG_n|FLAG_g)))
-        toys.optflags |= FLAG_1;
-    else {
-        TT.screen_width = 80;
-        terminal_size(&TT.screen_width, NULL);
-    }
-    // The optflags parsing infrastructure should really do this for us,
-    // but currently it has "switch off when this is set", so "-dR" and "-Rd"
-    // behave differently
-    if (toys.optflags & FLAG_d) toys.optflags &= ~FLAG_R;
-
-    // Iterate through command line arguments, collecting directories and files.
-    // Non-absolute paths are relative to current directory.
-    TT.files = dirtree_add_node(0, 0, 0);
-    for (s = *toys.optargs ? toys.optargs : noargs; *s; s++) {
-        dt = dirtree_add_node(AT_FDCWD, *s,
-            (toys.optflags & (FLAG_L|FLAG_H|FLAG_l))^FLAG_l);
-
-        if (!dt) {
-            toys.exitval = 1;
-            continue;
-        }
-
-        // Typecast means double_list->prev temporarirly goes in dirtree->parent
-        dlist_add_nomalloc((struct double_list **)&TT.files->child,
-                           (struct double_list *)dt);
-    }
-
-    // Turn double_list into dirtree
-    dlist_to_dirtree(TT.files);
-
-    // Display the files we collected
-    listfiles(AT_FDCWD, TT.files);
-
-    if (CFG_TOYBOX_FREE) free(TT.files);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/lsb/dmesg.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,59 @@
+/* vi: set sw=4 ts=4:
+ *
+ * dmesg.c - display/control kernel ring buffer.
+ *
+ * Copyright 2006, 2007 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3.
+
+USE_DMESG(NEWTOY(dmesg, "s#n#c", TOYFLAG_BIN))
+
+config DMESG
+	bool "dmesg"
+	default y
+	help
+	  usage: dmesg [-n level] [-s bufsize] | -c
+
+	  Print or control the kernel ring buffer.
+
+	  -n	Set kernel logging level (1-9).
+	  -s	Size of buffer to read (in bytes), default 16384.
+	  -c	Clear the ring buffer after printing.
+*/
+
+#include "toys.h"
+#include <sys/klog.h>
+
+DEFINE_GLOBALS(
+	long level;
+	long size;
+)
+
+#define TT this.dmesg
+
+void dmesg_main(void)
+{
+	// For -n just tell kernel to which messages to keep.
+	if (toys.optflags & 2) {
+		if (klogctl(8, NULL, TT.level))
+			error_exit("klogctl");
+	} else {
+		int size, i, last = '\n';
+		char *data;
+
+		// Figure out how much data we need, and fetch it.
+		size = TT.size;
+		if (size<2) size = 16384;
+		data = xmalloc(size);
+		size = klogctl(3 + (toys.optflags&1), data, size);
+		if (size < 0) error_exit("klogctl");
+
+		// Display data, filtering out level markers.
+		for (i=0; i<size; ) {
+			if (last=='\n' && data[i]=='<') i += 3;
+			else xputc(last = data[i++]);
+		}
+		if (last!='\n') xputc('\n');
+		if (CFG_TOYBOX_FREE) free(data);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/lsb/hostname.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,33 @@
+/* vi: set sw=4 ts=4:
+ *
+ * hostname.c - Get/Set the hostname
+ *
+ * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
+ *
+ * Not in SUSv4.
+
+USE_HOSTNAME(NEWTOY(hostname, NULL, TOYFLAG_BIN))
+
+config HOSTNAME
+	bool "hostname"
+	default n
+	help
+	  usage: hostname [newname]
+
+	  Get/Set the current hostname
+*/
+
+#include "toys.h"
+
+void hostname_main(void)
+{
+	const char *hostname = toys.optargs[0];
+        if (hostname) {
+            if (sethostname(hostname, strlen(hostname)))
+                perror_exit("cannot set hostname to '%s'", hostname);
+        } else {
+            if (gethostname(toybuf, sizeof(toybuf)))
+                perror_exit("cannot get hostname");
+            xputs(toybuf);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/lsb/killall.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,79 @@
+/* vi: set sw=4 ts=4:
+ *
+ * killall.c - Send signal (default: TERM) to all processes with given names.
+ *
+ * Copyright 2012 Andreas Heck <aheck@gmx.de>
+ *
+ * Not in SUSv4.
+
+USE_KILLALL(NEWTOY(killall, "<1?lq", TOYFLAG_USR|TOYFLAG_BIN))
+
+config KILLALL
+	bool "killall"
+	default y
+	help
+	  usage: killall [-l] [-q] [-SIG] PROCESS_NAME...
+
+	  Send a signal (default: TERM) to all processes with the given names.
+
+		-l	print list of all available signals
+		-q	don't print any warnings or error messages
+*/
+
+#include "toys.h"
+
+#define FLAG_q	1
+#define FLAG_l	2
+
+DEFINE_GLOBALS(
+	int signum;
+)
+#define TT this.killall
+
+static void kill_process(pid_t pid)
+{
+	int ret;
+
+	toys.exitval = 0;
+	ret = kill(pid, TT.signum);
+
+	if (ret == -1 && !(toys.optflags & FLAG_q)) perror("kill");
+}
+
+void killall_main(void)
+{
+	char **names;
+
+	if (toys.optflags & FLAG_l) {
+		sig_to_num(NULL);
+		return;
+	}
+
+	TT.signum = SIGTERM;
+	toys.exitval++;
+
+	if (!*toys.optargs) {
+		toys.exithelp = 1;
+		error_exit("Process name missing!");
+	}
+
+	names = toys.optargs;
+
+	if (**names == '-') {
+		if (0 > (TT.signum = sig_to_num((*names)+1))) {
+			if (toys.optflags & FLAG_q) exit(1);
+			error_exit("Invalid signal");
+		}
+		names++;
+
+		if (!*names) {
+			toys.exithelp++;
+			error_exit("Process name missing!");
+		}
+	}
+
+	for_each_pid_with_name_in(names, kill_process);
+
+	if (toys.exitval && !(toys.optflags & FLAG_q))
+		error_exit("No such process");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/lsb/mknod.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,51 @@
+/* vi: set sw=4 ts=4:
+ *
+ * mknod.c - make block or character special file
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv3.
+
+USE_MKNOD(NEWTOY(mknod, "<2>4", TOYFLAG_BIN))
+
+config MKNOD
+	bool "mknod"
+	default y
+	help
+	  usage: mknod NAME TYPE [MAJOR MINOR]
+
+	  Create a special file NAME with a given type, possible types are
+	  b       create a block device with the given MAJOR/MINOR
+	  c or u  create a character device with the given MAJOR/MINOR
+	  p       create a named pipe ignoring MAJOR/MINOR
+*/
+
+#include "toys.h"
+
+static const char modes_char[] = {'p', 'c', 'u', 'b'};
+static const mode_t modes[] = {S_IFIFO, S_IFCHR, S_IFCHR, S_IFBLK};
+
+void mknod_main(void)
+{
+	int major=0, minor=0, type;
+	char * tmp;
+	int mode = 0660;
+
+	tmp = strchr(modes_char, toys.optargs[1][0]);
+	if (!tmp)
+		perror_exit("unknown special device type %c", toys.optargs[1][0]);
+
+	type = modes[tmp-modes_char];
+
+	if (type == S_IFCHR || type == S_IFBLK) {
+                if (toys.optc != 4)
+                    perror_exit("creating a block/char device requires major/minor");
+
+		major = atoi(toys.optargs[2]);
+		minor = atoi(toys.optargs[3]);
+	}
+
+	if (mknod(toys.optargs[0], mode | type, makedev(major, minor)))
+		perror_exit("mknod %s failed", toys.optargs[0]);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/lsb/mktemp.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,54 @@
+/* vi: set sw=4 ts=4:
+ *
+ * mktemp.c - Create a temporary file or directory.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_MKTEMP(NEWTOY(mktemp, ">1(directory)d(tmpdir)p:", TOYFLAG_BIN))
+
+config MKTEMP
+	bool "mktemp"
+	default y
+	help
+	  usage: mktemp [OPTION] [TEMPLATE]
+
+	  Safely create a temporary file or directory and print its name.
+	  TEMPLATE should end in 6 consecutive X's, the default
+	  template is tmp.XXXXXX and the default directory is /tmp/.
+	  
+	  -d, --directory        Create a directory, instead of a file
+	  -p DIR, --tmpdir=DIR   Use DIR as a base path
+
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	char * tmpdir;
+)
+#define TT this.mktemp
+
+void mktemp_main(void)
+{
+	int  d_flag = toys.optflags & 2;
+	char *tmp, *path;
+
+	tmp = *toys.optargs;
+	if (!tmp) tmp = "tmp.XXXXXX";
+	if (!TT.tmpdir) TT.tmpdir = "/tmp/";
+
+	tmp = xmsprintf("%s/%s", TT.tmpdir, tmp);
+
+	if (d_flag ? mkdtemp(tmp) == NULL : mkstemp(tmp) == -1)
+		perror_exit("Failed to create temporary %s",
+			d_flag ? "directory" : "file");
+
+	xputs(path = xrealpath(tmp));
+
+	if (CFG_TOYBOX_FREE) {
+		free(path);
+		free(tmp);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/lsb/passwd.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,274 @@
+/* vi: set sw=4 ts=4:
+ *
+ * passwd.c - Program to upadte user password.
+ *
+ * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com>
+ * Modified 2012 Jason Kyungwan Han <asura321@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
+
+config PASSWD
+	bool "passwd"
+	default y
+	help
+	  usage: passwd [-a ALGO] [-d] [-l] [-u] <account name>
+
+	  update user’s authentication tokens. Default : current user
+
+	  -a ALGO	Encryption method (des, md5, sha256, sha512) default: des
+	  -d		Set password to ''
+	  -l		Lock (disable) account
+	  -u 		Unlock (enable) account
+
+*/
+
+#include "toys.h"
+#include <time.h>
+
+
+DEFINE_GLOBALS(
+	char *algo;
+)
+
+#define TT this.passwd
+
+#define FLAG_u	(1 << 0)
+#define FLAG_l	(1 << 1)
+#define FLAG_d	(1 << 2)
+#define FLAG_a	(1 << 3)
+
+#define MAX_SALT_LEN  20 //3 for id, 16 for key, 1 for '\0'
+#define URANDOM_PATH    "/dev/urandom"
+
+#ifndef _GNU_SOURCE
+char *strcasestr(const char *haystack, const char *needle);
+#endif
+
+unsigned int random_number_generator(int fd)
+{
+    unsigned int randnum;
+    xreadall(fd, &randnum, sizeof(randnum));
+	return randnum;
+}
+
+
+
+char inttoc(int i)
+{
+	// salt value uses 64 chracters in "./0-9a-zA-Z"
+	const char character_set[]="./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    i &= 0x3f; // masking for using 10 bits only
+	return character_set[i];
+}
+
+int get_salt(char *salt)
+{                     
+	int i, salt_length = 0;
+    int randfd;
+	if(!strncmp(TT.algo,"des",3)){
+		// 2 bytes salt value is used in des
+		salt_length = 2;
+	} else {
+		*salt++ = '$';
+		if(!strncmp(TT.algo,"md5",3)){
+			*salt++ = '1';
+			// 8 bytes salt value is used in md5
+			salt_length = 8;
+		} else if(!strncmp(TT.algo,"sha256",6)){
+			*salt++ = '5';
+			// 16 bytes salt value is used in sha256
+			salt_length = 16;
+		} else if(!strncmp(TT.algo,"sha512",6)){
+			*salt++ = '6';
+			// 16 bytes salt value is used in sha512
+			salt_length = 16;
+		} else return 1;
+
+		*salt++ = '$';
+	}
+
+    randfd = xopen(URANDOM_PATH, O_RDONLY);
+	for(i=0; i<salt_length; i++)
+		salt[i] = inttoc(random_number_generator(randfd));
+	salt[salt_length+1] = '\0';
+    xclose(randfd);
+
+	return 0;
+}
+
+static int str_check(char *s, char *p)
+{
+    if((strcasestr(s, p) != NULL) || (strcasestr(p, s) != NULL))
+        return 1;
+    return 0;
+}
+
+static void strength_check(char *newp, char *oldp, char *user)
+{
+    char *msg = NULL;
+    if(strlen(newp) < 6) { //Min passwd len
+        msg = "too short";
+        xprintf("BAD PASSWORD: %s\n",msg);
+    }
+    if(!newp[0])
+        return; //passwd is empty
+
+    if(str_check(newp, user)) {
+        msg = "user based password";
+        xprintf("BAD PASSWORD: %s\n",msg);
+    }
+
+    if(oldp[0] && str_check(newp, oldp)) {
+        msg = "based on old passwd";
+        xprintf("BAD PASSWORD: %s\n",msg);
+    }
+}
+
+static int verify_passwd(char * pwd)
+{    
+    char * pass;
+
+    if (!pwd) return 1;
+    if (pwd[0] == '!' || pwd[0] == '*') return 1;
+
+    pass = crypt(toybuf, pwd);
+    if (pass != NULL && strcmp(pass, pwd)==0)
+        return 0;
+
+    return 1;
+}
+
+static char *new_password(char *oldp, char *user)
+{
+    char *newp = NULL;
+
+    if(read_password(toybuf, sizeof(toybuf), "New password:"))
+        return NULL; //may be due to Ctrl-C
+
+    newp = xstrdup(toybuf);
+    strength_check(newp, oldp, user);
+    if(read_password(toybuf, sizeof(toybuf), "Retype password:")) {
+        free(newp);
+        return NULL; //may be due to Ctrl-C
+    }
+
+    if(strcmp(newp, toybuf) == 0)
+        return newp;
+    else error_msg("Passwords do not match.\n");
+    /*Failure Case */
+    free(newp);
+    return NULL;
+}
+
+
+void passwd_main(void)
+{
+    uid_t myuid;
+    struct passwd *pw;
+    struct spwd *sp;
+    char *name = NULL;
+    char *pass = NULL, *encrypted = NULL, *newp = NULL;
+    char *orig = (char *)"";
+    char salt[MAX_SALT_LEN];
+    int ret = -1;
+
+    myuid = getuid();
+    if((myuid != 0) && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d)))
+        error_exit("You need to be root to do these actions\n");
+
+    pw = getpwuid(myuid);
+
+    if(!pw)
+        error_exit("Unknown uid '%u'",myuid);
+
+    if(toys.optargs[0])
+        name = toys.optargs[0];
+    else
+        name = xstrdup(pw->pw_name);
+
+    pw = getpwnam(name);
+    if(!pw) error_exit("Unknown user '%s'",name);
+
+    if(myuid != 0 && (myuid != pw->pw_uid))
+        error_exit("You need to be root to change '%s' password\n", name);
+
+    pass = pw->pw_passwd;
+    if(pw->pw_passwd[0] == 'x') {
+        /*get shadow passwd */
+        sp = getspnam(name);
+        if(sp)
+            pass = sp->sp_pwdp;
+    }
+
+
+    if(!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) {
+        printf("Changing password for %s\n",name);
+        if(pass[0] == '!') 
+            error_exit("Can't change, password is locked for %s",name);
+        if(myuid != 0) {
+            /*Validate user */
+
+            if(read_password(toybuf, sizeof(toybuf), "Origial password:")) {
+                if(!toys.optargs[0]) free(name);
+                return;
+            }
+            orig = toybuf;
+            if(verify_passwd(pass))
+                error_exit("Authentication failed\n");
+        }
+
+        orig = xstrdup(orig);
+
+        /*Get new password */
+        newp = new_password(orig, name);
+        if(!newp) {
+            free(orig);
+            if(!toys.optargs[0]) free(name);
+            return; //new password is not set well.
+        }
+
+        /*Encrypt the passwd */
+        if(!(toys.optflags & FLAG_a)) TT.algo = "des";
+
+		if(get_salt(salt))
+			error_exit("Error: Unkown encryption algorithm\n");
+		
+        encrypted = crypt(newp, salt);
+        free(newp);
+        free(orig);
+    }
+    else if(toys.optflags & FLAG_l) {
+        if(pass[0] == '!')
+            error_exit("password is already locked for %s",name);
+        printf("Locking password for %s\n",name);
+        encrypted = xmsprintf("!%s",pass);
+    }
+    else if(toys.optflags & FLAG_u) {
+        if(pass[0] != '!')         
+            error_exit("password is already unlocked for %s",name);
+
+        printf("Unlocking password for %s\n",name);
+        encrypted = xstrdup(&pass[1]);
+    }
+    else if(toys.optflags & FLAG_d) {
+        printf("Deleting password for %s\n",name);
+        encrypted = (char*)xzalloc(sizeof(char)*2); //1 = "", 2 = '\0'
+    }
+
+    /*Update the passwd */
+    if(pw->pw_passwd[0] == 'x')
+        ret = update_password("/etc/shadow", name, encrypted);
+    else
+        ret = update_password("/etc/passwd", name, encrypted);
+
+    if((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) 
+        free(encrypted);
+
+    if(!toys.optargs[0]) free(name);
+    if(!ret)
+        error_msg("Success");
+    else
+        error_msg("Failure");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/lsb/pidof.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4:
+ *
+ * pidof.c - Print the PIDs of all processes with the given names.
+ *
+ * Copyright 2012 Andreas Heck <aheck@gmx.de>
+ *
+ * Not in SUSv4.
+
+USE_PIDOF(NEWTOY(pidof, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+
+config PIDOF
+	bool "pidof"
+	default y
+	help
+	  usage: pidof [NAME]...
+
+	  Print the PIDs of all processes with the given names.
+*/
+
+#include "toys.h"
+
+static void print_pid(pid_t pid) {
+    xprintf("%s%ld", toys.exitval ? "" : " ", (long)pid);
+    toys.exitval = 0;
+}
+
+void pidof_main(void)
+{
+    toys.exitval = 1;
+    for_each_pid_with_name_in(toys.optargs, print_pid);
+    if (!toys.exitval) xputc('\n');
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/lsb/seq.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,48 @@
+/* vi: set sw=4 ts=4:
+ *
+ * seq.c - Count from first to last, by increment.
+ *
+ * Copyright 2006 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3.  (Don't ask me why not.)
+
+USE_SEQ(NEWTOY(seq, "<1>3?", TOYFLAG_USR|TOYFLAG_BIN))
+
+config SEQ
+	bool "seq"
+	depends on TOYBOX_FLOAT
+	default y
+	help
+	  usage: seq [first] [increment] last
+
+	  Count from first to last, by increment.  Omitted arguments default
+	  to 1.  Two arguments are used as first and last.  Arguments can be
+	  negative or floating point.
+*/
+
+#include "toys.h"
+
+void seq_main(void)
+{
+	double first, increment, last, dd;
+
+	// Parse command line arguments, with appropriate defaults.
+	// Note that any non-numeric arguments are treated as zero.
+	first = increment = 1;
+	switch (toys.optc) {
+		case 3:
+			increment = atof(toys.optargs[1]);
+		case 2:
+			first = atof(*toys.optargs);
+		default:
+			last = atof(toys.optargs[toys.optc-1]);
+	}
+
+	// Yes, we're looping on a double.  Yes rounding errors can accumulate if
+	// you use a non-integer increment.  Deal with it.
+	for (dd=first; (increment>0 && dd<=last) || (increment <0 && dd>=last);
+		dd+=increment)
+	{
+		printf("%g\n", dd);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/lsb/sync.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,25 @@
+/* vi: set sw=4 ts=4:
+ *
+ * sync.c - Write all pending data to disk.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3.
+
+USE_SYNC(NEWTOY(sync, NULL, TOYFLAG_BIN))
+
+config SYNC
+	bool "sync"
+	default y
+	help
+	  usage: sync
+
+	  Write pending cached data to disk (synchronize), blocking until done.
+*/
+
+#include "toys.h"
+
+void sync_main(void)
+{
+	sync();
+}
--- a/toys/lsmod.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * lsmod.c - Show the status of modules in the kernel
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
-
-USE_LSMOD(NEWTOY(lsmod, NULL, TOYFLAG_BIN))
-
-config LSMOD
-	bool "lsmod"
-	default y
-	help
-	  usage: lsmod
-
-	  Display the currently loaded modules, their sizes and their
-	  dependencies.
-*/
-
-#include "toys.h"
-
-void lsmod_main(void)
-{
-	char *modfile = "/proc/modules";
-	FILE * file = xfopen(modfile, "r");
-
-	xprintf("%-23s Size  Used by\n", "Module");
-
-	while (fgets(toybuf, sizeof(toybuf), file)) {
-		char *name = strtok(toybuf, " "), *size = strtok(NULL, " "),
-			*refcnt = strtok(NULL, " "), *users = strtok(NULL, " ");
-
-		if(users) {
-			int len = strlen(users)-1;
-			if (users[len] == ',' || users[len] == '-')
-				users[len] = 0;
-			xprintf("%-19s %8s  %s %s\n", name, size, refcnt, users);
-		} else perror_exit("bad %s", modfile);
-	}
-	fclose(file);
-}
--- a/toys/mdev.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/* vi:set ts=4:
- *
- * mdev - Mini udev for busybox
- *
- * Copyright 2005, 2008 Rob Landley <rob@landley.net>
- * Copyright 2005 Frank Sorenson <frank@tuxrocks.com>
- *
- * Not in SUSv3.
-
-USE_MDEV(NEWTOY(mdev, "s", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
-
-config MDEV
-	bool "mdev"
-	default n
-	help
-	  usage: mdev [-s]
-
-	  Create devices in /dev using information from /sys.
-
-	  -s	Scan all entries in /sys to populate /dev.
-
-config MDEV_CONF
-	bool "Configuration file for mdev"
-	default y
-	depends on MDEV
-	help
-	  The mdev config file (/etc/mdev.conf) contains lines that look like:
-		hd[a-z][0-9]* 0:3 660
-
-	  Each line must contain three whitespace separated fields.  The first
-	  field is a regular expression matching one or more device names, and
-	  the second and third fields are uid:gid and file permissions for
-	  matching devies.
-*/
-
-#include "toys.h"
-#include "lib/xregcomp.h"
-
-// todo, open() block devices to trigger partition scanning.
-
-// mknod in /dev based on a path like "/sys/block/hda/hda1"
-static void make_device(char *path)
-{
-	char *device_name, *s, *temp;
-	int major, minor, type, len, fd;
-	int mode = 0660;
-	uid_t uid = 0;
-	gid_t gid = 0;
-
-	// Try to read major/minor string
-
-	temp = strrchr(path, '/');
-	fd = open(path, O_RDONLY);
-	*temp=0;
-	temp = toybuf;
-	len = read(fd, temp, 64);
-	close(fd);
-	if (len<1) return;
-	temp[len] = 0;
-
-	// Determine device name, type, major and minor
-
-	device_name = strrchr(path, '/') + 1;
-	type = path[5]=='c' ? S_IFCHR : S_IFBLK;
-	major = minor = 0;
-	sscanf(temp, "%u:%u", &major, &minor);
-
-	// If we have a config file, look up permissions for this device
-
-	if (CFG_MDEV_CONF) {
-		char *conf, *pos, *end;
-
-		// mmap the config file
-		if (-1!=(fd = open("/etc/mdev.conf", O_RDONLY))) {
-			len = fdlength(fd);
-			conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
-			if (conf) {
-				int line = 0;
-
-				// Loop through lines in mmaped file
-				for (pos = conf; pos-conf<len;) {
-					int field;
-					char *end2;
-
-					line++;
-					// find end of this line
-					for(end = pos; end-conf<len && *end!='\n'; end++);
-
-					// Three fields: regex, uid:gid, mode
-					for (field = 3; field; field--) {
-						// Skip whitespace
-						while (pos<end && isspace(*pos)) pos++;
-						if (pos==end || *pos=='#') break;
-						for (end2 = pos;
-							end2<end && !isspace(*end2) && *end2!='#'; end2++);
-						switch(field) {
-							// Regex to match this device
-							case 3:
-							{
-								char *regex = strndup(pos, end2-pos);
-								regex_t match;
-								regmatch_t off;
-								int result;
-
-								// Is this it?
-								xregcomp(&match, regex, REG_EXTENDED);
-								result=regexec(&match, device_name, 1, &off, 0);
-								regfree(&match);
-								free(regex);
-
-								// If not this device, skip rest of line
-								if (result || off.rm_so
-									|| off.rm_eo!=strlen(device_name))
-										goto end_line;
-
-								break;
-							}
-							// uid:gid
-							case 2:
-							{
-								char *s2;
-
-								// Find :
-								for(s = pos; s<end2 && *s!=':'; s++);
-								if (s==end2) goto end_line;
-
-								// Parse UID
-								uid = strtoul(pos,&s2,10);
-								if (s!=s2) {
-									struct passwd *pass;
-									char *str = strndup(pos, s-pos);
-									pass = getpwnam(str);
-									free(str);
-									if (!pass) goto end_line;
-									uid = pass->pw_uid;
-								}
-								s++;
-								// parse GID
-								gid = strtoul(s,&s2,10);
-								if (end2!=s2) {
-									struct group *grp;
-									char *str = strndup(s, end2-s);
-									grp = getgrnam(str);
-									free(str);
-									if (!grp) goto end_line;
-									gid = grp->gr_gid;
-								}
-								break;
-							}
-							// mode
-							case 1:
-							{
-								mode = strtoul(pos, &pos, 8);
-								if (pos!=end2) goto end_line;
-								goto found_device;
-							}
-						}
-						pos=end2;
-					}
-end_line:
-					// Did everything parse happily?
-					if (field && field!=3) error_exit("Bad line %d", line);
-
-					// Next line
-					pos = ++end;
-				}
-found_device:
-				munmap(conf, len);
-			}
-			close(fd);
-		}
-	}
-
-	sprintf(temp, "/dev/%s", device_name);
-	if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST)
-		perror_exit("mknod %s failed", temp);
-
-	if (CFG_MDEV_CONF) mode=chown(temp, uid, gid);
-}
-
-static int callback(struct dirtree *node)
-{
-	// Entries in /sys/class/block aren't char devices, so skip 'em.  (We'll
-	// get block devices out of /sys/block.)
-	if(!strcmp(node->name, "block")) return 0;
-
-	// Does this directory have a "dev" entry in it?
-	// This is path based because the hotplug callbacks are
-	if (S_ISDIR(node->st.st_mode) || S_ISLNK(node->st.st_mode)) {
-		int len=4;
-		char *dev = dirtree_path(node, &len);
-		strcpy(dev+len, "/dev");
-		if (!access(dev, R_OK)) make_device(dev);
-		free(dev);
-	}
-
-	// Circa 2.6.25 the entries more than 2 deep are all either redundant
-	// (mouse#, event#) or unnamed (every usb_* entry is called "device").
-
-	return (node->parent && node->parent->parent) ? 0 : DIRTREE_RECURSE;
-}
-
-void mdev_main(void)
-{
-	// Handle -s
-
-	if (toys.optflags) {
-		dirtree_read("/sys/class", callback);
-		dirtree_read("/sys/block", callback);
-	}
-
-	// hotplug support goes here
-}
--- a/toys/mkdir.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * mkdir.c - Make directories
- *
- * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
- *
- * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/mkdir.html
- *
- * TODO: Add -m
-
-USE_MKDIR(NEWTOY(mkdir, "<1p", TOYFLAG_BIN))
-
-config MKDIR
-	bool "mkdir"
-	default y
-	help
-	  usage: mkdir [-p] [dirname...]
-	  Create one or more directories.
-
-	  -p	make parent directories as needed.
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	long mode;
-)
-
-#define TT this.mkdir
-
-static int do_mkdir(char *dir)
-{
-	struct stat buf;
-	char *s;
-
-	// mkdir -p one/two/three is not an error if the path already exists,
-	// but is if "three" is a file.  The others we dereference and catch
-	// not-a-directory along the way, but the last one we must explicitly
-	// test for. Might as well do it up front.
-
-	if (!stat(dir, &buf) && !S_ISDIR(buf.st_mode)) {
-		errno = EEXIST;
-		return 1;
-	}
-
-	for (s=dir; ; s++) {
-		char save=0;
-
-		// Skip leading / of absolute paths.
-		if (s!=dir && *s == '/' && toys.optflags) {
-			save = *s;
-			*s = 0;
-		} else if (*s) continue;
-
-		if (mkdir(dir, TT.mode)<0 && (!toys.optflags || errno != EEXIST))
-			return 1;
-
-		if (!(*s = save)) break;
-	}
-
-	return 0;
-}
-
-void mkdir_main(void)
-{
-	char **s;
-
-	TT.mode = 0777;
-
-	for (s=toys.optargs; *s; s++) {
-		if (do_mkdir(*s)) {
-			perror_msg("cannot create directory '%s'", *s);
-			toys.exitval = 1;
-		}
-	}
-}
--- a/toys/mke2fs.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,662 +0,0 @@
-/* vi: set ts=4:
- *
- * mke2fs.c - Create an ext2 filesystem image.
- *
- * Copyright 2006, 2007 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3.
-
-// Still to go: "E:jJ:L:m:O:"
-USE_MKE2FS(NEWTOY(mke2fs, "<1>2g:Fnqm#N#i#b#", TOYFLAG_SBIN))
-
-config MKE2FS
-	bool "mke2fs (unfinished and broken by dirtree changes)"
-	default n
-	help
-	  usage: mke2fs [-Fnq] [-b ###] [-N|i ###] [-m ###] device
-
-	  Create an ext2 filesystem on a block device or filesystem image.
-
-	  -F         Force to run on a mounted device
-	  -n         Don't write to device
-	  -q         Quiet (no output)
-	  -b size    Block size (1024, 2048, or 4096)
-	  -N inodes  Allocate this many inodes
-	  -i bytes   Allocate one inode for every XXX bytes of device
-	  -m percent Reserve this percent of filesystem space for root user
-
-config MKE2FS_JOURNAL
-	bool "Journaling support (ext3)"
-	default n
-	depends on MKE2FS
-	help
-	  usage: [-j] [-J size=###,device=XXX]
-
-	  -j         Create journal (ext3)
-	  -J         Journal options
-	             size: Number of blocks (1024-102400)
-	             device: Specify an external journal
-
-config MKE2FS_GEN
-	bool "Generate (gene2fs)"
-	default n
-	depends on MKE2FS
-	help
-	  usage: gene2fs [options] device filename
-
-	  The [options] are the same as mke2fs.
-
-config MKE2FS_LABEL
-	bool "Label support"
-	default n
-	depends on MKE2FS
-	help
-	  usage: mke2fs [-L label] [-M path] [-o string]
-
-	  -L         Volume label
-	  -M         Path to mount point
-	  -o         Created by
-
-config MKE2FS_EXTENDED
-	bool "Extended options"
-	default n
-	depends on MKE2FS
-	help
-	  usage: mke2fs [-E stride=###] [-O option[,option]]
-
-	  -E stride= Set RAID stripe size (in blocks)
-	  -O [opts]  Specify fewer ext2 option flags (for old kernels)
-	             All of these are on by default (as appropriate)
-	     none         Clear default options (all but journaling)
-	     dir_index    Use htree indexes for large directories
-	     filetype     Store file type info in directory entry
-	     has_journal  Set by -j
-	     journal_dev  Set by -J device=XXX
-	     sparse_super Don't allocate huge numbers of redundant superblocks
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	// Command line arguments.
-	long blocksize;
-	long bytes_per_inode;
-	long inodes;           // Total inodes in filesystem.
-	long reserved_percent; // Integer precent of space to reserve for root.
-	char *gendir;          // Where to read dirtree from.
-
-	// Internal data.
-	struct dirtree *dt;    // Tree of files to copy into the new filesystem.
-	unsigned treeblocks;   // Blocks used by dt
-	unsigned treeinodes;   // Inodes used by dt
-
-	unsigned blocks;       // Total blocks in the filesystem.
-	unsigned freeblocks;   // Free blocks in the filesystem.
-	unsigned inodespg;     // Inodes per group
-	unsigned groups;       // Total number of block groups.
-	unsigned blockbits;    // Bits per block.  (Also blocks per group.)
-
-	// For gene2fs
-	unsigned nextblock;    // Next data block to allocate
-	unsigned nextgroup;    // Next group we'll be allocating from
-	int fsfd;              // File descriptor of filesystem (to output to).
-
-	struct ext2_superblock sb;
-)
-
-// Shortcut to our global data structure, since we use it so much.
-#define TT this.mke2fs
-
-#define INODES_RESERVED 10
-
-static uint32_t div_round_up(uint32_t a, uint32_t b)
-{
-	uint32_t c = a/b;
-
-	if (a%b) c++;
-	return c;
-}
-
-// Calculate data blocks plus index blocks needed to hold a file.
-
-static uint32_t file_blocks_used(uint64_t size, uint32_t *blocklist)
-{
-	uint32_t dblocks = (uint32_t)((size+(TT.blocksize-1))/TT.blocksize);
-	uint32_t idx=TT.blocksize/4, iblocks=0, diblocks=0, tiblocks=0;
-
-	// Fill out index blocks in inode.
-
-	if (blocklist) {
-		int i;
-
-		// Direct index blocks
-		for (i=0; i<13 && i<dblocks; i++) blocklist[i] = i;
-		// Singly indirect index blocks
-		if (dblocks > 13+idx) blocklist[13] = 13+idx;
-		// Doubly indirect index blocks
-		idx = 13 + idx + (idx*idx);
-		if (dblocks > idx) blocklist[14] = idx;
-
-		return 0;
-	}
-
-	// Account for direct, singly, doubly, and triply indirect index blocks
-
-	if (dblocks > 12) {
-		iblocks = ((dblocks-13)/idx)+1;
-		if (iblocks > 1) {
-			diblocks = ((iblocks-2)/idx)+1;
-			if (diblocks > 1)
-				tiblocks = ((diblocks-2)/idx)+1;
-		}
-	}
-
-	return dblocks + iblocks + diblocks + tiblocks;
-}
-
-// Use the parent pointer to iterate through the tree non-recursively.
-static struct dirtree *treenext(struct dirtree *this)
-{
-	while (this && !this->next) this = this->parent;
-	if (this) this = this->next;
-
-	return this;
-}
-
-// Recursively calculate the number of blocks used by each inode in the tree.
-// Returns blocks used by this directory, assigns bytes used to *size.
-// Writes total block count to TT.treeblocks and inode count to TT.treeinodes.
-
-static long check_treesize(struct dirtree *that, off_t *size)
-{
-	long blocks;
-
-	while (that) {
-		*size += sizeof(struct ext2_dentry) + strlen(that->name);
-
-		if (that->child)
-			that->st.st_blocks = check_treesize(that->child, &that->st.st_size);
-		else if (S_ISREG(that->st.st_mode)) {
-			 that->st.st_blocks = file_blocks_used(that->st.st_size, 0);
-			 TT.treeblocks += that->st.st_blocks;
-		}
-		that = that->next;
-	}
-	TT.treeblocks += blocks = file_blocks_used(*size, 0);
-	TT.treeinodes++;
-
-	return blocks;
-}
-
-// Calculate inode numbers and link counts.
-// 
-// To do this right I need to copy the tree and sort it, but here's a really
-// ugly n^2 way of dealing with the problem that doesn't scale well to large
-// numbers of files (> 100,000) but can be done in very little code.
-// This rewrites inode numbers to their final values, allocating depth first.
-
-static void check_treelinks(struct dirtree *tree)
-{
-	struct dirtree *current=tree, *that;
-	long inode = INODES_RESERVED;
-
-	while (current) {
-		++inode;
-		// Since we can't hardlink to directories, we know their link count.
-		if (S_ISDIR(current->st.st_mode)) current->st.st_nlink = 2;
-		else {
-			dev_t new = current->st.st_dev;
-
-			if (!new) continue;
-
-			// Look for other copies of current node
-			current->st.st_nlink = 0;
-			for (that = tree; that; that = treenext(that)) {
-				if (current->st.st_ino == that->st.st_ino &&
-					current->st.st_dev == that->st.st_dev)
-				{
-					current->st.st_nlink++;
-					current->st.st_ino = inode;
-				}
-			}
-		}
-		current->st.st_ino = inode;
-		current = treenext(current);
-	}
-}
-
-// According to http://www.opengroup.org/onlinepubs/9629399/apdxa.htm
-// we should generate a uuid structure by reading a clock with 100 nanosecond
-// precision, normalizing it to the start of the gregorian calendar in 1582,
-// and looking up our eth0 mac address.
-//
-// On the other hand, we have 128 bits to come up with a unique identifier, of
-// which 6 have a defined value.  /dev/urandom it is.
-
-static void create_uuid(char *uuid)
-{
-	// Read 128 random bits
-	int fd = xopen("/dev/urandom", O_RDONLY);
-	xreadall(fd, uuid, 16);
-	close(fd);
-
-	// Claim to be a DCE format UUID.
-	uuid[6] = (uuid[6] & 0x0F) | 0x40;
-	uuid[8] = (uuid[8] & 0x3F) | 0x80;
-
-    // rfc2518 section 6.4.1 suggests if we're not using a macaddr, we should
-	// set bit 1 of the node ID, which is the mac multicast bit.  This means we
-	// should never collide with anybody actually using a macaddr.
-	uuid[11] = uuid[11] | 128;
-}
-
-// Calculate inodes per group from total inodes.
-static uint32_t get_inodespg(uint32_t inodes)
-{
-	uint32_t temp;
-
-	// Round up to fill complete inode blocks.
-	temp = (inodes + TT.groups - 1) / TT.groups;
-	inodes = TT.blocksize/sizeof(struct ext2_inode);
-	return ((temp + inodes - 1)/inodes)*inodes;
-}
-
-// Fill out superblock and TT structures.
-
-static void init_superblock(struct ext2_superblock *sb)
-{
-	uint32_t temp;
-
-	// Set log_block_size and log_frag_size.
-
-	for (temp = 0; temp < 4; temp++) if (TT.blocksize == 1024<<temp) break;
-	if (temp==4) error_exit("bad blocksize");
-	sb->log_block_size = sb->log_frag_size = SWAP_LE32(temp);
-
-	// Fill out blocks_count, r_blocks_count, first_data_block
-
-	sb->blocks_count = SWAP_LE32(TT.blocks);
-	sb->free_blocks_count = SWAP_LE32(TT.freeblocks);
-	temp = (TT.blocks * (uint64_t)TT.reserved_percent) / 100;
-	sb->r_blocks_count = SWAP_LE32(temp);
-
-	sb->first_data_block = SWAP_LE32(TT.blocksize == 1024 ? 1 : 0);
-
-	// Set blocks_per_group and frags_per_group, which is the size of an
-	// allocation bitmap that fits in one block (I.E. how many bits per block)?
-
-	sb->blocks_per_group = sb->frags_per_group = SWAP_LE32(TT.blockbits);
-
-	// Set inodes_per_group and total inodes_count
-	sb->inodes_per_group = SWAP_LE32(TT.inodespg);
-	sb->inodes_count = SWAP_LE32(TT.inodespg * TT.groups);
-
-	// Determine free inodes.
-	temp = TT.inodespg*TT.groups - INODES_RESERVED;
-	if (temp < TT.treeinodes) error_exit("Not enough inodes.\n");
-	sb->free_inodes_count = SWAP_LE32(temp - TT.treeinodes);
-
-	// Fill out the rest of the superblock.
-	sb->max_mnt_count=0xFFFF;
-	sb->wtime = sb->lastcheck = sb->mkfs_time = SWAP_LE32(time(NULL));
-	sb->magic = SWAP_LE32(0xEF53);
-	sb->state = sb->errors = SWAP_LE16(1);
-
-	sb->rev_level = SWAP_LE32(1);
-	sb->first_ino = SWAP_LE32(INODES_RESERVED+1);
-	sb->inode_size = SWAP_LE16(sizeof(struct ext2_inode));
-	sb->feature_incompat = SWAP_LE32(EXT2_FEATURE_INCOMPAT_FILETYPE);
-	sb->feature_ro_compat = SWAP_LE32(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER);
-
-	create_uuid(sb->uuid);
-	
-	// TODO If we're called as mke3fs or mkfs.ext3, do a journal.
-
-	//if (strchr(toys.which->name,'3'))
-	//	sb->feature_compat |= SWAP_LE32(EXT3_FEATURE_COMPAT_HAS_JOURNAL);
-}
-
-// Does this group contain a superblock backup (and group descriptor table)?
-static int is_sb_group(uint32_t group)
-{
-	int i;
-
-	// Superblock backups are on groups 0, 1, and powers of 3, 5, and 7.
-	if(!group || group==1) return 1;
-	for (i=3; i<9; i+=2) {
-		int j = i;
-		while (j<group) j*=i;
-		if (j==group) return 1;
-	}
-	return 0;
-}
-
-	
-// Number of blocks used in group by optional superblock/group list backup.
-static int group_superblock_overhead(uint32_t group)
-{
-	int used;
-
-	if (!is_sb_group(group)) return 0;
-
-	// How many blocks does the group descriptor table take up?
-	used = TT.groups * sizeof(struct ext2_group);
-	used += TT.blocksize - 1;
-	used /= TT.blocksize;
-	// Plus the superblock itself.
-	used++;
-	// And a corner case.
-	if (!group && TT.blocksize == 1024) used++;
-
-	return used;
-}
-
-// Number of blocks used in group to store superblock/group/inode list
-static int group_overhead(uint32_t group)
-{
-	// Return superblock backup overhead (if any), plus block/inode
-	// allocation bitmaps, plus inode tables.
-	return group_superblock_overhead(group) + 2 + get_inodespg(TT.inodespg)
-				/ (TT.blocksize/sizeof(struct ext2_inode));
-}
-
-// In bitmap "array" set "len" bits starting at position "start" (from 0).
-static void bits_set(char *array, int start, int len)
-{
-	while(len) {
-		if ((start&7) || len<8) {
-			array[start/8]|=(1<<(start&7));
-			start++;
-			len--;
-		} else {
-			array[start/8]=255;
-			start+=8;
-			len-=8;
-		}
-	}
-}
-
-// Seek past len bytes (to maintain sparse file), or write zeroes if output
-// not seekable
-static void put_zeroes(int len)
-{
-	if(-1 == lseek(TT.fsfd, len, SEEK_SET)) {
-		memset(toybuf, 0, sizeof(toybuf));
-		while (len) {
-			int out = len > sizeof(toybuf) ? sizeof(toybuf) : len;
-			xwrite(TT.fsfd, toybuf, out);
-			len -= out;
-		}
-	}
-}
-
-// Fill out an inode structure from struct stat info in dirtree.
-static void fill_inode(struct ext2_inode *in, struct dirtree *that)
-{
-	uint32_t fbu[15];
-	int temp;
-
-	file_blocks_used(that->st.st_size, fbu);
-
-	// If that inode needs data blocks allocated to it.
-	if (that->st.st_size) {
-		int i, group = TT.nextblock/TT.blockbits;
-
-		// TODO: teach this about indirect blocks.
-		for (i=0; i<15; i++) {
-			// If we just jumped into a new group, skip group overhead blocks.
-			while (group >= TT.nextgroup)
-				TT.nextblock += group_overhead(TT.nextgroup++);
-		}
-	}
-	// TODO :  S_ISREG/DIR/CHR/BLK/FIFO/LNK/SOCK(m)
-	in->mode = SWAP_LE32(that->st.st_mode);
-
-	in->uid = SWAP_LE16(that->st.st_uid & 0xFFFF);
-	in->uid_high = SWAP_LE16(that->st.st_uid >> 16);
-	in->gid = SWAP_LE16(that->st.st_gid & 0xFFFF);
-	in->gid_high = SWAP_LE16(that->st.st_gid >> 16);
-	in->size = SWAP_LE32(that->st.st_size & 0xFFFFFFFF);
-
-	// Contortions to make the compiler not generate a warning for x>>32
-	// when x is 32 bits.  The optimizer should clean this up.
-	if (sizeof(that->st.st_size) > 4) temp = 32;
-	else temp = 0;
-	if (temp) in->dir_acl = SWAP_LE32(that->st.st_size >> temp);
-	
-	in->atime = SWAP_LE32(that->st.st_atime);
-	in->ctime = SWAP_LE32(that->st.st_ctime);
-	in->mtime = SWAP_LE32(that->st.st_mtime);
-
-	in->links_count = SWAP_LE16(that->st.st_nlink);
-	in->blocks = SWAP_LE32(that->st.st_blocks);
-	// in->faddr
-}
-
-// Works like an archiver.
-// The first argument is the name of the file to create.  If it already
-// exists, that size will be used.
-
-void mke2fs_main(void)
-{
-	int i, temp;
-	off_t length;
-	uint32_t usedblocks, usedinodes, dtiblk, dtbblk;
-	struct dirtree *dti, *dtb;
-
-	// Handle command line arguments.
-
-	if (toys.optargs[1]) {
-		sscanf(toys.optargs[1], "%u", &TT.blocks);
-		temp = O_RDWR|O_CREAT;
-	} else temp = O_RDWR;
-	if (!TT.reserved_percent) TT.reserved_percent = 5;
-
-	// TODO: Check if filesystem is mounted here
-
-	// For mke?fs, open file.  For gene?fs, create file.
-	TT.fsfd = xcreate(*toys.optargs, temp, 0777);
-	
-	// Determine appropriate block size and block count from file length.
-	// (If no length, default to 4k.  They can override it on the cmdline.)
-
-	length = fdlength(TT.fsfd);
-	if (!TT.blocksize) TT.blocksize = (length && length < 1<<29) ? 1024 : 4096;
-	TT.blockbits = 8*TT.blocksize;
-	if (!TT.blocks) TT.blocks = length/TT.blocksize;
-
-	// Collect gene2fs list or lost+found, calculate requirements.
-
-	if (TT.gendir) {
-		strncpy(toybuf, TT.gendir, sizeof(toybuf));
-		dti = dirtree_read(toybuf, NULL, NULL);
-	} else {
-		dti = xzalloc(sizeof(struct dirtree)+11);
-		strcpy(dti->name, "lost+found");
-		dti->st.st_mode = S_IFDIR|0755;
-		dti->st.st_ctime = dti->st.st_mtime = time(NULL);
-	}
-
-	// Add root directory inode.  This is iterated through for when finding
-	// blocks, but not when finding inodes.  The tree's parent pointers don't
-	// point back into this.
-
-	dtb = xzalloc(sizeof(struct dirtree)+1);
-	dtb->st.st_mode = S_IFDIR|0755;
-	dtb->st.st_ctime = dtb->st.st_mtime = time(NULL);
-	dtb->child = dti;
-	
-	// Figure out how much space is used by preset files
-	length = check_treesize(dtb, &(dtb->st.st_size));
-	check_treelinks(dtb);
-
-	// Figure out how many total inodes we need.
-
-	if (!TT.inodes) {
-		if (!TT.bytes_per_inode) TT.bytes_per_inode = 8192;
-		TT.inodes = (TT.blocks * (uint64_t)TT.blocksize) / TT.bytes_per_inode;
-	}
-
-	// If we're generating a filesystem and have no idea how many blocks it
-	// needs, start with a minimal guess, find the overhead of that many
-	// groups, and loop until this is enough groups to store this many blocks.
-	if (!TT.blocks) TT.groups = (TT.treeblocks/TT.blockbits)+1;
-	else TT.groups = div_round_up(TT.blocks, TT.blockbits);
-
-	for (;;) {
-		temp = TT.treeblocks;
-
-		for (i = 0; i<TT.groups; i++) temp += group_overhead(i);
-
-		if (TT.blocks) {
-			if (TT.blocks < temp) error_exit("Not enough space.\n");
-			break;
-		}
-		if (temp <= TT.groups * TT.blockbits) {
-			TT.blocks = temp;
-			break;
-		}
-		TT.groups++;
-	}
-	TT.freeblocks = TT.blocks - temp;
-
-	// Now we know all the TT data, initialize superblock structure.
-
-	init_superblock(&TT.sb);
-
-	// Start writing.  Skip the first 1k to avoid the boot sector (if any).
-	put_zeroes(1024);
-
-	// Loop through block groups, write out each one.
-	dtiblk = dtbblk = usedblocks = usedinodes = 0;
-	for (i=0; i<TT.groups; i++) {
-		struct ext2_inode *in = (struct ext2_inode *)toybuf;
-		uint32_t start, itable, used, end;
-		int j, slot;
-
-		// Where does this group end?
-		end = TT.blockbits;
-		if ((i+1)*TT.blockbits > TT.blocks) end = TT.blocks & (TT.blockbits-1);
-
-		// Blocks used by inode table
-		itable = (TT.inodespg*sizeof(struct ext2_inode))/TT.blocksize;
-
-		// If a superblock goes here, write it out.
-		start = group_superblock_overhead(i);
-		if (start) {
-			struct ext2_group *bg = (struct ext2_group *)toybuf;
-			int treeblocks = TT.treeblocks, treeinodes = TT.treeinodes;
-
-			TT.sb.block_group_nr = SWAP_LE16(i);
-
-			// Write superblock and pad it up to block size
-			xwrite(TT.fsfd, &TT.sb, sizeof(struct ext2_superblock));
-			temp = TT.blocksize - sizeof(struct ext2_superblock);
-			if (!i && TT.blocksize > 1024) temp -= 1024;
-			memset(toybuf, 0, TT.blocksize);
-			xwrite(TT.fsfd, toybuf, temp);
-
-			// Loop through groups to write group descriptor table.
-			for(j=0; j<TT.groups; j++) {
-
-				// Figure out what sector this group starts in.
-				used = group_superblock_overhead(j);
-
-				// Find next array slot in this block (flush block if full).
-				slot = j % (TT.blocksize/sizeof(struct ext2_group));
-				if (!slot) {
-					if (j) xwrite(TT.fsfd, bg, TT.blocksize);
-					memset(bg, 0, TT.blocksize);
-				}
-
-				// How many free inodes in this group?
-				temp = TT.inodespg;
-				if (!i) temp -= INODES_RESERVED;
-				if (temp > treeinodes) {
-					treeinodes -= temp;
-					temp = 0;
-				} else {
-					temp -= treeinodes;
-					treeinodes = 0;
-				}
-				bg[slot].free_inodes_count = SWAP_LE16(temp);
-
-				// How many free blocks in this group?
-				temp = TT.inodespg/(TT.blocksize/sizeof(struct ext2_inode)) + 2;
-				temp = end-used-temp;
-				if (temp > treeblocks) {
-					treeblocks -= temp;
-					temp = 0;
-				} else {
-					temp -= treeblocks;
-					treeblocks = 0;
-				}
-				bg[slot].free_blocks_count = SWAP_LE32(temp);
-
-				// Fill out rest of group structure
-				used += j*TT.blockbits;
-				bg[slot].block_bitmap = SWAP_LE32(used++);
-				bg[slot].inode_bitmap = SWAP_LE32(used++);
-				bg[slot].inode_table = SWAP_LE32(used);
-				bg[slot].used_dirs_count = 0;  // (TODO)
-			}
-			xwrite(TT.fsfd, bg, TT.blocksize);
-		}
-
-		// Now write out stuff that every block group has.
-
-		// Write block usage bitmap
-
-		start += 2 + itable;
-		memset(toybuf, 0, TT.blocksize);
-		bits_set(toybuf, 0, start);
-		bits_set(toybuf, end, TT.blockbits-end);
-		temp = TT.treeblocks - usedblocks;
-		if (temp) {
-			if (end-start > temp) temp = end-start;
-			bits_set(toybuf, start, temp);
-		}
-		xwrite(TT.fsfd, toybuf, TT.blocksize);
-
-		// Write inode bitmap
-		memset(toybuf, 0, TT.blocksize);
-		j = 0;
-		if (!i) bits_set(toybuf, 0, j = INODES_RESERVED);
-		bits_set(toybuf, TT.inodespg, slot = TT.blockbits-TT.inodespg);
-		temp = TT.treeinodes - usedinodes;
-		if (temp) {
-			if (slot-j > temp) temp = slot-j;
-			bits_set(toybuf, j, temp);
-		}
-		xwrite(TT.fsfd, toybuf, TT.blocksize);
-
-		// Write inode table for this group (TODO)
-		for (j = 0; j<TT.inodespg; j++) {
-			slot = j % (TT.blocksize/sizeof(struct ext2_inode));
-			if (!slot) {
-				if (j) xwrite(TT.fsfd, in, TT.blocksize);
-				memset(in, 0, TT.blocksize);
-			}
-			if (!i && j<INODES_RESERVED) {
-				// Write root inode
-				if (j == 2) fill_inode(in+slot, dtb);
-			} else if (dti) {
-				fill_inode(in+slot, dti);
-				dti = treenext(dti);
-			}
-		}
-		xwrite(TT.fsfd, in, TT.blocksize);
-
-		while (dtb) {
-			// TODO write index data block
-			// TODO write root directory data block
-			// TODO write directory data block
-			// TODO write file data block
-			put_zeroes(TT.blocksize);
-			start++;
-			if (start == end) break;
-		}
-		// Write data blocks (TODO)
-		put_zeroes((end-start) * TT.blocksize);
-	}
-}
--- a/toys/mkfifo.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * mkfifo.c - Create FIFOs (named pipes)
- *
- * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
- *
- * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/mkfifo.html
- *
- * TODO: Add -m
-
-USE_MKFIFO(NEWTOY(mkfifo, "<1m:", TOYFLAG_BIN))
-
-config MKFIFO
-	bool "mkfifo"
-	default y
-	help
-	  usage: mkfifo [fifo_name...]
-
-	  Create FIFOs (named pipes).
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	char *m_string;
-	mode_t mode;
-)
-
-#define TT this.mkfifo
-#define FLAG_m (1)
-
-void mkfifo_main(void)
-{
-	char **s;
-
-	TT.mode = 0666;
-	if (toys.optflags & FLAG_m) {
-		TT.mode = string_to_mode(TT.m_string, 0);
-	}
-
-	for (s = toys.optargs; *s; s++) {
-		if (mknod(*s, S_IFIFO | TT.mode, 0) < 0) {
-			perror_msg("cannot create fifo '%s'", *s);
-			toys.exitval = 1;
-		}
-	}
-}
--- a/toys/mknod.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * mknod.c - make block or character special file
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv3.
-
-USE_MKNOD(NEWTOY(mknod, "<2>4", TOYFLAG_BIN))
-
-config MKNOD
-	bool "mknod"
-	default y
-	help
-	  usage: mknod NAME TYPE [MAJOR MINOR]
-
-	  Create a special file NAME with a given type, possible types are
-	  b       create a block device with the given MAJOR/MINOR
-	  c or u  create a character device with the given MAJOR/MINOR
-	  p       create a named pipe ignoring MAJOR/MINOR
-*/
-
-#include "toys.h"
-
-static const char modes_char[] = {'p', 'c', 'u', 'b'};
-static const mode_t modes[] = {S_IFIFO, S_IFCHR, S_IFCHR, S_IFBLK};
-
-void mknod_main(void)
-{
-	int major=0, minor=0, type;
-	char * tmp;
-	int mode = 0660;
-
-	tmp = strchr(modes_char, toys.optargs[1][0]);
-	if (!tmp)
-		perror_exit("unknown special device type %c", toys.optargs[1][0]);
-
-	type = modes[tmp-modes_char];
-
-	if (type == S_IFCHR || type == S_IFBLK) {
-                if (toys.optc != 4)
-                    perror_exit("creating a block/char device requires major/minor");
-
-		major = atoi(toys.optargs[2]);
-		minor = atoi(toys.optargs[3]);
-	}
-
-	if (mknod(toys.optargs[0], mode | type, makedev(major, minor)))
-		perror_exit("mknod %s failed", toys.optargs[0]);
-
-}
--- a/toys/mkswap.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * mkswap.c - Format swap device.
- *
- * Copyright 2009 Rob Landley <rob@landley.net>
- *
- * Not in SUSv4.
-
-USE_MKSWAP(NEWTOY(mkswap, "<1>1", TOYFLAG_SBIN))
-
-config MKSWAP
-	bool "mkswap"
-	default y
-	help
-	  usage: mkswap DEVICE
-
-	  Sets up a Linux swap area on a device or file.
-*/
-
-#include "toys.h"
-
-void mkswap_main(void)
-{
-	int fd = xopen(*toys.optargs, O_RDWR), pagesize = sysconf(_SC_PAGE_SIZE);
-	off_t len = fdlength(fd);
-	unsigned int pages = (len/pagesize)-1, *swap = (unsigned int *)toybuf;
-
-	// Write header.  Note that older kernel versions checked signature
-	// on disk (not in cache) during swapon, so sync after writing.
-
-	swap[0] = 1;
-	swap[1] = pages;
-	xlseek(fd, 1024, SEEK_SET);
-	xwrite(fd, swap, 129*sizeof(unsigned int));
-	xlseek(fd, pagesize-10, SEEK_SET);
-	xwrite(fd, "SWAPSPACE2", 10);
-	fsync(fd);
-
-	if (CFG_TOYBOX_FREE) close(fd);
-
-	printf("Swapspace size: %luk\n", pages*(unsigned long)(pagesize/1024));
-}
--- a/toys/mktemp.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * mktemp.c - Create a temporary file or directory.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
-
-USE_MKTEMP(NEWTOY(mktemp, ">1(directory)d(tmpdir)p:", TOYFLAG_BIN))
-
-config MKTEMP
-	bool "mktemp"
-	default y
-	help
-	  usage: mktemp [OPTION] [TEMPLATE]
-
-	  Safely create a temporary file or directory and print its name.
-	  TEMPLATE should end in 6 consecutive X's, the default
-	  template is tmp.XXXXXX and the default directory is /tmp/.
-	  
-	  -d, --directory        Create a directory, instead of a file
-	  -p DIR, --tmpdir=DIR   Use DIR as a base path
-
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	char * tmpdir;
-)
-#define TT this.mktemp
-
-void mktemp_main(void)
-{
-	int  d_flag = toys.optflags & 2;
-	char *tmp, *path;
-
-	tmp = *toys.optargs;
-	if (!tmp) tmp = "tmp.XXXXXX";
-	if (!TT.tmpdir) TT.tmpdir = "/tmp/";
-
-	tmp = xmsprintf("%s/%s", TT.tmpdir, tmp);
-
-	if (d_flag ? mkdtemp(tmp) == NULL : mkstemp(tmp) == -1)
-		perror_exit("Failed to create temporary %s",
-			d_flag ? "directory" : "file");
-
-	xputs(path = xrealpath(tmp));
-
-	if (CFG_TOYBOX_FREE) {
-		free(path);
-		free(tmp);
-	}
-}
--- a/toys/modinfo.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * modinfo.c - Display module info
- *
- * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
- *
-
-USE_MODINFO(NEWTOY(modinfo, "<1F:0", TOYFLAG_BIN))
-
-config MODINFO
-	bool "modinfo"
-	default y
-	help
-	  usage: modinfo [-0] [-F field] [modulename...]
-*/
-
-#include "toys.h"
-
-#define FLAG_0  (1 << 0)
-
-DEFINE_GLOBALS(
-    char *field;
-)
-#define TT this.modinfo
-
-static const char *modinfo_tags[] = {
-    "alias", "license", "description", "author", "vermagic",
-    "srcversion", "intree", "parm", "depends",
-};
-
-static void output_field(const char *field, const char *value)
-{
-    int len;
-
-    if (TT.field && strcmp(TT.field, field) != 0)
-        return;
-
-    len = strlen(field);
-
-    if (TT.field)
-        xprintf("%s", value);
-    else
-        xprintf("%s:%*s%s",
-                field, 15 - len, "", value);
-    if (toys.optflags & FLAG_0)
-        xwrite(fileno(stdout), "\0", 1);
-    else
-        xputs("");
-}
-
-
-static void modinfo_file(struct dirtree *dir)
-{
-    int fd, len, i;
-    char *buf, *pos;
-    char *full_name;
-
-    full_name = dirtree_path(dir, NULL);
-
-    output_field("filename", full_name);
-    fd = xopen(full_name, O_RDONLY);
-    len = fdlength(fd);
-    buf = xmalloc(len);
-    xreadall(fd, buf, len);
-
-    for (pos = buf; pos < buf + len + 10; pos++) {
-        if (*pos)
-            continue;
-
-        for (i = 0; i < sizeof(modinfo_tags) / sizeof(modinfo_tags[0]); i++) {
-            const char *str = modinfo_tags[i];
-            int len = strlen(str); 
-            if (strncmp(pos + 1, str, len) == 0 && pos[len + 1] == '=')
-                output_field(str, &pos[len + 2]);
-        }
-    }
-
-    free(full_name);
-    free(buf);
-    close(fd);
-}
-
-static int check_module(struct dirtree *new)
-{
-    if (S_ISREG(new->st.st_mode)) {
-        char **s;
-        for (s = toys.optargs; *s; s++) {
-            int len = strlen(*s);
-            if (!strncmp(*s, new->name, len) && !strcmp(new->name+len, ".ko"))
-                modinfo_file(new);
-        }
-    }
-
-    return dirtree_notdotdot(new);
-}
-
-void modinfo_main(void)
-{
-    struct utsname uts;
-    if (uname(&uts) < 0) perror_exit("bad uname");
-    sprintf(toybuf, "/lib/modules/%s", uts.release);
-    dirtree_read(toybuf, check_module);
-}
--- a/toys/mountpoint.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * mountpoint.c - Check if a directory is a mountpoint.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
-
-USE_MOUNTPOINT(NEWTOY(mountpoint, "<1qdx", TOYFLAG_BIN))
-
-config MOUNTPOINT
-	bool "mountpoint"
-	default y
-	help
-	  usage: mountpoint [-q] [-d] directory
-			 mountpoint [-q] [-x] device 
-	  -q Be quiet, return zero if directory is a mountpoint
-	  -d Print major/minor device number of the directory
-	  -x Print major/minor device number of the block device
-*/
-
-#include "toys.h"
-
-void mountpoint_main(void)
-{
-	struct stat st1, st2;
-	int res = 0;
-	int quiet = toys.optflags & 0x4;
-	toys.exitval = 1; // be pessimistic
-	strncpy(toybuf, toys.optargs[0], sizeof(toybuf));
-	if (((toys.optflags & 0x1) && lstat(toybuf, &st1)) || stat(toybuf, &st1))
-		perror_exit("%s", toybuf);
-
-	if (toys.optflags & 0x1){
-		if (S_ISBLK(st1.st_mode)) {
-			if (!quiet) printf("%u:%u\n", major(st1.st_rdev), minor(st1.st_rdev));
-			toys.exitval = 0;
-			return;
-		}
-		if (!quiet) printf("%s: not a block device\n", toybuf);
-		return;
-	}
-
-	if(!S_ISDIR(st1.st_mode)){
-		if (!quiet) printf("%s: not a directory\n", toybuf);
-		return;
-	}
-	strncat(toybuf, "/..", sizeof(toybuf));
-	stat(toybuf, &st2);
-	res = (st1.st_dev != st2.st_dev) ||
-		(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
-	if (!quiet) printf("%s is %sa mountpoint\n", toys.optargs[0], res ? "" : "not ");
-	if (toys.optflags & 0x2)
-		printf("%u:%u\n", major(st1.st_dev), minor(st1.st_dev));
-	toys.exitval = res ? 0 : 1;
-}
--- a/toys/netcat.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * nc: mini-netcat - Forward stdin/stdout to a file or network connection.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3.
-
-USE_NETCAT(OLDTOY(nc, netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN))
-USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN))
-
-config NETCAT
-	bool "netcat"
-	default y
-	help
-	  usage: netcat [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|-let} [-e COMMAND]
-
-	  -w	SECONDS timeout for connection
-	  -p	local port number
-	  -s	local ipv4 address
-	  -q	SECONDS quit this many seconds after EOF on stdin.
-	  -f	use FILENAME (ala /dev/ttyS0) instead of network
-
-	  Use "stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho" with
-	  netcat -f to connect to a serial port.
-
-
-config NETCAT_LISTEN
-	bool "netcat sever options (-let)"
-	default y
-	depends on NETCAT
-	help
-	  -t    allocate tty (must come before -l or -L)
-	  -l	listen for one incoming connection.
-	  -L	listen for multiple incoming connections (server mode).
-
-	  Any additional command line arguments after -l or -L are executed
-	  to handle each incoming connection.  If none, the connection is
-	  forwarded to stdin/stdout.
-
-	  For a quick-and-dirty server, try something like:
-		netcat -s 127.0.0.1 -p 1234 -tL /bin/bash -l
-*/
-
-#include "toys.h"
-#include "toynet.h"
-
-DEFINE_GLOBALS(
-	char *filename;        // -f read from filename instead of network
-	long quit_delay;       // -q Exit after EOF from stdin after # seconds.
-	char *source_address;  // -s Bind to a specific source address.
-	long port;             // -p Bind to a specific source port.
-	long wait;             // -w Wait # seconds for a connection.
-)
-
-#define TT this.netcat
-
-#define FLAG_f   1
-#define FLAG_L  32
-#define FLAG_l  64
-#define FLAG_t 128
-
-static void timeout(int signum)
-{
-	if (TT.wait) error_exit("Timeout");
-	exit(0);
-}
-
-static void set_alarm(int seconds)
-{
-	signal(SIGALRM, seconds ? timeout : SIG_DFL);
-	alarm(seconds);
-}
-
-// Translate x.x.x.x numeric IPv4 address, or else DNS lookup an IPv4 name.
-static void lookup_name(char *name, uint32_t *result)
-{
-	struct hostent *hostbyname;
-
-	hostbyname = gethostbyname(name);
-	if (!hostbyname) error_exit("no host '%s'", name);
-	*result = *(uint32_t *)*hostbyname->h_addr_list;
-}
-
-// Worry about a fancy lookup later.
-static void lookup_port(char *str, uint16_t *port)
-{
-  *port = SWAP_BE16(atoi(str));
-}
-
-void netcat_main(void)
-{
-	int sockfd=-1, pollcount=2;
-	struct pollfd pollfds[2];
-
-	memset(pollfds, 0, 2*sizeof(struct pollfd));
-	pollfds[0].events = pollfds[1].events = POLLIN;
-	set_alarm(TT.wait);
-
-	// The argument parsing logic can't make "<2" conditional on other
-	// arguments like -f and -l, so we do it by hand here.
-	if (toys.optflags&FLAG_f) {
-		if (toys.optc) toys.exithelp++;
-	} else if (!(toys.optflags&(FLAG_l|FLAG_L)) && toys.optc!=2) toys.exithelp++;
-
-	if (toys.exithelp) error_exit("Argument count wrong");
-
-	if (TT.filename) pollfds[0].fd = xopen(TT.filename, O_RDWR);
-	else {
-		int temp;
-		struct sockaddr_in address;
-
-		// Setup socket
-		sockfd = socket(AF_INET, SOCK_STREAM, 0);
-		if (-1 == sockfd) perror_exit("socket");
-		fcntl(sockfd, F_SETFD, FD_CLOEXEC);
-		temp = 1;
-		setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(temp));
-		memset(&address, 0, sizeof(address));
-		address.sin_family = AF_INET;
-		if (TT.source_address || TT.port) {
-			address.sin_port = SWAP_BE16(TT.port);
-			if (TT.source_address) 
-				lookup_name(TT.source_address, (uint32_t *)&address.sin_addr);
-			if (bind(sockfd, (struct sockaddr *)&address, sizeof(address)))
-				perror_exit("bind");
-		}
-
-		// Dial out
-
-		if (!CFG_NETCAT_LISTEN || !(toys.optflags&(FLAG_L|FLAG_l))) {
-			// Figure out where to dial out to.
-			lookup_name(*toys.optargs, (uint32_t *)&address.sin_addr);
-			lookup_port(toys.optargs[1], &address.sin_port);
-			temp = connect(sockfd, (struct sockaddr *)&address, sizeof(address));
-			if (temp<0) perror_exit("connect");
-			pollfds[0].fd = sockfd;
-
-		// Listen for incoming connections
-
-		} else {
-			socklen_t len = sizeof(address);
-
-			if (listen(sockfd, 5)) error_exit("listen");
-			if (!TT.port) {
-				getsockname(sockfd, (struct sockaddr *)&address, &len);
-				printf("%d\n", SWAP_BE16(address.sin_port));
-				fflush(stdout);
-			}
-			// Do we need to return immediately because -l has arguments?
-
-			if ((toys.optflags&FLAG_l) && toys.optc) {
-				if (fork()) goto cleanup;
-				close(0);
-				close(1);
-				close(2);
-			}
-
-			for (;;) {
-				pid_t child = 0;
-
-				// For -l, call accept from the _new_ thread.
-
-				pollfds[0].fd = accept(sockfd, (struct sockaddr *)&address,
-					&len);
-				if (pollfds[0].fd<0) perror_exit("accept");
-
-				// Do we need a tty?
-
-				if (toys.optflags&FLAG_t)
-					child = forkpty(&(pollfds[1].fd), NULL, NULL, NULL);
-
-				// Do we need to fork and/or redirect for exec?
-
-				else {
-					if (toys.optflags&FLAG_L) child = fork();
-					if (!child && toys.optc) {
-						int fd = pollfds[0].fd;
-
-						if (!temp) close(sockfd);
-						dup2(fd, 0);
-						dup2(fd, 1);
-						dup2(fd, 2);
-						if (fd>2) close(fd);
-					}
-				}
-
-				if (child<0) error_msg("Fork failed\n");
-				if (child<1) break;
-				close(pollfds[0].fd);
-			}
-		}
-	}
-
-	// We have a connection.  Disarm timeout.
-	// (Does not play well with -L, but what _should_ that do?)
-	set_alarm(0);
-
-	if (CFG_NETCAT_LISTEN && (toys.optflags&(FLAG_L|FLAG_l) && toys.optc)) {
-		execvp(*toys.optargs, toys.optargs);
-		error_exit("Exec failed");
-	}
-
-	// Poll loop copying stdin->socket and socket->stdout.
-	for (;;) {
-		int i;
-
-		if (0>poll(pollfds, pollcount, -1)) perror_exit("poll");
-
-		for (i=0; i<pollcount; i++) {
-			if (pollfds[i].revents & POLLIN) {
-				int len = read(pollfds[i].fd, toybuf, sizeof(toybuf));
-				if (len<1) goto dohupnow;
-				xwrite(i ? pollfds[0].fd : 1, toybuf, len);
-			} else if (pollfds[i].revents & POLLHUP) {
-dohupnow:
-				// Close half-connection.  This is needed for things like
-				// "echo GET / | netcat landley.net 80"
-				if (i) {
-					shutdown(pollfds[0].fd, SHUT_WR);
-					pollcount--;
-					set_alarm(TT.quit_delay);
-				} else goto cleanup;
-			}
-		}
-	}
-cleanup:
-	if (CFG_TOYBOX_FREE) {
-		close(pollfds[0].fd);
-		close(sockfd);
-	}
-}
--- a/toys/nice.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * nice.c - Run a program at a different niceness level.
- *
- * Copyright 2010 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/9699919799/utilities/nice.html
-
-USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_USR|TOYFLAG_BIN))
-
-config NICE
-	bool "nice"
-	default y
-	help
-	  usage: nice [-n PRIORITY] command [args...]
-
-	  Run a command line at an increased or decreased scheduling priority.
-
-	  Higher numbers make a program yield more CPU time, from -20 (highest
-	  priority) to 19 (lowest).  By default processes inherit their parent's
-	  niceness (usually 0).  By default this command adds 10 to the parent's
-	  priority.  Only root can set a negative niceness level.
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	long priority;
-)
-
-#define TT this.nice
-
-void nice_main(void)
-{
-	if (!toys.optflags) TT.priority = 10;
-
-	errno = 0;
-	if (nice(TT.priority)==-1 && errno) perror_exit("Can't set priority");
-
-	xexec(toys.optargs);
-}
--- a/toys/nohup.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * nohup.c - run commandline with SIGHUP blocked.
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/nohup.html
-
-USE_NOHUP(NEWTOY(nohup, "<1", TOYFLAG_USR|TOYFLAG_BIN))
-
-config NOHUP
-	bool "nohup"
-	default y
-	help
-	  usage: nohup COMMAND [ARGS...]
-
-	  Run a command that survives the end of its terminal.
-	  If stdin is a tty, redirect from /dev/null
-	  If stdout is a tty, redirect to file "nohup.out"
-*/
-
-#include "toys.h"
-
-void nohup_main(void)
-{
-	signal(SIGHUP, SIG_IGN);
-	if (isatty(1)) {
-		close(1);
-		if (-1 == open("nohup.out", O_CREAT|O_APPEND|O_WRONLY,
-				S_IRUSR|S_IWUSR ))
-		{
-			char *temp = getenv("HOME");
-			temp = xmsprintf("%s/%s", temp ? temp : "", "nohup.out");
-			xcreate(temp, O_CREAT|O_APPEND|O_WRONLY, S_IRUSR|S_IWUSR);
-		}
-	}
-	if (isatty(0)) {
-		close(0);
-		open("/dev/null", O_RDONLY);
-	}
-	xexec(toys.optargs);
-}
--- a/toys/od.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * od.c - Provide octal/hex dumps of data
- *
- * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
- * Copyright 2012 Rob Landley <rob@landley.net>
- *
- * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/od.html
-
-USE_OD(NEWTOY(od, "j#vN#xsodcbA:t*", TOYFLAG_USR|TOYFLAG_BIN))
-
-config OD
-	bool "od"
-	default y
-	help
-          usage: od [-bdosxv] [-j #] [-N #] [-A doxn] [-t arg]
-
-	  -A	Address base (decimal, octal, hexdecimal, none)
-	  -t	output type(s) a (ascii) c (char) d (decimal) foux
-*/
-
-#include "toys.h"
-
-#define FLAG_t	(1 << 0)
-#define FLAG_A	(1 << 1)
-#define FLAG_b	(1 << 2)
-#define FLAG_c	(1 << 3)
-#define FLAG_d	(1 << 4)
-#define FLAG_o	(1 << 5)
-#define FLAG_s	(1 << 6)
-#define FLAG_x	(1 << 7)
-#define FLAG_N	(1 << 8)
-#define FLAG_v  (1 << 9)
-
-DEFINE_GLOBALS(
-	struct arg_list *output_base;
-	char *address_base;
-	long max_count;
-	long jump_bytes;
-
-	unsigned types, leftover, star, address_idx;
-	char *buf;
-	uint64_t bufs[4]; // force 64-bit alignment
-	off_t pos;
-)
-
-#define TT this.od
-
-static char *ascii = "nulsohstxetxeotenqackbel bs ht nl vt ff cr so si"
-	"dledc1dc2dc3dc4naksynetbcan emsubesc fs gs rs us sp";
-
-struct odtype {
-	int type;
-	int size;
-};
-
-static void od_outline(void)
-{
-	unsigned flags = toys.optflags;
-	char *abases[] = {"", "%07d", "%07o", "%06x"};
-	struct odtype *types = (struct odtype *)toybuf, *t;
-	int i, len;
-
-	if (TT.leftover<16) memset(TT.buf+TT.leftover, 0, 16-TT.leftover);
-
-	// Handle duplciate lines as *
-	if (!(flags&FLAG_v) && TT.jump_bytes != TT.pos && TT.leftover
-		&& !memcmp(TT.bufs, TT.bufs + 2, 16))
-	{
-		if (!TT.star) {
-			xputs("*");
-			TT.star++;
-		}
-
-	// Print line position
-	} else {
-		TT.star = 0;
-
-		xprintf(abases[TT.address_idx], TT.pos);
-		if (!TT.leftover) {
-			if (TT.address_idx) xputc('\n');
-			return;
-		}
-	}
-
-	TT.pos += len = TT.leftover;
-	TT.leftover = 0;
-	if (TT.star) return;
-
-	// For each output type, print one line
-
-	for (i=0; i<TT.types; i++) {
-		int j = 0, pad = i ? 8 : 0;
-		char buf[128];
-
-		t = types+i;
-		while (j<len) {
-			unsigned k;
-			int throw = 0;
-
-			// Handle ascii
-			if (t->type < 2) {
-				char c = TT.buf[j++];
-				pad += 4;
-
-				if (!t->type) {
-					c &= 127;
-					if (c<=32) sprintf(buf, "%.3s", ascii+(3*c));
-					else if (c==127) strcpy(buf, "del");
-					else sprintf(buf, "%c", c);
-				} else {
-					char *bfnrtav = "\b\f\n\r\t\a\v", *s = strchr(bfnrtav, c);
-					if (s) sprintf(buf, "\\%c", "bfnrtav0"[s-bfnrtav]);
-					else if (c < 32 || c >= 127) sprintf(buf, "%03o", c);
-					else {
-						// TODO: this should be UTF8 aware.
-						sprintf(buf, "%c", c);
-					}
-				}
-			} else if (CFG_TOYBOX_FLOAT && t->type == 6) {
-				long double ld;
-				union {float f; double d; long double ld;} fdl;
-
-				memcpy(&fdl, TT.buf+j, t->size);
-				j += t->size;
-				if (sizeof(float) == t->size) {
-					ld = fdl.f;
-					pad += (throw = 8)+7;
-				} else if (sizeof(double) == t->size) {
-					ld = fdl.d;
-					pad += (throw = 17)+8;
-				} else if (sizeof(long double) == t->size) {
-					ld = fdl.ld;
-					pad += (throw = 21)+9;
-				} else error_exit("bad -tf '%d'", t->size);
-
-				sprintf(buf, "%.*Le", throw, ld);
-			// Integer types
-			} else {
-				unsigned long long ll = 0, or;
-				char *c[] = {"%*lld", "%*llu", "%0*llo", "%0*llx"},
-					*class = c[t->type-2];
-
-				// Work out width of field
-				if (t->size == 8) {
-					or = -1LL;
-					if (t->type == 2) or >>= 1;
-				} else or = (1LL<<(8*t->size))-1;
-				throw = sprintf(buf, class, 0, or);
-
-				// Accumulate integer based on size argument
-				for (k=0; k < t->size; k++) {
-					or = TT.buf[j++];
-					ll |= or << (8*(IS_BIG_ENDIAN ? t->size-k-1 : k));
-				}
-
-				// Handle negative values
-				if (t->type == 2) {
-					or = sizeof(or) - t->size;
-					throw++;
-					if (or && (ll & (1l<<((8*t->size)-1))))
-						ll |= ((or<<(8*or))-1) << (8*t->size);
-				}
-
-				sprintf(buf, class, throw, ll);
-				pad += throw+1;
-			}
-			xprintf("%*s", pad, buf);
-			pad = 0;
-		}
-		xputc('\n');
-	}
-
-	// buffer toggle for "same as last time" check.
-	TT.buf = (char *)((TT.buf == (char *)TT.bufs) ? TT.bufs+2 : TT.bufs);
-}
-
-static void do_od(int fd, char *name)
-{
-	// Skip input, possibly more than one entire file.
-	if (TT.jump_bytes < TT.pos) {
-		off_t off = lskip(fd, TT.jump_bytes);
-		if (off > 0) TT.pos += off;
-		if (TT.jump_bytes < TT.pos) return;
-	}
-
-	for(;;) {
-		char *buf = TT.buf + TT.leftover;
-		int len = 16 - TT.leftover;
-
-		if (toys.optflags & FLAG_N) {
-			if (!TT.max_count) break;
-			if (TT.max_count < len) len = TT.max_count;
-		}
-
-		len = readall(fd, buf, len);
-		if (len < 0) {
-			perror_msg("%s", name);
-			break;
-		}
-		if (TT.max_count) TT.max_count -= len;
-		TT.leftover += len;
-		if (TT.leftover < 16) break;
-
-		od_outline();
-	}
-}
-
-static void append_base(char *base)
-{
-	char *s = base;
-	struct odtype *types = (struct odtype *)toybuf;
-	int type;
-
-	for (;;) {
-		int size = 1;
-
-		if (!*s) return;
-		if (TT.types >= sizeof(toybuf)/sizeof(struct odtype)) break;
-		if (-1 == (type = stridx("acduox"USE_TOYBOX_FLOAT("f"), *(s++)))) break;
-
-		if (isdigit(*s)) {
-			size = strtol(s, &s, 10);
-			if (type < 2 && size != 1) break;
-			if (CFG_TOYBOX_FLOAT && type == 6 && size == sizeof(long double));
-			else if (size < 0 || size > 8) break;
-		} else if (CFG_TOYBOX_FLOAT && type == 6) {
-			int sizes[] = {sizeof(float), sizeof(double), sizeof(long double)};
-			if (-1 == (size = stridx("FDL", *s))) size = sizeof(double);
-			else {
-				s++;
-				size = sizes[size];
-			}
-		} else if (type > 1) {
-			if (-1 == (size = stridx("CSIL", *s))) size = 4;
-			else {
-				s++;
-				size = 1 << size;
-			}
-		}
-
-		types[TT.types].type = type;
-		types[TT.types].size = size;
-		TT.types++;
-	}
-
-	error_exit("bad -t %s", base);
-}
-
-void od_main(void)
-{
-	struct arg_list *arg;
-
-	TT.buf = (char *)TT.bufs;
-
-	if (!TT.address_base) TT.address_idx = 2;
-	else if (0>(TT.address_idx = stridx("ndox", *TT.address_base)))
-		error_exit("bad -A '%c'", *TT.address_base);
-
-	// Collect -t entries
-
-	for (arg = TT.output_base; arg; arg = arg->next) append_base(arg->arg);
-	if (toys.optflags & FLAG_b) append_base("o1");
-	if (toys.optflags & FLAG_d) append_base("u2");
-	if (toys.optflags & FLAG_o) append_base("o2");
-	if (toys.optflags & FLAG_s) append_base("d2");
-	if (toys.optflags & FLAG_x) append_base("x2");
-	if (!TT.output_base) append_base("o2");
-
-	loopfiles(toys.optargs, do_od);
-
-	if (TT.leftover) od_outline();
-	od_outline();
-}
--- a/toys/oneit.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * oneit.c, tiny one-process init replacement.
- *
- * Copyright 2005, 2007 by Rob Landley <rob@landley.net>.
- *
- * Not in SUSv3.
-
-USE_ONEIT(NEWTOY(oneit, "^<1c:p", TOYFLAG_SBIN))
-
-config ONEIT
-	bool "oneit"
-	default y
-	help
-	  usage: oneit [-p] [-c /dev/tty0] command [...]
-
-	  A simple init program that runs a single supplied command line with a
-	  controlling tty (so CTRL-C can kill it).
-
-	  -p	Power off instead of rebooting when command exits.
-	  -c	Which console device to use.
-
-	  The oneit command runs the supplied command line as a child process
-	  (because PID 1 has signals blocked), attached to /dev/tty0, in its
-	  own session.  Then oneit reaps zombies until the child exits, at
-	  which point it reboots (or with -p, powers off) the system.
-*/
-
-#include "toys.h"
-#include <sys/reboot.h>
-
-DEFINE_GLOBALS(
-	char *console;
-)
-
-#define TT this.oneit
-
-// The minimum amount of work necessary to get ctrl-c and such to work is:
-//
-// - Fork a child (PID 1 is special: can't exit, has various signals blocked).
-// - Do a setsid() (so we have our own session).
-// - In the child, attach stdio to /dev/tty0 (/dev/console is special)
-// - Exec the rest of the command line.
-//
-// PID 1 then reaps zombies until the child process it spawned exits, at which
-// point it calls sync() and reboot().  I could stick a kill -1 in there.
-
-
-void oneit_main(void)
-{
-  int i;
-  pid_t pid;
-
-  // Create a new child process.
-  pid = vfork();
-  if (pid) {
-
-    // pid 1 just reaps zombies until it gets its child, then halts the system.
-    while (pid!=wait(&i));
-    sync();
-
-	// PID 1 can't call reboot() because it kills the task that calls it,
-	// which causes the kernel to panic before the actual reboot happens.
-	if (!vfork()) reboot((toys.optflags&1) ? RB_POWER_OFF : RB_AUTOBOOT);
-	sleep(5);
-	_exit(1);
-  }
-
-  // Redirect stdio to /dev/tty0, with new session ID, so ctrl-c works.
-  setsid();
-  for (i=0; i<3; i++) {
-    close(i);
-    xopen(TT.console ? TT.console : "/dev/tty0",O_RDWR);
-  }
-
-  // Can't xexec() here, because we vforked so we don't want to error_exit().
-  toy_exec(toys.optargs);
-  execvp(*toys.optargs, toys.optargs);
-  _exit(127);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/bzcat.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,30 @@
+/* vi: set sw=4 ts=4:
+ *
+ * bzcat.c - decompress stdin to stdout using bunzip2.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3.
+
+USE_BZCAT(NEWTOY(bzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+
+config BZCAT
+	bool "bzcat"
+	default y
+	help
+	  usage: bzcat [filename...]
+
+	  Decompress listed files to stdout.  Use stdin if no files listed.
+*/
+
+#include "toys.h"
+
+static void do_bzcat(int fd, char *name)
+{
+    bunzipStream(fd, 1);
+}
+
+void bzcat_main(void)
+{
+    loopfiles(toys.optargs, do_bzcat);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/catv.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,67 @@
+/* vi: set sw=4 ts=4:
+ *
+ * cat -v implementation for toybox
+ *
+ * Copyright (C) 2006, 2007 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3, but see "Cat -v considered harmful" at
+ *   http://cm.bell-labs.com/cm/cs/doc/84/kp.ps.gz
+
+USE_CATV(NEWTOY(catv, "vte", TOYFLAG_USR|TOYFLAG_BIN))
+
+config CATV
+	bool "catv"
+	default y
+	help
+	  usage: catv [-evt] [filename...]
+
+	  Display nonprinting characters as escape sequences.  Use M-x for
+	  high ascii characters (>127), and ^x for other nonprinting chars.
+
+	  -e	Mark each newline with $
+	  -t	Show tabs as ^I
+	  -v	Don't use ^x or M-x escapes.
+*/
+
+#include "toys.h"
+
+// Callback function for loopfiles()
+
+static void do_catv(int fd, char *name)
+{
+	for(;;) {
+		int i, len;
+
+		len = read(fd, toybuf, sizeof(toybuf));
+		if (len < 0) toys.exitval = EXIT_FAILURE;
+		if (len < 1) break;
+		for (i=0; i<len; i++) {
+			char c=toybuf[i];
+
+			if (c > 126 && (toys.optflags & 4)) {
+				if (c == 127) {
+					printf("^?");
+					continue;
+				} else {
+					printf("M-");
+					c -= 128;
+				}
+			}
+			if (c < 32) {
+				if (c == 10) {
+					if (toys.optflags & 1) xputc('$');
+				} else if (toys.optflags & (c==9 ? 2 : 4)) {
+					printf("^%c", c+'@');
+					continue;
+				}
+			}
+			xputc(c);
+		}
+	}
+}
+
+void catv_main(void)
+{
+	toys.optflags^=4;
+	loopfiles(toys.optargs, do_catv);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/chroot.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,28 @@
+/* vi: set sw=4 ts=4:
+ *
+ * chroot.c - Run command in new root directory.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3.
+
+USE_CHROOT(NEWTOY(chroot, "^<1", TOYFLAG_USR|TOYFLAG_SBIN))
+
+config CHROOT
+	bool "chroot"
+	default y
+	help
+	  usage: chroot NEWPATH [commandline...]
+
+	  Run command within a new root directory.  If no command, run /bin/sh.
+*/
+
+#include "toys.h"
+
+void chroot_main(void)
+{
+	char *binsh[] = {"/bin/sh", "-i", 0};
+	if (chdir(*toys.optargs) || chroot("."))
+		perror_exit("%s", *toys.optargs);
+	xexec(toys.optargs[1] ? toys.optargs+1 : binsh);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/chvt.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,51 @@
+/* vi: set sw=4 ts=4:
+ *
+ * chvt.c - switch virtual terminals
+ *
+ * Copyright (C) 2008 David Anders <danders@amltd.com>
+ *
+ * Not in SUSv3.
+
+USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_SBIN))
+
+config CHVT
+	bool "chvt"
+	default y
+	help
+	  usage: chvt N
+
+	  Change to virtual terminal number N.  (This only works in text mode.)
+
+	  Virtual terminals are the Linux VGA text mode displays, ordinarily
+	  switched between via alt-F1, alt-F2, etc.  Use ctrl-alt-F1 to switch
+	  from X to a virtual terminal, and alt-F6 (or F7, or F8) to get back.
+*/
+
+#include "toys.h"
+
+/* Note: get_console_fb() will need to be moved into a seperate lib section */
+int get_console_fd()
+{
+	int fd;
+	char *consoles[]={"/dev/console", "/dev/vc/0", "/dev/tty", NULL}, **cc;
+
+	cc = consoles;
+	while (*cc) {
+		fd = open(*cc++, O_RDWR);
+		if (fd >= 0) return fd;
+	}
+
+	return -1;
+}
+
+void chvt_main(void)
+{
+	int vtnum, fd;
+
+	vtnum=atoi(*toys.optargs);
+
+	fd=get_console_fd();
+	// These numbers are VT_ACTIVATE and VT_WAITACTIVE from linux/vt.h
+	if (fd < 0 || ioctl(fd, 0x5606, vtnum) || ioctl(fd, 0x5607, vtnum))
+		perror_exit(NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/clear.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,23 @@
+/* vi: set sw=4 ts=4:
+ *
+ * clear.c - clear the screen
+ *
+ * Copyright 2012 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv4.
+
+USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+
+config CLEAR
+	bool "clear"
+	default y
+	help
+	  Clear the screen.
+*/
+
+#include "toys.h"
+
+void clear_main(void)
+{
+	write(1, "\e[2J\e[H", 7);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/count.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,36 @@
+/* vi: set sw=4 ts=4:
+ *
+ * count.c - Progress indicator from stdin to stdout
+ *
+ * Copyright 2002 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3.
+
+USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+
+config COUNT
+	bool "count"
+	default y
+	help
+	  usage: count
+
+	  Copy stdin to stdout, displaying simple progress indicator to stderr.
+*/
+
+#include "toys.h"
+
+void count_main(void)
+{
+	uint64_t size = 0;
+	int len;
+	char buf[32];
+
+	for (;;) {
+		len = xread(0, toybuf, sizeof(toybuf));
+		if (!len) break;
+		size += len;
+		xwrite(1, toybuf, len);
+		xwrite(2, buf, sprintf(buf, "%"PRIu64" bytes\r", size));
+	}
+	xwrite(2, "\n", 1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/dos2unix.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,70 @@
+/* vi: set sw=4 ts=4:
+ *
+ * dos2unix.c - convert newline format
+ *
+ * Copyright 2012 Rob Landley <rob@landley.net>
+ *
+ * No standard
+
+USE_DOS2UNIX(NEWTOY(dos2unix, NULL, TOYFLAG_BIN))
+USE_DOS2UNIX(OLDTOY(unix2dos, dos2unix, NULL, TOYFLAG_BIN))
+
+config DOS2UNIX
+	bool "dos2unix/unix2dos"
+	default y
+	help
+	  usage: dos2unix/unix2dos [file...]
+
+	  Convert newline format between dos (\r\n) and unix (just \n)
+	  If no files listed copy from stdin, "-" is a synonym for stdin.
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	char *tempfile;
+)
+
+#define TT this.dos2unix
+
+static void do_dos2unix(int fd, char *name)
+{
+	char c = toys.which->name[0];
+	int outfd = 1, catch = 0;
+
+	if (fd) outfd = copy_tempfile(fd, name, &TT.tempfile);
+
+	for (;;) {
+		int len, in, out;
+
+		len = read(fd, toybuf+(sizeof(toybuf)/2), sizeof(toybuf)/2);
+		if (len<0) {
+			perror_msg("%s",name);
+			toys.exitval = 1;
+		}
+		if (len<1) break;
+
+		for (in = out = 0; in < len; in++) {
+			char x = toybuf[in+sizeof(toybuf)/2];
+
+			// Drop \r only if followed by \n in dos2unix mode
+			if (catch) {
+				if (c == 'u' || x != '\n') toybuf[out++] = '\r';
+				catch = 0;
+			// Add \r only if \n not after \r in unix2dos mode
+			} else if (c == 'u' && x == '\n') toybuf[out++] = '\r';
+
+			if (x == '\r') catch++;
+			else toybuf[out++] = x;
+		}
+		xwrite(outfd, toybuf, out);
+	}
+	if (catch) xwrite(outfd, "\r", 1);
+
+	if (fd) replace_tempfile(-1, outfd, &TT.tempfile);
+}
+
+void dos2unix_main(void)
+{
+	loopfiles(toys.optargs, do_dos2unix);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/free.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,60 @@
+/* vi: set sw=4 ts=4:
+ *
+ * free.c - Display amount of free and used memory in the system.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_FREE(NEWTOY(free, "gmkb", TOYFLAG_USR|TOYFLAG_BIN))
+
+config FREE
+	bool "free"
+	default y
+	help
+	  usage: free [-bkmg]
+
+	  Display the total, free and used amount of physical memory and
+	  swap space.
+
+	  -bkmg    Output in bytes (default), KB, MB or GB
+*/
+
+#include "toys.h"
+
+static unsigned long long convert(unsigned long d, unsigned int iscale,
+				unsigned int oscale)
+{
+	return ((unsigned long long)d*iscale)>>oscale;
+}
+
+void free_main(void)
+{
+	struct sysinfo info;
+	unsigned int iscale = 1;
+	unsigned int oscale = 0;
+
+	sysinfo(&info);
+	if (info.mem_unit) iscale = info.mem_unit;
+	if (toys.optflags & 1) oscale = 0;
+	if (toys.optflags & 2) oscale = 10;
+	if (toys.optflags & 4) oscale = 20;
+	if (toys.optflags & 8) oscale = 30;
+
+	xprintf("\t\ttotal        used        free      shared     buffers\n");
+	xprintf("Mem:%17llu%12llu%12llu%12llu%12llu\n",
+		convert(info.totalram, iscale, oscale),
+		convert(info.totalram-info.freeram, iscale, oscale),
+		convert(info.freeram, iscale, oscale),
+		convert(info.sharedram, iscale, oscale),
+		convert(info.bufferram, iscale, oscale));
+
+	xprintf("-/+ buffers/cache:%15llu%12llu\n",
+		convert(info.totalram - info.freeram - info.bufferram, iscale, oscale),
+		convert(info.freeram + info.bufferram, iscale, oscale));
+
+	xprintf("Swap:%16llu%12llu%12llu\n",
+		convert(info.totalswap, iscale, oscale),
+		convert(info.totalswap - info.freeswap, iscale, oscale),
+		convert(info.freeswap, iscale, oscale));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/hello.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,60 @@
+/* vi: set sw=4 ts=4:
+ *
+ * hello.c - A hello world program.
+ *
+ * Copyright 2012 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv4/LSB.
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/
+ * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html
+
+USE_HELLO(NEWTOY(hello, "e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
+
+config HELLO
+	bool "hello"
+	default n
+	help
+	  usage: hello [-a] [-b string] [-c number] [-d list] [-e count] [...]
+
+	  A hello world program.  You don't need this.
+
+	  Mostly used as an example/skeleton file for adding new commands,
+	  occasionally nice to test kernel booting via "init=/bin/hello".
+*/
+
+#include "toys.h"
+
+// Hello doesn't use these globals, they're here for example/skeleton purposes.
+
+DEFINE_GLOBALS(
+	char *b_string;
+	long c_number;
+	struct arg_list *d_list;
+	long e_count;
+
+	int more_globals;
+)
+
+#define TT this.hello
+
+#define FLAG_a	1
+#define FLAG_b	2
+#define FLAG_c	4
+#define FLAG_d	8
+#define FLAG_e	16
+
+void hello_main(void)
+{
+	printf("Hello world\n");
+
+	if (toys.optflags & FLAG_a) printf("Saw a\n");
+	if (toys.optflags & FLAG_b) printf("b=%s\n", TT.b_string);
+	if (toys.optflags & FLAG_c) printf("c=%ld\n", TT.c_number);
+	while (TT.d_list) {
+		printf("d=%s\n", TT.d_list->arg);
+		TT.d_list = TT.d_list->next;
+	}
+	if (TT.e_count) printf("e was seen %ld times", TT.e_count);
+
+	while (*toys.optargs) printf("optarg=%s\n", *(toys.optargs++));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/help.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,48 @@
+/* vi: set sw=4 ts=4:
+ *
+ * help.c - Show help for toybox
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3, but exists as a bash builtin.
+
+USE_HELP(NEWTOY(help, "<1", TOYFLAG_BIN))
+
+config HELP
+	bool "help"
+	default y
+	help
+	  usage: help [command]
+
+	  Show usage information for toybox commands.
+	  Run "toybox" with no arguments for a list of available commands.
+*/
+ 
+
+#include "toys.h"
+#include "generated/help.h"
+
+#undef NEWTOY
+#undef OLDTOY
+#define NEWTOY(name,opt,flags) help_##name "\0"
+#define OLDTOY(name,oldname,opts,flags) "\xff" #oldname "\0"
+static char *help_data =
+#include "generated/newtoys.h"
+;
+
+void help_main(void)
+{
+	struct toy_list *t = toy_find(*toys.optargs);
+	int i = t-toy_list;
+	char *s = help_data;
+
+	if (!t) error_exit("Unknown command '%s'", *toys.optargs);
+	for (;;) {
+		while (i--) s += strlen(s) + 1;
+		if (*s != 255) break;
+		i = toy_find(++s)-toy_list;
+		s = help_data;
+	}
+
+	fprintf(toys.exithelp ? stderr : stdout, "%s", s);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/insmod.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,47 @@
+/* vi: set sw=4 ts=4:
+ *
+ * insmod.c - Load a module into the Linux kernel.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
+
+config INSMOD
+	bool "insmod"
+	default y
+	help
+	  usage: insmod MODULE [MODULE_OPTIONS]
+
+	  Load the module named MODULE passing options if given.
+*/
+
+#include "toys.h"
+
+#include <sys/syscall.h>
+#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
+
+void insmod_main(void)
+{
+	char * buf = NULL;
+	int len, res, i;
+	int fd = xopen(toys.optargs[0], O_RDONLY);
+
+	len = fdlength(fd);
+	buf = xmalloc(len);
+	xreadall(fd, buf, len);
+
+	i = 1;
+	while(toys.optargs[i] &&
+		strlen(toybuf) + strlen(toys.optargs[i]) + 2 < sizeof(toybuf)) {
+		strcat(toybuf, toys.optargs[i++]);
+		strcat(toybuf, " ");
+	}
+
+	res = init_module(buf, len, toybuf);
+	if (CFG_TOYBOX_FREE && buf != toybuf) free(buf);
+
+	if (res)
+		perror_exit("failed to load %s", toys.optargs[0]);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/login.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,246 @@
+/* vi: set sw=4 ts=4:
+ *
+ * login.c - Start a session on the system.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+ * No support for PAM/securetty/selinux/login script/issue/utmp
+ * Relies on libcrypt for hash calculation.
+
+USE_LOGIN(NEWTOY(login, ">1fph:", TOYFLAG_BIN))
+
+config LOGIN
+	bool "login"
+	default y
+	help
+	  usage: login [-p] [-h host] [[-f] username]
+
+	  Establish a new session with the system.
+	  -p    Preserve environment
+	  -h    The name of the remote host for this login
+	  -f    Do not perform authentication
+*/
+
+#include "toys.h"
+
+#define LOGIN_TIMEOUT 60
+#define LOGIN_FAIL_TIMEOUT 3
+#define USER_NAME_MAX_SIZE 32
+#define HOSTNAME_SIZE 32
+
+DEFINE_GLOBALS(
+	char *hostname;
+)
+#define TT this.login
+
+static void login_timeout_handler(int sig __attribute__((unused)))
+{
+	printf("\nLogin timed out after %d seconds.\n", LOGIN_TIMEOUT);
+	exit(0);
+}
+
+static char *forbid[] = {
+	"BASH_ENV",
+	"ENV",
+	"HOME",
+	"IFS",
+	"LD_LIBRARY_PATH",
+	"LD_PRELOAD",
+	"LD_TRACE_LOADED_OBJECTS",
+	"LD_BIND_NOW",
+	"LD_AOUT_LIBRARY_PATH",
+	"LD_AOUT_PRELOAD",
+	"LD_NOWARN",
+	"LD_KEEPDIR",
+	"SHELL",
+	NULL
+};
+
+int verify_password(char * pwd)
+{
+	char *pass;
+
+	if (read_password(toybuf, sizeof(toybuf), "Password: ")) return 1;
+	if (!pwd) return 1;
+	if (pwd[0] == '!' || pwd[0] == '*') return 1;
+
+	pass = crypt(toybuf, pwd);
+	if (pass && !strcmp(pass, pwd)) return 0;
+
+	return 1;
+}
+
+void read_user(char * buff, int size)
+{
+	char hostname[HOSTNAME_SIZE+1];
+	int i = 0;
+	hostname[HOSTNAME_SIZE] = 0;
+	if(!gethostname(hostname, HOSTNAME_SIZE)) fputs(hostname, stdout);
+
+	fputs(" login: ", stdout);
+	fflush(stdout);
+
+	do {
+		buff[0] = getchar();
+		if (buff[0] == EOF)
+			exit(EXIT_FAILURE);
+	} while (isblank(buff[0]));
+
+	if (buff[0] != '\n')
+		if(!fgets(&buff[1], HOSTNAME_SIZE-1, stdin))
+			_exit(1);
+
+	while(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) i++;
+	buff[i] = 0;
+}
+
+void handle_nologin(void)
+{
+	int fd = open("/etc/nologin", O_RDONLY);
+	int size;
+	if (fd == -1) return;
+
+	size = readall(fd, toybuf,sizeof(toybuf)-1);
+	toybuf[size] = 0;
+	if (!size) puts("System closed for routine maintenance\n");
+	else puts(toybuf);
+
+	close(fd);
+	fflush(stdout);
+	exit(EXIT_FAILURE);
+}
+
+void handle_motd(void)
+{
+	int fd = open("/etc/motd", O_RDONLY);
+	int size;
+	if (fd == -1) return;
+
+	size = readall(fd, toybuf,sizeof(toybuf)-1);
+	toybuf[size] = 0;
+	puts(toybuf);
+
+	close(fd);
+	fflush(stdout);
+}
+
+int change_identity(const struct passwd *pwd)
+{
+	if (initgroups(pwd->pw_name,pwd->pw_gid)) return 1;
+	if (setgid(pwd->pw_uid)) return 1;
+	if (setuid(pwd->pw_uid)) return 1;
+
+	return 0;
+}
+
+void spawn_shell(const char *shell)
+{
+	const char * exec_name = strrchr(shell,'/');
+	if (exec_name) exec_name++;
+	else exec_name = shell;
+
+	snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell);
+	execl(shell, toybuf, NULL);
+	error_exit("Failed to spawn shell");
+}
+
+void setup_environment(const struct passwd *pwd, int clear_env)
+{
+	if (chdir(pwd->pw_dir)) printf("bad home dir: %s\n", pwd->pw_dir);
+
+	if (clear_env) {
+		const char * term = getenv("TERM");
+		clearenv();
+		if (term) setenv("TERM", term, 1);
+	}
+
+	setenv("USER", pwd->pw_name, 1);
+	setenv("LOGNAME", pwd->pw_name, 1);
+	setenv("HOME", pwd->pw_dir, 1);
+	setenv("SHELL", pwd->pw_shell, 1);
+}
+
+void login_main(void)
+{
+	int f_flag = (toys.optflags & 4) >> 2;
+	int p_flag = (toys.optflags & 2) >> 1;
+	int h_flag = toys.optflags & 1;
+	char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss;
+	struct passwd * pwd = NULL;
+	struct spwd * spwd = NULL;
+	int auth_fail_cnt = 0;
+
+	if (f_flag && toys.optc != 1)
+		error_exit("-f requires username");
+
+	if (geteuid()) error_exit("not root");
+
+	if (!isatty(0) || !isatty(1) || !isatty(2)) error_exit("no tty");
+
+	openlog("login", LOG_PID | LOG_CONS, LOG_AUTH);
+	signal(SIGALRM, login_timeout_handler);
+	alarm(LOGIN_TIMEOUT);
+
+	for (ss = forbid; *ss; ss++) unsetenv(*ss);
+
+	while (1) {
+		tcflush(0, TCIFLUSH);
+
+		username[USER_NAME_MAX_SIZE] = 0;
+		if (toys.optargs[0])
+			strncpy(username, toys.optargs[0], USER_NAME_MAX_SIZE);
+		else {
+			read_user(username, USER_NAME_MAX_SIZE+1);
+			if (username[0] == 0) continue;
+		}
+
+		pwd = getpwnam(username);
+		if (!pwd) goto query_pass; // Non-existing user
+
+		if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*')
+			goto query_pass;  // Locked account
+
+		if (f_flag) break; // Pre-authenticated
+
+		if (!pwd->pw_passwd[0]) break; // Password-less account
+
+		pass = pwd->pw_passwd;
+		if (pwd->pw_passwd[0] == 'x') {
+			spwd = getspnam (username);
+			if (spwd) pass = spwd->sp_pwdp;
+		}
+
+query_pass:
+		if (!verify_password(pass)) break;
+
+		f_flag = 0;
+		syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username,
+			ttyname(0), (h_flag)?"from":"", (h_flag)?TT.hostname:"");
+
+		sleep(LOGIN_FAIL_TIMEOUT);
+		puts("Login incorrect");
+
+		if (++auth_fail_cnt == 3)
+			error_exit("Maximum number of tries exceeded (%d)\n", auth_fail_cnt);
+
+		username[0] = 0;
+		pwd = NULL;
+		spwd = NULL;
+	}
+
+	alarm(0);
+
+	if (pwd->pw_uid) handle_nologin();
+
+	if (change_identity(pwd)) error_exit("Failed to change identity");
+
+	setup_environment(pwd, !p_flag);
+
+	handle_motd();
+
+	syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name,
+		ttyname(0), (h_flag)?"from":"", (h_flag)?TT.hostname:"");
+
+	spawn_shell(pwd->pw_shell);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/lsmod.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,42 @@
+/* vi: set sw=4 ts=4:
+ *
+ * lsmod.c - Show the status of modules in the kernel
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_LSMOD(NEWTOY(lsmod, NULL, TOYFLAG_BIN))
+
+config LSMOD
+	bool "lsmod"
+	default y
+	help
+	  usage: lsmod
+
+	  Display the currently loaded modules, their sizes and their
+	  dependencies.
+*/
+
+#include "toys.h"
+
+void lsmod_main(void)
+{
+	char *modfile = "/proc/modules";
+	FILE * file = xfopen(modfile, "r");
+
+	xprintf("%-23s Size  Used by\n", "Module");
+
+	while (fgets(toybuf, sizeof(toybuf), file)) {
+		char *name = strtok(toybuf, " "), *size = strtok(NULL, " "),
+			*refcnt = strtok(NULL, " "), *users = strtok(NULL, " ");
+
+		if(users) {
+			int len = strlen(users)-1;
+			if (users[len] == ',' || users[len] == '-')
+				users[len] = 0;
+			xprintf("%-19s %8s  %s %s\n", name, size, refcnt, users);
+		} else perror_exit("bad %s", modfile);
+	}
+	fclose(file);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/mdev.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,213 @@
+/* vi:set ts=4:
+ *
+ * mdev - Mini udev for busybox
+ *
+ * Copyright 2005, 2008 Rob Landley <rob@landley.net>
+ * Copyright 2005 Frank Sorenson <frank@tuxrocks.com>
+ *
+ * Not in SUSv3.
+
+USE_MDEV(NEWTOY(mdev, "s", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
+
+config MDEV
+	bool "mdev"
+	default n
+	help
+	  usage: mdev [-s]
+
+	  Create devices in /dev using information from /sys.
+
+	  -s	Scan all entries in /sys to populate /dev.
+
+config MDEV_CONF
+	bool "Configuration file for mdev"
+	default y
+	depends on MDEV
+	help
+	  The mdev config file (/etc/mdev.conf) contains lines that look like:
+		hd[a-z][0-9]* 0:3 660
+
+	  Each line must contain three whitespace separated fields.  The first
+	  field is a regular expression matching one or more device names, and
+	  the second and third fields are uid:gid and file permissions for
+	  matching devies.
+*/
+
+#include "toys.h"
+#include "lib/xregcomp.h"
+
+// todo, open() block devices to trigger partition scanning.
+
+// mknod in /dev based on a path like "/sys/block/hda/hda1"
+static void make_device(char *path)
+{
+	char *device_name, *s, *temp;
+	int major, minor, type, len, fd;
+	int mode = 0660;
+	uid_t uid = 0;
+	gid_t gid = 0;
+
+	// Try to read major/minor string
+
+	temp = strrchr(path, '/');
+	fd = open(path, O_RDONLY);
+	*temp=0;
+	temp = toybuf;
+	len = read(fd, temp, 64);
+	close(fd);
+	if (len<1) return;
+	temp[len] = 0;
+
+	// Determine device name, type, major and minor
+
+	device_name = strrchr(path, '/') + 1;
+	type = path[5]=='c' ? S_IFCHR : S_IFBLK;
+	major = minor = 0;
+	sscanf(temp, "%u:%u", &major, &minor);
+
+	// If we have a config file, look up permissions for this device
+
+	if (CFG_MDEV_CONF) {
+		char *conf, *pos, *end;
+
+		// mmap the config file
+		if (-1!=(fd = open("/etc/mdev.conf", O_RDONLY))) {
+			len = fdlength(fd);
+			conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+			if (conf) {
+				int line = 0;
+
+				// Loop through lines in mmaped file
+				for (pos = conf; pos-conf<len;) {
+					int field;
+					char *end2;
+
+					line++;
+					// find end of this line
+					for(end = pos; end-conf<len && *end!='\n'; end++);
+
+					// Three fields: regex, uid:gid, mode
+					for (field = 3; field; field--) {
+						// Skip whitespace
+						while (pos<end && isspace(*pos)) pos++;
+						if (pos==end || *pos=='#') break;
+						for (end2 = pos;
+							end2<end && !isspace(*end2) && *end2!='#'; end2++);
+						switch(field) {
+							// Regex to match this device
+							case 3:
+							{
+								char *regex = strndup(pos, end2-pos);
+								regex_t match;
+								regmatch_t off;
+								int result;
+
+								// Is this it?
+								xregcomp(&match, regex, REG_EXTENDED);
+								result=regexec(&match, device_name, 1, &off, 0);
+								regfree(&match);
+								free(regex);
+
+								// If not this device, skip rest of line
+								if (result || off.rm_so
+									|| off.rm_eo!=strlen(device_name))
+										goto end_line;
+
+								break;
+							}
+							// uid:gid
+							case 2:
+							{
+								char *s2;
+
+								// Find :
+								for(s = pos; s<end2 && *s!=':'; s++);
+								if (s==end2) goto end_line;
+
+								// Parse UID
+								uid = strtoul(pos,&s2,10);
+								if (s!=s2) {
+									struct passwd *pass;
+									char *str = strndup(pos, s-pos);
+									pass = getpwnam(str);
+									free(str);
+									if (!pass) goto end_line;
+									uid = pass->pw_uid;
+								}
+								s++;
+								// parse GID
+								gid = strtoul(s,&s2,10);
+								if (end2!=s2) {
+									struct group *grp;
+									char *str = strndup(s, end2-s);
+									grp = getgrnam(str);
+									free(str);
+									if (!grp) goto end_line;
+									gid = grp->gr_gid;
+								}
+								break;
+							}
+							// mode
+							case 1:
+							{
+								mode = strtoul(pos, &pos, 8);
+								if (pos!=end2) goto end_line;
+								goto found_device;
+							}
+						}
+						pos=end2;
+					}
+end_line:
+					// Did everything parse happily?
+					if (field && field!=3) error_exit("Bad line %d", line);
+
+					// Next line
+					pos = ++end;
+				}
+found_device:
+				munmap(conf, len);
+			}
+			close(fd);
+		}
+	}
+
+	sprintf(temp, "/dev/%s", device_name);
+	if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST)
+		perror_exit("mknod %s failed", temp);
+
+	if (CFG_MDEV_CONF) mode=chown(temp, uid, gid);
+}
+
+static int callback(struct dirtree *node)
+{
+	// Entries in /sys/class/block aren't char devices, so skip 'em.  (We'll
+	// get block devices out of /sys/block.)
+	if(!strcmp(node->name, "block")) return 0;
+
+	// Does this directory have a "dev" entry in it?
+	// This is path based because the hotplug callbacks are
+	if (S_ISDIR(node->st.st_mode) || S_ISLNK(node->st.st_mode)) {
+		int len=4;
+		char *dev = dirtree_path(node, &len);
+		strcpy(dev+len, "/dev");
+		if (!access(dev, R_OK)) make_device(dev);
+		free(dev);
+	}
+
+	// Circa 2.6.25 the entries more than 2 deep are all either redundant
+	// (mouse#, event#) or unnamed (every usb_* entry is called "device").
+
+	return (node->parent && node->parent->parent) ? 0 : DIRTREE_RECURSE;
+}
+
+void mdev_main(void)
+{
+	// Handle -s
+
+	if (toys.optflags) {
+		dirtree_read("/sys/class", callback);
+		dirtree_read("/sys/block", callback);
+	}
+
+	// hotplug support goes here
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/mke2fs.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,662 @@
+/* vi: set ts=4:
+ *
+ * mke2fs.c - Create an ext2 filesystem image.
+ *
+ * Copyright 2006, 2007 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3.
+
+// Still to go: "E:jJ:L:m:O:"
+USE_MKE2FS(NEWTOY(mke2fs, "<1>2g:Fnqm#N#i#b#", TOYFLAG_SBIN))
+
+config MKE2FS
+	bool "mke2fs (unfinished and broken by dirtree changes)"
+	default n
+	help
+	  usage: mke2fs [-Fnq] [-b ###] [-N|i ###] [-m ###] device
+
+	  Create an ext2 filesystem on a block device or filesystem image.
+
+	  -F         Force to run on a mounted device
+	  -n         Don't write to device
+	  -q         Quiet (no output)
+	  -b size    Block size (1024, 2048, or 4096)
+	  -N inodes  Allocate this many inodes
+	  -i bytes   Allocate one inode for every XXX bytes of device
+	  -m percent Reserve this percent of filesystem space for root user
+
+config MKE2FS_JOURNAL
+	bool "Journaling support (ext3)"
+	default n
+	depends on MKE2FS
+	help
+	  usage: [-j] [-J size=###,device=XXX]
+
+	  -j         Create journal (ext3)
+	  -J         Journal options
+	             size: Number of blocks (1024-102400)
+	             device: Specify an external journal
+
+config MKE2FS_GEN
+	bool "Generate (gene2fs)"
+	default n
+	depends on MKE2FS
+	help
+	  usage: gene2fs [options] device filename
+
+	  The [options] are the same as mke2fs.
+
+config MKE2FS_LABEL
+	bool "Label support"
+	default n
+	depends on MKE2FS
+	help
+	  usage: mke2fs [-L label] [-M path] [-o string]
+
+	  -L         Volume label
+	  -M         Path to mount point
+	  -o         Created by
+
+config MKE2FS_EXTENDED
+	bool "Extended options"
+	default n
+	depends on MKE2FS
+	help
+	  usage: mke2fs [-E stride=###] [-O option[,option]]
+
+	  -E stride= Set RAID stripe size (in blocks)
+	  -O [opts]  Specify fewer ext2 option flags (for old kernels)
+	             All of these are on by default (as appropriate)
+	     none         Clear default options (all but journaling)
+	     dir_index    Use htree indexes for large directories
+	     filetype     Store file type info in directory entry
+	     has_journal  Set by -j
+	     journal_dev  Set by -J device=XXX
+	     sparse_super Don't allocate huge numbers of redundant superblocks
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	// Command line arguments.
+	long blocksize;
+	long bytes_per_inode;
+	long inodes;           // Total inodes in filesystem.
+	long reserved_percent; // Integer precent of space to reserve for root.
+	char *gendir;          // Where to read dirtree from.
+
+	// Internal data.
+	struct dirtree *dt;    // Tree of files to copy into the new filesystem.
+	unsigned treeblocks;   // Blocks used by dt
+	unsigned treeinodes;   // Inodes used by dt
+
+	unsigned blocks;       // Total blocks in the filesystem.
+	unsigned freeblocks;   // Free blocks in the filesystem.
+	unsigned inodespg;     // Inodes per group
+	unsigned groups;       // Total number of block groups.
+	unsigned blockbits;    // Bits per block.  (Also blocks per group.)
+
+	// For gene2fs
+	unsigned nextblock;    // Next data block to allocate
+	unsigned nextgroup;    // Next group we'll be allocating from
+	int fsfd;              // File descriptor of filesystem (to output to).
+
+	struct ext2_superblock sb;
+)
+
+// Shortcut to our global data structure, since we use it so much.
+#define TT this.mke2fs
+
+#define INODES_RESERVED 10
+
+static uint32_t div_round_up(uint32_t a, uint32_t b)
+{
+	uint32_t c = a/b;
+
+	if (a%b) c++;
+	return c;
+}
+
+// Calculate data blocks plus index blocks needed to hold a file.
+
+static uint32_t file_blocks_used(uint64_t size, uint32_t *blocklist)
+{
+	uint32_t dblocks = (uint32_t)((size+(TT.blocksize-1))/TT.blocksize);
+	uint32_t idx=TT.blocksize/4, iblocks=0, diblocks=0, tiblocks=0;
+
+	// Fill out index blocks in inode.
+
+	if (blocklist) {
+		int i;
+
+		// Direct index blocks
+		for (i=0; i<13 && i<dblocks; i++) blocklist[i] = i;
+		// Singly indirect index blocks
+		if (dblocks > 13+idx) blocklist[13] = 13+idx;
+		// Doubly indirect index blocks
+		idx = 13 + idx + (idx*idx);
+		if (dblocks > idx) blocklist[14] = idx;
+
+		return 0;
+	}
+
+	// Account for direct, singly, doubly, and triply indirect index blocks
+
+	if (dblocks > 12) {
+		iblocks = ((dblocks-13)/idx)+1;
+		if (iblocks > 1) {
+			diblocks = ((iblocks-2)/idx)+1;
+			if (diblocks > 1)
+				tiblocks = ((diblocks-2)/idx)+1;
+		}
+	}
+
+	return dblocks + iblocks + diblocks + tiblocks;
+}
+
+// Use the parent pointer to iterate through the tree non-recursively.
+static struct dirtree *treenext(struct dirtree *this)
+{
+	while (this && !this->next) this = this->parent;
+	if (this) this = this->next;
+
+	return this;
+}
+
+// Recursively calculate the number of blocks used by each inode in the tree.
+// Returns blocks used by this directory, assigns bytes used to *size.
+// Writes total block count to TT.treeblocks and inode count to TT.treeinodes.
+
+static long check_treesize(struct dirtree *that, off_t *size)
+{
+	long blocks;
+
+	while (that) {
+		*size += sizeof(struct ext2_dentry) + strlen(that->name);
+
+		if (that->child)
+			that->st.st_blocks = check_treesize(that->child, &that->st.st_size);
+		else if (S_ISREG(that->st.st_mode)) {
+			 that->st.st_blocks = file_blocks_used(that->st.st_size, 0);
+			 TT.treeblocks += that->st.st_blocks;
+		}
+		that = that->next;
+	}
+	TT.treeblocks += blocks = file_blocks_used(*size, 0);
+	TT.treeinodes++;
+
+	return blocks;
+}
+
+// Calculate inode numbers and link counts.
+// 
+// To do this right I need to copy the tree and sort it, but here's a really
+// ugly n^2 way of dealing with the problem that doesn't scale well to large
+// numbers of files (> 100,000) but can be done in very little code.
+// This rewrites inode numbers to their final values, allocating depth first.
+
+static void check_treelinks(struct dirtree *tree)
+{
+	struct dirtree *current=tree, *that;
+	long inode = INODES_RESERVED;
+
+	while (current) {
+		++inode;
+		// Since we can't hardlink to directories, we know their link count.
+		if (S_ISDIR(current->st.st_mode)) current->st.st_nlink = 2;
+		else {
+			dev_t new = current->st.st_dev;
+
+			if (!new) continue;
+
+			// Look for other copies of current node
+			current->st.st_nlink = 0;
+			for (that = tree; that; that = treenext(that)) {
+				if (current->st.st_ino == that->st.st_ino &&
+					current->st.st_dev == that->st.st_dev)
+				{
+					current->st.st_nlink++;
+					current->st.st_ino = inode;
+				}
+			}
+		}
+		current->st.st_ino = inode;
+		current = treenext(current);
+	}
+}
+
+// According to http://www.opengroup.org/onlinepubs/9629399/apdxa.htm
+// we should generate a uuid structure by reading a clock with 100 nanosecond
+// precision, normalizing it to the start of the gregorian calendar in 1582,
+// and looking up our eth0 mac address.
+//
+// On the other hand, we have 128 bits to come up with a unique identifier, of
+// which 6 have a defined value.  /dev/urandom it is.
+
+static void create_uuid(char *uuid)
+{
+	// Read 128 random bits
+	int fd = xopen("/dev/urandom", O_RDONLY);
+	xreadall(fd, uuid, 16);
+	close(fd);
+
+	// Claim to be a DCE format UUID.
+	uuid[6] = (uuid[6] & 0x0F) | 0x40;
+	uuid[8] = (uuid[8] & 0x3F) | 0x80;
+
+    // rfc2518 section 6.4.1 suggests if we're not using a macaddr, we should
+	// set bit 1 of the node ID, which is the mac multicast bit.  This means we
+	// should never collide with anybody actually using a macaddr.
+	uuid[11] = uuid[11] | 128;
+}
+
+// Calculate inodes per group from total inodes.
+static uint32_t get_inodespg(uint32_t inodes)
+{
+	uint32_t temp;
+
+	// Round up to fill complete inode blocks.
+	temp = (inodes + TT.groups - 1) / TT.groups;
+	inodes = TT.blocksize/sizeof(struct ext2_inode);
+	return ((temp + inodes - 1)/inodes)*inodes;
+}
+
+// Fill out superblock and TT structures.
+
+static void init_superblock(struct ext2_superblock *sb)
+{
+	uint32_t temp;
+
+	// Set log_block_size and log_frag_size.
+
+	for (temp = 0; temp < 4; temp++) if (TT.blocksize == 1024<<temp) break;
+	if (temp==4) error_exit("bad blocksize");
+	sb->log_block_size = sb->log_frag_size = SWAP_LE32(temp);
+
+	// Fill out blocks_count, r_blocks_count, first_data_block
+
+	sb->blocks_count = SWAP_LE32(TT.blocks);
+	sb->free_blocks_count = SWAP_LE32(TT.freeblocks);
+	temp = (TT.blocks * (uint64_t)TT.reserved_percent) / 100;
+	sb->r_blocks_count = SWAP_LE32(temp);
+
+	sb->first_data_block = SWAP_LE32(TT.blocksize == 1024 ? 1 : 0);
+
+	// Set blocks_per_group and frags_per_group, which is the size of an
+	// allocation bitmap that fits in one block (I.E. how many bits per block)?
+
+	sb->blocks_per_group = sb->frags_per_group = SWAP_LE32(TT.blockbits);
+
+	// Set inodes_per_group and total inodes_count
+	sb->inodes_per_group = SWAP_LE32(TT.inodespg);
+	sb->inodes_count = SWAP_LE32(TT.inodespg * TT.groups);
+
+	// Determine free inodes.
+	temp = TT.inodespg*TT.groups - INODES_RESERVED;
+	if (temp < TT.treeinodes) error_exit("Not enough inodes.\n");
+	sb->free_inodes_count = SWAP_LE32(temp - TT.treeinodes);
+
+	// Fill out the rest of the superblock.
+	sb->max_mnt_count=0xFFFF;
+	sb->wtime = sb->lastcheck = sb->mkfs_time = SWAP_LE32(time(NULL));
+	sb->magic = SWAP_LE32(0xEF53);
+	sb->state = sb->errors = SWAP_LE16(1);
+
+	sb->rev_level = SWAP_LE32(1);
+	sb->first_ino = SWAP_LE32(INODES_RESERVED+1);
+	sb->inode_size = SWAP_LE16(sizeof(struct ext2_inode));
+	sb->feature_incompat = SWAP_LE32(EXT2_FEATURE_INCOMPAT_FILETYPE);
+	sb->feature_ro_compat = SWAP_LE32(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER);
+
+	create_uuid(sb->uuid);
+	
+	// TODO If we're called as mke3fs or mkfs.ext3, do a journal.
+
+	//if (strchr(toys.which->name,'3'))
+	//	sb->feature_compat |= SWAP_LE32(EXT3_FEATURE_COMPAT_HAS_JOURNAL);
+}
+
+// Does this group contain a superblock backup (and group descriptor table)?
+static int is_sb_group(uint32_t group)
+{
+	int i;
+
+	// Superblock backups are on groups 0, 1, and powers of 3, 5, and 7.
+	if(!group || group==1) return 1;
+	for (i=3; i<9; i+=2) {
+		int j = i;
+		while (j<group) j*=i;
+		if (j==group) return 1;
+	}
+	return 0;
+}
+
+	
+// Number of blocks used in group by optional superblock/group list backup.
+static int group_superblock_overhead(uint32_t group)
+{
+	int used;
+
+	if (!is_sb_group(group)) return 0;
+
+	// How many blocks does the group descriptor table take up?
+	used = TT.groups * sizeof(struct ext2_group);
+	used += TT.blocksize - 1;
+	used /= TT.blocksize;
+	// Plus the superblock itself.
+	used++;
+	// And a corner case.
+	if (!group && TT.blocksize == 1024) used++;
+
+	return used;
+}
+
+// Number of blocks used in group to store superblock/group/inode list
+static int group_overhead(uint32_t group)
+{
+	// Return superblock backup overhead (if any), plus block/inode
+	// allocation bitmaps, plus inode tables.
+	return group_superblock_overhead(group) + 2 + get_inodespg(TT.inodespg)
+				/ (TT.blocksize/sizeof(struct ext2_inode));
+}
+
+// In bitmap "array" set "len" bits starting at position "start" (from 0).
+static void bits_set(char *array, int start, int len)
+{
+	while(len) {
+		if ((start&7) || len<8) {
+			array[start/8]|=(1<<(start&7));
+			start++;
+			len--;
+		} else {
+			array[start/8]=255;
+			start+=8;
+			len-=8;
+		}
+	}
+}
+
+// Seek past len bytes (to maintain sparse file), or write zeroes if output
+// not seekable
+static void put_zeroes(int len)
+{
+	if(-1 == lseek(TT.fsfd, len, SEEK_SET)) {
+		memset(toybuf, 0, sizeof(toybuf));
+		while (len) {
+			int out = len > sizeof(toybuf) ? sizeof(toybuf) : len;
+			xwrite(TT.fsfd, toybuf, out);
+			len -= out;
+		}
+	}
+}
+
+// Fill out an inode structure from struct stat info in dirtree.
+static void fill_inode(struct ext2_inode *in, struct dirtree *that)
+{
+	uint32_t fbu[15];
+	int temp;
+
+	file_blocks_used(that->st.st_size, fbu);
+
+	// If that inode needs data blocks allocated to it.
+	if (that->st.st_size) {
+		int i, group = TT.nextblock/TT.blockbits;
+
+		// TODO: teach this about indirect blocks.
+		for (i=0; i<15; i++) {
+			// If we just jumped into a new group, skip group overhead blocks.
+			while (group >= TT.nextgroup)
+				TT.nextblock += group_overhead(TT.nextgroup++);
+		}
+	}
+	// TODO :  S_ISREG/DIR/CHR/BLK/FIFO/LNK/SOCK(m)
+	in->mode = SWAP_LE32(that->st.st_mode);
+
+	in->uid = SWAP_LE16(that->st.st_uid & 0xFFFF);
+	in->uid_high = SWAP_LE16(that->st.st_uid >> 16);
+	in->gid = SWAP_LE16(that->st.st_gid & 0xFFFF);
+	in->gid_high = SWAP_LE16(that->st.st_gid >> 16);
+	in->size = SWAP_LE32(that->st.st_size & 0xFFFFFFFF);
+
+	// Contortions to make the compiler not generate a warning for x>>32
+	// when x is 32 bits.  The optimizer should clean this up.
+	if (sizeof(that->st.st_size) > 4) temp = 32;
+	else temp = 0;
+	if (temp) in->dir_acl = SWAP_LE32(that->st.st_size >> temp);
+	
+	in->atime = SWAP_LE32(that->st.st_atime);
+	in->ctime = SWAP_LE32(that->st.st_ctime);
+	in->mtime = SWAP_LE32(that->st.st_mtime);
+
+	in->links_count = SWAP_LE16(that->st.st_nlink);
+	in->blocks = SWAP_LE32(that->st.st_blocks);
+	// in->faddr
+}
+
+// Works like an archiver.
+// The first argument is the name of the file to create.  If it already
+// exists, that size will be used.
+
+void mke2fs_main(void)
+{
+	int i, temp;
+	off_t length;
+	uint32_t usedblocks, usedinodes, dtiblk, dtbblk;
+	struct dirtree *dti, *dtb;
+
+	// Handle command line arguments.
+
+	if (toys.optargs[1]) {
+		sscanf(toys.optargs[1], "%u", &TT.blocks);
+		temp = O_RDWR|O_CREAT;
+	} else temp = O_RDWR;
+	if (!TT.reserved_percent) TT.reserved_percent = 5;
+
+	// TODO: Check if filesystem is mounted here
+
+	// For mke?fs, open file.  For gene?fs, create file.
+	TT.fsfd = xcreate(*toys.optargs, temp, 0777);
+	
+	// Determine appropriate block size and block count from file length.
+	// (If no length, default to 4k.  They can override it on the cmdline.)
+
+	length = fdlength(TT.fsfd);
+	if (!TT.blocksize) TT.blocksize = (length && length < 1<<29) ? 1024 : 4096;
+	TT.blockbits = 8*TT.blocksize;
+	if (!TT.blocks) TT.blocks = length/TT.blocksize;
+
+	// Collect gene2fs list or lost+found, calculate requirements.
+
+	if (TT.gendir) {
+		strncpy(toybuf, TT.gendir, sizeof(toybuf));
+		dti = dirtree_read(toybuf, NULL, NULL);
+	} else {
+		dti = xzalloc(sizeof(struct dirtree)+11);
+		strcpy(dti->name, "lost+found");
+		dti->st.st_mode = S_IFDIR|0755;
+		dti->st.st_ctime = dti->st.st_mtime = time(NULL);
+	}
+
+	// Add root directory inode.  This is iterated through for when finding
+	// blocks, but not when finding inodes.  The tree's parent pointers don't
+	// point back into this.
+
+	dtb = xzalloc(sizeof(struct dirtree)+1);
+	dtb->st.st_mode = S_IFDIR|0755;
+	dtb->st.st_ctime = dtb->st.st_mtime = time(NULL);
+	dtb->child = dti;
+	
+	// Figure out how much space is used by preset files
+	length = check_treesize(dtb, &(dtb->st.st_size));
+	check_treelinks(dtb);
+
+	// Figure out how many total inodes we need.
+
+	if (!TT.inodes) {
+		if (!TT.bytes_per_inode) TT.bytes_per_inode = 8192;
+		TT.inodes = (TT.blocks * (uint64_t)TT.blocksize) / TT.bytes_per_inode;
+	}
+
+	// If we're generating a filesystem and have no idea how many blocks it
+	// needs, start with a minimal guess, find the overhead of that many
+	// groups, and loop until this is enough groups to store this many blocks.
+	if (!TT.blocks) TT.groups = (TT.treeblocks/TT.blockbits)+1;
+	else TT.groups = div_round_up(TT.blocks, TT.blockbits);
+
+	for (;;) {
+		temp = TT.treeblocks;
+
+		for (i = 0; i<TT.groups; i++) temp += group_overhead(i);
+
+		if (TT.blocks) {
+			if (TT.blocks < temp) error_exit("Not enough space.\n");
+			break;
+		}
+		if (temp <= TT.groups * TT.blockbits) {
+			TT.blocks = temp;
+			break;
+		}
+		TT.groups++;
+	}
+	TT.freeblocks = TT.blocks - temp;
+
+	// Now we know all the TT data, initialize superblock structure.
+
+	init_superblock(&TT.sb);
+
+	// Start writing.  Skip the first 1k to avoid the boot sector (if any).
+	put_zeroes(1024);
+
+	// Loop through block groups, write out each one.
+	dtiblk = dtbblk = usedblocks = usedinodes = 0;
+	for (i=0; i<TT.groups; i++) {
+		struct ext2_inode *in = (struct ext2_inode *)toybuf;
+		uint32_t start, itable, used, end;
+		int j, slot;
+
+		// Where does this group end?
+		end = TT.blockbits;
+		if ((i+1)*TT.blockbits > TT.blocks) end = TT.blocks & (TT.blockbits-1);
+
+		// Blocks used by inode table
+		itable = (TT.inodespg*sizeof(struct ext2_inode))/TT.blocksize;
+
+		// If a superblock goes here, write it out.
+		start = group_superblock_overhead(i);
+		if (start) {
+			struct ext2_group *bg = (struct ext2_group *)toybuf;
+			int treeblocks = TT.treeblocks, treeinodes = TT.treeinodes;
+
+			TT.sb.block_group_nr = SWAP_LE16(i);
+
+			// Write superblock and pad it up to block size
+			xwrite(TT.fsfd, &TT.sb, sizeof(struct ext2_superblock));
+			temp = TT.blocksize - sizeof(struct ext2_superblock);
+			if (!i && TT.blocksize > 1024) temp -= 1024;
+			memset(toybuf, 0, TT.blocksize);
+			xwrite(TT.fsfd, toybuf, temp);
+
+			// Loop through groups to write group descriptor table.
+			for(j=0; j<TT.groups; j++) {
+
+				// Figure out what sector this group starts in.
+				used = group_superblock_overhead(j);
+
+				// Find next array slot in this block (flush block if full).
+				slot = j % (TT.blocksize/sizeof(struct ext2_group));
+				if (!slot) {
+					if (j) xwrite(TT.fsfd, bg, TT.blocksize);
+					memset(bg, 0, TT.blocksize);
+				}
+
+				// How many free inodes in this group?
+				temp = TT.inodespg;
+				if (!i) temp -= INODES_RESERVED;
+				if (temp > treeinodes) {
+					treeinodes -= temp;
+					temp = 0;
+				} else {
+					temp -= treeinodes;
+					treeinodes = 0;
+				}
+				bg[slot].free_inodes_count = SWAP_LE16(temp);
+
+				// How many free blocks in this group?
+				temp = TT.inodespg/(TT.blocksize/sizeof(struct ext2_inode)) + 2;
+				temp = end-used-temp;
+				if (temp > treeblocks) {
+					treeblocks -= temp;
+					temp = 0;
+				} else {
+					temp -= treeblocks;
+					treeblocks = 0;
+				}
+				bg[slot].free_blocks_count = SWAP_LE32(temp);
+
+				// Fill out rest of group structure
+				used += j*TT.blockbits;
+				bg[slot].block_bitmap = SWAP_LE32(used++);
+				bg[slot].inode_bitmap = SWAP_LE32(used++);
+				bg[slot].inode_table = SWAP_LE32(used);
+				bg[slot].used_dirs_count = 0;  // (TODO)
+			}
+			xwrite(TT.fsfd, bg, TT.blocksize);
+		}
+
+		// Now write out stuff that every block group has.
+
+		// Write block usage bitmap
+
+		start += 2 + itable;
+		memset(toybuf, 0, TT.blocksize);
+		bits_set(toybuf, 0, start);
+		bits_set(toybuf, end, TT.blockbits-end);
+		temp = TT.treeblocks - usedblocks;
+		if (temp) {
+			if (end-start > temp) temp = end-start;
+			bits_set(toybuf, start, temp);
+		}
+		xwrite(TT.fsfd, toybuf, TT.blocksize);
+
+		// Write inode bitmap
+		memset(toybuf, 0, TT.blocksize);
+		j = 0;
+		if (!i) bits_set(toybuf, 0, j = INODES_RESERVED);
+		bits_set(toybuf, TT.inodespg, slot = TT.blockbits-TT.inodespg);
+		temp = TT.treeinodes - usedinodes;
+		if (temp) {
+			if (slot-j > temp) temp = slot-j;
+			bits_set(toybuf, j, temp);
+		}
+		xwrite(TT.fsfd, toybuf, TT.blocksize);
+
+		// Write inode table for this group (TODO)
+		for (j = 0; j<TT.inodespg; j++) {
+			slot = j % (TT.blocksize/sizeof(struct ext2_inode));
+			if (!slot) {
+				if (j) xwrite(TT.fsfd, in, TT.blocksize);
+				memset(in, 0, TT.blocksize);
+			}
+			if (!i && j<INODES_RESERVED) {
+				// Write root inode
+				if (j == 2) fill_inode(in+slot, dtb);
+			} else if (dti) {
+				fill_inode(in+slot, dti);
+				dti = treenext(dti);
+			}
+		}
+		xwrite(TT.fsfd, in, TT.blocksize);
+
+		while (dtb) {
+			// TODO write index data block
+			// TODO write root directory data block
+			// TODO write directory data block
+			// TODO write file data block
+			put_zeroes(TT.blocksize);
+			start++;
+			if (start == end) break;
+		}
+		// Write data blocks (TODO)
+		put_zeroes((end-start) * TT.blocksize);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/mkswap.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,42 @@
+/* vi: set sw=4 ts=4:
+ *
+ * mkswap.c - Format swap device.
+ *
+ * Copyright 2009 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv4.
+
+USE_MKSWAP(NEWTOY(mkswap, "<1>1", TOYFLAG_SBIN))
+
+config MKSWAP
+	bool "mkswap"
+	default y
+	help
+	  usage: mkswap DEVICE
+
+	  Sets up a Linux swap area on a device or file.
+*/
+
+#include "toys.h"
+
+void mkswap_main(void)
+{
+	int fd = xopen(*toys.optargs, O_RDWR), pagesize = sysconf(_SC_PAGE_SIZE);
+	off_t len = fdlength(fd);
+	unsigned int pages = (len/pagesize)-1, *swap = (unsigned int *)toybuf;
+
+	// Write header.  Note that older kernel versions checked signature
+	// on disk (not in cache) during swapon, so sync after writing.
+
+	swap[0] = 1;
+	swap[1] = pages;
+	xlseek(fd, 1024, SEEK_SET);
+	xwrite(fd, swap, 129*sizeof(unsigned int));
+	xlseek(fd, pagesize-10, SEEK_SET);
+	xwrite(fd, "SWAPSPACE2", 10);
+	fsync(fd);
+
+	if (CFG_TOYBOX_FREE) close(fd);
+
+	printf("Swapspace size: %luk\n", pages*(unsigned long)(pagesize/1024));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/modinfo.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,103 @@
+/* vi: set sw=4 ts=4:
+ *
+ * modinfo.c - Display module info
+ *
+ * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
+ *
+
+USE_MODINFO(NEWTOY(modinfo, "<1F:0", TOYFLAG_BIN))
+
+config MODINFO
+	bool "modinfo"
+	default y
+	help
+	  usage: modinfo [-0] [-F field] [modulename...]
+*/
+
+#include "toys.h"
+
+#define FLAG_0  (1 << 0)
+
+DEFINE_GLOBALS(
+    char *field;
+)
+#define TT this.modinfo
+
+static const char *modinfo_tags[] = {
+    "alias", "license", "description", "author", "vermagic",
+    "srcversion", "intree", "parm", "depends",
+};
+
+static void output_field(const char *field, const char *value)
+{
+    int len;
+
+    if (TT.field && strcmp(TT.field, field) != 0)
+        return;
+
+    len = strlen(field);
+
+    if (TT.field)
+        xprintf("%s", value);
+    else
+        xprintf("%s:%*s%s",
+                field, 15 - len, "", value);
+    if (toys.optflags & FLAG_0)
+        xwrite(fileno(stdout), "\0", 1);
+    else
+        xputs("");
+}
+
+
+static void modinfo_file(struct dirtree *dir)
+{
+    int fd, len, i;
+    char *buf, *pos;
+    char *full_name;
+
+    full_name = dirtree_path(dir, NULL);
+
+    output_field("filename", full_name);
+    fd = xopen(full_name, O_RDONLY);
+    len = fdlength(fd);
+    buf = xmalloc(len);
+    xreadall(fd, buf, len);
+
+    for (pos = buf; pos < buf + len + 10; pos++) {
+        if (*pos)
+            continue;
+
+        for (i = 0; i < sizeof(modinfo_tags) / sizeof(modinfo_tags[0]); i++) {
+            const char *str = modinfo_tags[i];
+            int len = strlen(str); 
+            if (strncmp(pos + 1, str, len) == 0 && pos[len + 1] == '=')
+                output_field(str, &pos[len + 2]);
+        }
+    }
+
+    free(full_name);
+    free(buf);
+    close(fd);
+}
+
+static int check_module(struct dirtree *new)
+{
+    if (S_ISREG(new->st.st_mode)) {
+        char **s;
+        for (s = toys.optargs; *s; s++) {
+            int len = strlen(*s);
+            if (!strncmp(*s, new->name, len) && !strcmp(new->name+len, ".ko"))
+                modinfo_file(new);
+        }
+    }
+
+    return dirtree_notdotdot(new);
+}
+
+void modinfo_main(void)
+{
+    struct utsname uts;
+    if (uname(&uts) < 0) perror_exit("bad uname");
+    sprintf(toybuf, "/lib/modules/%s", uts.release);
+    dirtree_read(toybuf, check_module);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/mountpoint.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,56 @@
+/* vi: set sw=4 ts=4:
+ *
+ * mountpoint.c - Check if a directory is a mountpoint.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_MOUNTPOINT(NEWTOY(mountpoint, "<1qdx", TOYFLAG_BIN))
+
+config MOUNTPOINT
+	bool "mountpoint"
+	default y
+	help
+	  usage: mountpoint [-q] [-d] directory
+			 mountpoint [-q] [-x] device 
+	  -q Be quiet, return zero if directory is a mountpoint
+	  -d Print major/minor device number of the directory
+	  -x Print major/minor device number of the block device
+*/
+
+#include "toys.h"
+
+void mountpoint_main(void)
+{
+	struct stat st1, st2;
+	int res = 0;
+	int quiet = toys.optflags & 0x4;
+	toys.exitval = 1; // be pessimistic
+	strncpy(toybuf, toys.optargs[0], sizeof(toybuf));
+	if (((toys.optflags & 0x1) && lstat(toybuf, &st1)) || stat(toybuf, &st1))
+		perror_exit("%s", toybuf);
+
+	if (toys.optflags & 0x1){
+		if (S_ISBLK(st1.st_mode)) {
+			if (!quiet) printf("%u:%u\n", major(st1.st_rdev), minor(st1.st_rdev));
+			toys.exitval = 0;
+			return;
+		}
+		if (!quiet) printf("%s: not a block device\n", toybuf);
+		return;
+	}
+
+	if(!S_ISDIR(st1.st_mode)){
+		if (!quiet) printf("%s: not a directory\n", toybuf);
+		return;
+	}
+	strncat(toybuf, "/..", sizeof(toybuf));
+	stat(toybuf, &st2);
+	res = (st1.st_dev != st2.st_dev) ||
+		(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
+	if (!quiet) printf("%s is %sa mountpoint\n", toys.optargs[0], res ? "" : "not ");
+	if (toys.optflags & 0x2)
+		printf("%u:%u\n", major(st1.st_dev), minor(st1.st_dev));
+	toys.exitval = res ? 0 : 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/netcat.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,232 @@
+/* vi: set sw=4 ts=4:
+ *
+ * nc: mini-netcat - Forward stdin/stdout to a file or network connection.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3.
+
+USE_NETCAT(OLDTOY(nc, netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN))
+USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN))
+
+config NETCAT
+	bool "netcat"
+	default y
+	help
+	  usage: netcat [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|-let} [-e COMMAND]
+
+	  -w	SECONDS timeout for connection
+	  -p	local port number
+	  -s	local ipv4 address
+	  -q	SECONDS quit this many seconds after EOF on stdin.
+	  -f	use FILENAME (ala /dev/ttyS0) instead of network
+
+	  Use "stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho" with
+	  netcat -f to connect to a serial port.
+
+
+config NETCAT_LISTEN
+	bool "netcat sever options (-let)"
+	default y
+	depends on NETCAT
+	help
+	  -t    allocate tty (must come before -l or -L)
+	  -l	listen for one incoming connection.
+	  -L	listen for multiple incoming connections (server mode).
+
+	  Any additional command line arguments after -l or -L are executed
+	  to handle each incoming connection.  If none, the connection is
+	  forwarded to stdin/stdout.
+
+	  For a quick-and-dirty server, try something like:
+		netcat -s 127.0.0.1 -p 1234 -tL /bin/bash -l
+*/
+
+#include "toys.h"
+#include "toynet.h"
+
+DEFINE_GLOBALS(
+	char *filename;        // -f read from filename instead of network
+	long quit_delay;       // -q Exit after EOF from stdin after # seconds.
+	char *source_address;  // -s Bind to a specific source address.
+	long port;             // -p Bind to a specific source port.
+	long wait;             // -w Wait # seconds for a connection.
+)
+
+#define TT this.netcat
+
+#define FLAG_f   1
+#define FLAG_L  32
+#define FLAG_l  64
+#define FLAG_t 128
+
+static void timeout(int signum)
+{
+	if (TT.wait) error_exit("Timeout");
+	exit(0);
+}
+
+static void set_alarm(int seconds)
+{
+	signal(SIGALRM, seconds ? timeout : SIG_DFL);
+	alarm(seconds);
+}
+
+// Translate x.x.x.x numeric IPv4 address, or else DNS lookup an IPv4 name.
+static void lookup_name(char *name, uint32_t *result)
+{
+	struct hostent *hostbyname;
+
+	hostbyname = gethostbyname(name);
+	if (!hostbyname) error_exit("no host '%s'", name);
+	*result = *(uint32_t *)*hostbyname->h_addr_list;
+}
+
+// Worry about a fancy lookup later.
+static void lookup_port(char *str, uint16_t *port)
+{
+  *port = SWAP_BE16(atoi(str));
+}
+
+void netcat_main(void)
+{
+	int sockfd=-1, pollcount=2;
+	struct pollfd pollfds[2];
+
+	memset(pollfds, 0, 2*sizeof(struct pollfd));
+	pollfds[0].events = pollfds[1].events = POLLIN;
+	set_alarm(TT.wait);
+
+	// The argument parsing logic can't make "<2" conditional on other
+	// arguments like -f and -l, so we do it by hand here.
+	if (toys.optflags&FLAG_f) {
+		if (toys.optc) toys.exithelp++;
+	} else if (!(toys.optflags&(FLAG_l|FLAG_L)) && toys.optc!=2) toys.exithelp++;
+
+	if (toys.exithelp) error_exit("Argument count wrong");
+
+	if (TT.filename) pollfds[0].fd = xopen(TT.filename, O_RDWR);
+	else {
+		int temp;
+		struct sockaddr_in address;
+
+		// Setup socket
+		sockfd = socket(AF_INET, SOCK_STREAM, 0);
+		if (-1 == sockfd) perror_exit("socket");
+		fcntl(sockfd, F_SETFD, FD_CLOEXEC);
+		temp = 1;
+		setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(temp));
+		memset(&address, 0, sizeof(address));
+		address.sin_family = AF_INET;
+		if (TT.source_address || TT.port) {
+			address.sin_port = SWAP_BE16(TT.port);
+			if (TT.source_address) 
+				lookup_name(TT.source_address, (uint32_t *)&address.sin_addr);
+			if (bind(sockfd, (struct sockaddr *)&address, sizeof(address)))
+				perror_exit("bind");
+		}
+
+		// Dial out
+
+		if (!CFG_NETCAT_LISTEN || !(toys.optflags&(FLAG_L|FLAG_l))) {
+			// Figure out where to dial out to.
+			lookup_name(*toys.optargs, (uint32_t *)&address.sin_addr);
+			lookup_port(toys.optargs[1], &address.sin_port);
+			temp = connect(sockfd, (struct sockaddr *)&address, sizeof(address));
+			if (temp<0) perror_exit("connect");
+			pollfds[0].fd = sockfd;
+
+		// Listen for incoming connections
+
+		} else {
+			socklen_t len = sizeof(address);
+
+			if (listen(sockfd, 5)) error_exit("listen");
+			if (!TT.port) {
+				getsockname(sockfd, (struct sockaddr *)&address, &len);
+				printf("%d\n", SWAP_BE16(address.sin_port));
+				fflush(stdout);
+			}
+			// Do we need to return immediately because -l has arguments?
+
+			if ((toys.optflags&FLAG_l) && toys.optc) {
+				if (fork()) goto cleanup;
+				close(0);
+				close(1);
+				close(2);
+			}
+
+			for (;;) {
+				pid_t child = 0;
+
+				// For -l, call accept from the _new_ thread.
+
+				pollfds[0].fd = accept(sockfd, (struct sockaddr *)&address,
+					&len);
+				if (pollfds[0].fd<0) perror_exit("accept");
+
+				// Do we need a tty?
+
+				if (toys.optflags&FLAG_t)
+					child = forkpty(&(pollfds[1].fd), NULL, NULL, NULL);
+
+				// Do we need to fork and/or redirect for exec?
+
+				else {
+					if (toys.optflags&FLAG_L) child = fork();
+					if (!child && toys.optc) {
+						int fd = pollfds[0].fd;
+
+						if (!temp) close(sockfd);
+						dup2(fd, 0);
+						dup2(fd, 1);
+						dup2(fd, 2);
+						if (fd>2) close(fd);
+					}
+				}
+
+				if (child<0) error_msg("Fork failed\n");
+				if (child<1) break;
+				close(pollfds[0].fd);
+			}
+		}
+	}
+
+	// We have a connection.  Disarm timeout.
+	// (Does not play well with -L, but what _should_ that do?)
+	set_alarm(0);
+
+	if (CFG_NETCAT_LISTEN && (toys.optflags&(FLAG_L|FLAG_l) && toys.optc)) {
+		execvp(*toys.optargs, toys.optargs);
+		error_exit("Exec failed");
+	}
+
+	// Poll loop copying stdin->socket and socket->stdout.
+	for (;;) {
+		int i;
+
+		if (0>poll(pollfds, pollcount, -1)) perror_exit("poll");
+
+		for (i=0; i<pollcount; i++) {
+			if (pollfds[i].revents & POLLIN) {
+				int len = read(pollfds[i].fd, toybuf, sizeof(toybuf));
+				if (len<1) goto dohupnow;
+				xwrite(i ? pollfds[0].fd : 1, toybuf, len);
+			} else if (pollfds[i].revents & POLLHUP) {
+dohupnow:
+				// Close half-connection.  This is needed for things like
+				// "echo GET / | netcat landley.net 80"
+				if (i) {
+					shutdown(pollfds[0].fd, SHUT_WR);
+					pollcount--;
+					set_alarm(TT.quit_delay);
+				} else goto cleanup;
+			}
+		}
+	}
+cleanup:
+	if (CFG_TOYBOX_FREE) {
+		close(pollfds[0].fd);
+		close(sockfd);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/oneit.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,80 @@
+/* vi: set sw=4 ts=4:
+ *
+ * oneit.c, tiny one-process init replacement.
+ *
+ * Copyright 2005, 2007 by Rob Landley <rob@landley.net>.
+ *
+ * Not in SUSv3.
+
+USE_ONEIT(NEWTOY(oneit, "^<1c:p", TOYFLAG_SBIN))
+
+config ONEIT
+	bool "oneit"
+	default y
+	help
+	  usage: oneit [-p] [-c /dev/tty0] command [...]
+
+	  A simple init program that runs a single supplied command line with a
+	  controlling tty (so CTRL-C can kill it).
+
+	  -p	Power off instead of rebooting when command exits.
+	  -c	Which console device to use.
+
+	  The oneit command runs the supplied command line as a child process
+	  (because PID 1 has signals blocked), attached to /dev/tty0, in its
+	  own session.  Then oneit reaps zombies until the child exits, at
+	  which point it reboots (or with -p, powers off) the system.
+*/
+
+#include "toys.h"
+#include <sys/reboot.h>
+
+DEFINE_GLOBALS(
+	char *console;
+)
+
+#define TT this.oneit
+
+// The minimum amount of work necessary to get ctrl-c and such to work is:
+//
+// - Fork a child (PID 1 is special: can't exit, has various signals blocked).
+// - Do a setsid() (so we have our own session).
+// - In the child, attach stdio to /dev/tty0 (/dev/console is special)
+// - Exec the rest of the command line.
+//
+// PID 1 then reaps zombies until the child process it spawned exits, at which
+// point it calls sync() and reboot().  I could stick a kill -1 in there.
+
+
+void oneit_main(void)
+{
+  int i;
+  pid_t pid;
+
+  // Create a new child process.
+  pid = vfork();
+  if (pid) {
+
+    // pid 1 just reaps zombies until it gets its child, then halts the system.
+    while (pid!=wait(&i));
+    sync();
+
+	// PID 1 can't call reboot() because it kills the task that calls it,
+	// which causes the kernel to panic before the actual reboot happens.
+	if (!vfork()) reboot((toys.optflags&1) ? RB_POWER_OFF : RB_AUTOBOOT);
+	sleep(5);
+	_exit(1);
+  }
+
+  // Redirect stdio to /dev/tty0, with new session ID, so ctrl-c works.
+  setsid();
+  for (i=0; i<3; i++) {
+    close(i);
+    xopen(TT.console ? TT.console : "/dev/tty0",O_RDWR);
+  }
+
+  // Can't xexec() here, because we vforked so we don't want to error_exit().
+  toy_exec(toys.optargs);
+  execvp(*toys.optargs, toys.optargs);
+  _exit(127);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/printenv.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,47 @@
+/* vi: set sw=4 ts=4:
+ *
+ * printenv.c - Print environment variables.
+ *
+ * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
+ *
+
+USE_PRINTENV(NEWTOY(printenv, "0(null)", TOYFLAG_USR|TOYFLAG_BIN))
+
+config PRINTENV
+	bool "printenv"
+	default y
+	help
+	  usage: printenv [-0] [env_var...]
+
+	  Print environment variables.
+
+	  -0	Use \0 as delimiter instead of \n
+*/
+
+#include "toys.h"
+
+extern char **environ;
+
+void printenv_main(void)
+{
+	char **env, **var = toys.optargs;
+	char delim = '\n';
+
+	if (toys.optflags) delim = 0;
+
+	do {
+		int catch = 0, len = *var ? strlen(*var) : 0;
+
+		for (env = environ; *env; env++) {
+			char *out = *env;
+			if (*var) {
+				if (!strncmp(out, *var, len) && out[len] == '=')
+					out += len +1;
+				else continue;
+			}
+			xprintf("%s%c", out, delim);
+			catch++;
+		}
+		if (*var && !catch) toys.exitval = 1;
+	} while (*var && *(++var));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/readlink.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4:
+ *
+ * readlink.c - Return string representation of a symbolic link.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3.
+
+USE_READLINK(NEWTOY(readlink, "<1f", TOYFLAG_BIN))
+
+config READLINK
+	bool "readlink"
+	default n
+	help
+	  usage: readlink
+
+	  Show what a symbolic link points to.
+
+config READLINK_F
+	bool "readlink -f"
+	default n
+	depends on READLINK
+	help
+	  usage: readlink [-f]
+
+	  -f	Show full cannonical path, with no symlinks in it.  Returns
+		nonzero if nothing could currently exist at this location.
+*/
+
+#include "toys.h"
+
+void readlink_main(void)
+{
+	char *s;
+
+	// Calculating full cannonical path?
+
+	if (CFG_READLINK_F && toys.optflags) s = xrealpath(*toys.optargs);
+	else s = xreadlink(*toys.optargs);
+
+	if (s) {
+		xputs(s);
+		if (CFG_TOYBOX_FREE) free(s);
+	} else toys.exitval = 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/realpath.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,31 @@
+/* vi: set sw=4 ts=4:
+ *
+ * realpath.c - Return the canonical version of a pathname
+ *
+ * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
+ *
+ * Not in SUSv4.
+
+USE_REALPATH(NEWTOY(realpath, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+
+config REALPATH
+	bool "realpath"
+	default y
+	help
+	  usage: realpath FILE...
+
+	  Display the canonical absolute pathname
+*/
+
+#include "toys.h"
+
+void realpath_main(void)
+{
+    char **s = toys.optargs;
+    for (s = toys.optargs; *s; s++) {
+        if (!realpath(*s, toybuf)) {
+            perror_msg("cannot access '%s'", *s);
+            toys.exitval = 1;
+        } else xputs(toybuf);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/rmmod.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,51 @@
+/* vi: set sw=4 ts=4:
+ *
+ * rmmod.c - Remove a module from the Linux kernel.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_RMMOD(NEWTOY(rmmod, "<1wf", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
+
+config RMMOD
+	bool "rmmod"
+	default y
+	help
+	  usage: rmmod [-wf] [MODULE]
+
+	  Unload the module named MODULE from the Linux kernel.
+	  -f   Force unload of a module
+	  -w   Wait until the module is no longer used.
+
+*/
+
+#include "toys.h"
+
+#include <sys/syscall.h>
+#define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
+
+void rmmod_main(void)
+{
+	unsigned int flags = O_NONBLOCK|O_EXCL;
+	char * mod_name;
+	int len;
+
+	// Basename
+	mod_name = strrchr(toys.optargs[0],'/');
+	if (mod_name)
+		mod_name++;
+	else
+		mod_name = toys.optargs[0];
+
+	// Remove .ko if present
+	len = strlen(mod_name);
+	if (len > 3 && !strcmp(&mod_name[len-3], ".ko" ))
+		mod_name[len-3] = 0;
+
+	if (toys.optflags & 1) flags |= O_TRUNC;
+	if (toys.optflags & 2) flags &= ~O_NONBLOCK;
+
+	if (delete_module(mod_name, flags))
+		perror_exit("failed to unload %s", mod_name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/setsid.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,33 @@
+/* vi: set sw=4 ts=4:
+ *
+ * setsid.c - Run program in a new session ID.
+ *
+ * Copyright 2006 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv4.
+
+USE_SETSID(NEWTOY(setsid, "^<1t", TOYFLAG_USR|TOYFLAG_BIN))
+
+config SETSID
+	bool "setsid"
+	default y
+	help
+	  usage: setsid [-t] command [args...]
+
+	  Run process in a new session.
+
+	  -t	Grab tty (become foreground process, receiving keyboard signals)
+*/
+
+#include "toys.h"
+
+void setsid_main(void)
+{
+	while (setsid()<0)
+		if (vfork()) _exit(0);
+	if (toys.optflags) {
+		setpgid(0,0);
+		tcsetpgrp(0, getpid());
+	}
+	xexec(toys.optargs);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/sha1sum.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,185 @@
+/* vi: set sw=4 ts=4:
+ *
+ * sha1sum.c - Calculate sha1 cryptographic hash for input.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * Based on the public domain SHA-1 in C by Steve Reid <steve@edmweb.com>
+ * from http://www.mirrors.wiretapped.net/security/cryptography/hashes/sha1/
+ *
+ * Not in SUSv3.
+
+USE_SHA1SUM(NEWTOY(sha1sum, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+
+config SHA1SUM
+	bool "sha1sum"
+	default y
+	help
+	  usage: sha1sum [file...]
+
+	  Calculate sha1 hash of files (or stdin).
+*/
+
+#include <toys.h>
+
+struct sha1 {
+	uint32_t state[5];
+	uint32_t oldstate[5];
+	uint64_t count;
+	union {
+		unsigned char c[64];
+		uint32_t i[16];
+	} buffer;
+};
+
+static void sha1_init(struct sha1 *this);
+static void sha1_transform(struct sha1 *this);
+static void sha1_update(struct sha1 *this, char *data, unsigned int len);
+static void sha1_final(struct sha1 *this, char digest[20]);
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+// blk0() and blk() perform the initial expand.
+// The idea of expanding during the round function comes from SSLeay
+#if 1
+#define blk0(i) (block[i] = (rol(block[i],24)&0xFF00FF00) \
+	|(rol(block[i],8)&0x00FF00FF))
+#else	// big endian?
+#define blk0(i) block[i]
+#endif
+#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
+	^block[(i+2)&15]^block[i&15],1))
+
+static const uint32_t rconsts[]={0x5A827999,0x6ED9EBA1,0x8F1BBCDC,0xCA62C1D6};
+
+// Hash a single 512-bit block. This is the core of the algorithm.
+
+static void sha1_transform(struct sha1 *this)
+{
+	int i, j, k, count;
+	uint32_t *block = this->buffer.i;
+	uint32_t *rot[5], *temp;
+
+	// Copy context->state[] to working vars
+	for (i=0; i<5; i++) {
+		this->oldstate[i] = this->state[i];
+		rot[i] = this->state + i;
+	}
+	// 4 rounds of 20 operations each.
+	for (i=count=0; i<4; i++) {
+		for (j=0; j<20; j++) {
+			uint32_t work;
+
+			work = *rot[2] ^ *rot[3];
+			if (!i) work = (work & *rot[1]) ^ *rot[3];
+			else {
+				if (i==2)
+					work = ((*rot[1]|*rot[2])&*rot[3])|(*rot[1]&*rot[2]);
+				else work ^= *rot[1];
+			}
+			if (!i && j<16) work += blk0(count);
+			else work += blk(count);
+			*rot[4] += work + rol(*rot[0],5) + rconsts[i];
+			*rot[1] = rol(*rot[1],30);
+
+			// Rotate by one for next time.
+			temp = rot[4];
+			for (k=4; k; k--) rot[k] = rot[k-1];
+			*rot = temp;
+			count++;
+		}
+	}
+	// Add the previous values of state[]
+	for (i=0; i<5; i++) this->state[i] += this->oldstate[i];
+}
+
+
+// Initialize a struct sha1.
+
+static void sha1_init(struct sha1 *this)
+{
+	/* SHA1 initialization constants */
+	this->state[0] = 0x67452301;
+	this->state[1] = 0xEFCDAB89;
+	this->state[2] = 0x98BADCFE;
+	this->state[3] = 0x10325476;
+	this->state[4] = 0xC3D2E1F0;
+	this->count = 0;
+}
+
+// Fill the 64-byte working buffer and call sha1_transform() when full.
+
+void sha1_update(struct sha1 *this, char *data, unsigned int len)
+{
+	unsigned int i, j;
+
+	j = this->count & 63;
+	this->count += len;
+
+	// Enough data to process a frame?
+	if ((j + len) > 63) {
+		i = 64-j;
+		memcpy(this->buffer.c + j, data, i);
+		sha1_transform(this);
+		for ( ; i + 63 < len; i += 64) {
+			memcpy(this->buffer.c, data + i, 64);
+			sha1_transform(this);
+		}
+		j = 0;
+	} else i = 0;
+	// Grab remaining chunk
+	memcpy(this->buffer.c + j, data + i, len - i);
+}
+
+// Add padding and return the message digest.
+
+void sha1_final(struct sha1 *this, char digest[20])
+{
+	uint64_t count = this->count << 3;
+	unsigned int i;
+	char buf;
+
+	// End the message by appending a "1" bit to the data, ending with the
+	// message size (in bits, big endian), and adding enough zero bits in
+	// between to pad to the end of the next 64-byte frame.
+	//
+	// Since our input up to now has been in whole bytes, we can deal with
+	// bytes here too.
+
+	buf = 0x80;
+	do {
+		sha1_update(this, &buf, 1);
+		buf = 0;
+	} while ((this->count & 63) != 56);
+	for (i = 0; i < 8; i++)
+	  this->buffer.c[56+i] = count >> (8*(7-i));
+	sha1_transform(this);
+
+	for (i = 0; i < 20; i++)
+		digest[i] = this->state[i>>2] >> ((3-(i & 3)) * 8);
+	// Wipe variables.  Cryptogropher paranoia.
+	memset(this, 0, sizeof(struct sha1));
+}
+
+// Callback for loopfiles()
+
+static void do_sha1(int fd, char *name)
+{
+	struct sha1 this;
+	int len;
+
+	sha1_init(&this);
+	for (;;) {
+		len = read(fd, toybuf, sizeof(toybuf));
+		if (len<1) break;
+		sha1_update(&this, toybuf, len);
+	}
+	sha1_final(&this, toybuf);
+	for (len = 0; len < 20; len++) printf("%02x", toybuf[len]);
+	printf("  %s\n", name);
+}
+
+void sha1sum_main(void)
+{
+	loopfiles(toys.optargs, do_sha1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/swapoff.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,26 @@
+/* vi: set sw=4 ts=4:
+ *
+ * swapoff.c - Disable region for swapping
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_SWAPOFF(NEWTOY(swapoff, "<1>1", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
+
+config SWAPOFF
+	bool "swapoff"
+	default y
+	help
+	  usage: swapoff swapregion
+
+	  Disable swapping on a given swapregion.
+*/
+
+#include "toys.h"
+
+void swapoff_main(void)
+{
+	if (swapoff(toys.optargs[0]))
+		perror_exit("failed to remove swaparea");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/swapon.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4:
+ *
+ * swapon.c - Enable region for swapping
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_SWAPON(NEWTOY(swapon, "<1>1p#<0>32767", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
+
+config SWAPON
+	bool "swapon"
+	default y
+	help
+	  usage: swapon [-p priority] filename
+
+	  Enable swapping on a given device/file.
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	long priority;
+)
+
+#define TT this.swapon
+
+void swapon_main(void)
+{
+	int flags = 0;
+
+	if (toys.optflags & 1)
+		flags = SWAP_FLAG_PREFER | (TT.priority << SWAP_FLAG_PRIO_SHIFT);
+
+	if (swapon(*toys.optargs, flags))
+		perror_exit("Couldn't swapon '%s'", *toys.optargs);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/tac.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,55 @@
+/* vi: set sw=4 ts=4:
+ *
+ * tac.c - output lines in reverse order
+ *
+ * Copyright 2012 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv4.
+
+USE_TAC(NEWTOY(tac, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+
+config TAC
+	bool "tac"
+	default y
+	help
+	  usage: tac [FILE...]
+
+	  Output lines in reverse order.
+*/
+
+#include "toys.h"
+
+void do_tac(int fd, char *name)
+{
+	struct arg_list *list = NULL;
+	char *c;
+
+	// Read in lines
+	for (;;) {
+		struct arg_list *temp;
+		int len;
+
+		if (!(c = get_line(fd))) break;
+
+		len = strlen(c);
+		if (len && c[len-1]=='\n') c[len-1] = 0;
+		temp = xmalloc(sizeof(struct arg_list));
+		temp->next = list;
+		temp->arg = c;
+		list = temp;
+	}
+
+	// Play them back.
+	while (list) {
+		struct arg_list *temp = list->next;
+		xputs(list->arg);
+		free(list->arg);
+		free(list);
+		list = temp;
+	}
+}
+
+void tac_main(void)
+{
+	loopfiles(toys.optargs, do_tac);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/taskset.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,110 @@
+/* vi: set sw=4 ts=4:
+ *
+ * taskset.c - Retrieve or set the CPU affinity of a process.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * No standard.
+
+USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_BIN|TOYFLAG_STAYROOT))
+
+config TASKSET
+	bool "taskset"
+	default y
+	help
+	  usage: taskset [-ap] [mask] [PID | cmd [args...]]
+
+	  Launch a new task which may only run on certain processors, or change
+	  the processor affinity of an exisitng PID.
+
+	  Mask is a hex string where each bit represents a processor the process
+	  is allowed to run on. PID without a mask displays existing affinity.
+
+	  -p	Set/get the affinity of given PID instead of a new command.
+	  -a	Set/get the affinity of all threads of the PID.
+*/
+
+#include "toys.h"
+
+#define FLAG_a 0x1
+#define FLAG_p 0x2
+
+// Prototype for syscall wrappers sched.h refuses to give us
+int sched_setaffinity(pid_t pid, size_t size, void *cpuset);
+int sched_getaffinity(pid_t pid, size_t size, void *cpuset);
+
+// mask is an array of long, which makes the layout a bit weird on big
+// endian systems but as long as it's consistent...
+
+static void do_taskset(pid_t pid, int quiet)
+{
+	unsigned long *mask = (unsigned long *)toybuf;
+	char *s = *toys.optargs, *failed = "failed to %s %d's affinity";
+	int i, j, k;
+
+	for (i=0; ; i++) {
+		if (!quiet) {
+			int j = sizeof(toybuf), flag = 0;
+
+			if (sched_getaffinity(pid, sizeof(toybuf), (void *)mask))
+				perror_exit(failed, "get", pid);
+
+			printf("pid %d's %s affinity mask: ", pid, i ? "new" : "current");
+
+			while (j--) {
+				int x = 255 & (mask[j/sizeof(long)] >> (8*(j&(sizeof(long)-1))));
+
+				if (flag) printf("%02x", x);
+				else if (x) {
+					flag++;
+					printf("%x", x);
+				}
+			}
+			putchar('\n');
+		}
+
+		if (i || toys.optc < 2) return;
+
+		memset(toybuf, 0, sizeof(toybuf));
+		k = strlen(s = *toys.optargs);
+		s += k;
+		for (j = 0; j<k; j++) {
+			unsigned long digit = *(--s) - '0';
+
+			if (digit > 9) digit = 10 + tolower(*s)-'a';
+			if (digit > 15) error_exit("bad mask '%s'", *toys.optargs);
+			mask[j/(2*sizeof(long))] |= digit << 4*(j&((2*sizeof(long))-1));
+		}
+
+		if (sched_setaffinity(pid, sizeof(toybuf), (void *)mask))
+			perror_exit(failed, "set", pid);
+	}
+}
+
+static int task_callback(struct dirtree *new)
+{
+	if (!new->parent) return DIRTREE_RECURSE;
+	if (isdigit(*new->name)) do_taskset(atoi(new->name), 0);
+
+	return 0;
+}
+
+void taskset_main(void)
+{
+	if (!(toys.optflags & FLAG_p)) {
+		if (toys.optc < 2) error_exit("Needs 2 args");
+		do_taskset(getpid(), 1);
+		xexec(toys.optargs+1);
+	} else {
+		char *c;
+		pid_t pid = strtol(toys.optargs[toys.optc-1], &c, 10);
+
+		if (*c) error_exit("Not int %s", toys.optargs[1]);
+
+		if (toys.optflags & FLAG_a) {
+			char buf[33];
+			sprintf(buf, "/proc/%ld/task/", (long)pid);
+			dirtree_read(buf, task_callback);
+		} else do_taskset(pid, 0);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/toysh.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,382 @@
+/* vi: set sw=4 ts=4:
+ *
+ * toysh - toybox shell
+ *
+ * Copyright 2006 Rob Landley <rob@landley.net>
+ *
+ * The spec for this is at:
+ * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
+ * and http://www.opengroup.org/onlinepubs/009695399/utilities/sh.html
+ *
+ * There are also specs for:
+ * http://www.opengroup.org/onlinepubs/009695399/utilities/cd.html
+ * http://www.opengroup.org/onlinepubs/009695399/utilities/exit.html
+ *
+ * Things like the bash man page are good to read too.
+ *
+ * TODO: // Handle embedded NUL bytes in the command line.
+
+USE_TOYSH(NEWTOY(cd, NULL, TOYFLAG_NOFORK))
+USE_TOYSH(NEWTOY(exit, NULL, TOYFLAG_NOFORK))
+USE_TOYSH(OLDTOY(sh, toysh, "c:i", TOYFLAG_BIN))
+USE_TOYSH(NEWTOY(toysh, "c:i", TOYFLAG_BIN))
+
+config TOYSH
+	bool "sh (toysh)"
+	default n
+	help
+	  usage: sh [-c command] [script]
+
+	  The toybox command shell.  Runs a shell script, or else reads input
+	  interactively and responds to it.
+
+	  -c	command line to execute
+
+config TOYSH_TTY
+	bool "Interactive shell (terminal control)"
+	default n
+	depends on TOYSH
+	help
+	  Add terminal control to toysh.  This is necessary for interactive use,
+	  so the shell isn't killed by CTRL-C.
+
+config TOYSH_PROFILE
+	bool "Profile support"
+	default n
+	depends on TOYSH_TTY
+	help
+	  Read /etc/profile and ~/.profile when running interactively.
+
+	  Also enables the built-in command "source".
+
+config TOYSH_JOBCTL
+	bool "Job Control (fg, bg, jobs)"
+	default n
+	depends on TOYSH_TTY
+	help
+	  Add job control to toysh.  This lets toysh handle CTRL-Z, and enables
+	  the built-in commands "fg", "bg", and "jobs".
+
+	  With pipe support, enable use of "&" to run background processes.
+
+config TOYSH_FLOWCTL
+	bool "Flow control (if, while, for, functions)"
+	default n
+	depends on TOYSH
+	help
+	  Add flow control to toysh.  This enables the if/then/else/fi,
+	  while/do/done, and for/do/done constructs.
+
+	  With pipe support, this enables the ability to define functions
+	  using the "function name" or "name()" syntax, plus curly brackets
+	  "{ }" to group commands.
+
+config TOYSH_QUOTES
+	bool "Smarter argument parsing (quotes)"
+	default n
+	depends on TOYSH
+	help
+	  Add support for parsing "" and '' style quotes to the toysh command
+	  parser, with lets arguments have spaces in them.
+
+config TOYSH_WILDCARDS
+	bool "Wildcards ( ?*{,} )"
+	default n
+	depends on TOYSH_QUOTES
+	help
+	  Expand wildcards in argument names, ala "ls -l *.t?z" and
+	  "rm subdir/{one,two,three}.txt".
+
+config TOYSH_PROCARGS
+	bool "Executable arguments ( `` and $() )"
+	default n
+	depends on TOYSH_QUOTES
+	help
+	  Add support for executing arguments contianing $() and ``, using
+	  the output of the command as the new argument value(s).
+
+	  (Bash calls this "command substitution".)
+
+config TOYSH_ENVVARS
+	bool "Environment variable support"
+	default n
+	depends on TOYSH_QUOTES
+	help
+	  Substitute environment variable values for $VARNAME or ${VARNAME},
+	  and enable the built-in command "export".
+
+config TOYSH_LOCALS
+	bool "Local variables"
+	default n
+	depends on TOYSH_ENVVARS
+	help
+	  Support for local variables, fancy prompts ($PS1), the "set" command,
+	  and $?.
+
+config TOYSH_ARRAYS
+	bool "Array variables"
+	default n
+	depends on TOYSH_LOCALS
+	help
+	  Support for ${blah[blah]} style array variables.
+
+config TOYSH_PIPES
+	bool "Pipes and redirects ( | > >> < << & && | || () ; )"
+	default n
+	depends on TOYSH
+	help
+	  Support multiple commands on the same command line.  This includes
+	  | pipes, > >> < redirects, << here documents, || && conditional
+	  execution, () subshells, ; sequential execution, and (with job
+	  control) & background processes.
+
+config TOYSH_BUILTINS
+	bool "Builtin commands"
+	default n
+	depends on TOYSH
+	help
+	  Adds the commands exec, fg, bg, help, jobs, pwd, export, source, set,
+	  unset, read, alias.
+
+config EXIT
+	bool
+	default n
+	depends on TOYSH
+	help
+	  usage: exit [status]
+
+	  Exit shell.  If no return value supplied on command line, use value
+	  of most recent command, or 0 if none.
+
+config CD
+	bool
+	default n
+	depends on TOYSH
+	help
+	  usage: cd [path]
+
+	  Change current directory.  With no arguments, go to $HOME.
+
+config CD_P
+	bool # "-P support for cd"
+	default n
+	depends on TOYSH
+	help
+	  usage: cd [-PL]
+
+	  -P    Physical path: resolve symlinks in path.
+	  -L    Cancel previous -P and restore default behavior.
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	char *command;
+)
+
+#define TT this.toysh
+
+// A single executable, its arguments, and other information we know about it.
+#define TOYSH_FLAG_EXIT    1
+#define TOYSH_FLAG_SUSPEND 2
+#define TOYSH_FLAG_PIPE    4
+#define TOYSH_FLAG_AND     8
+#define TOYSH_FLAG_OR      16
+#define TOYSH_FLAG_AMP     32
+#define TOYSH_FLAG_SEMI    64
+#define TOYSH_FLAG_PAREN   128
+
+// What we know about a single process.
+struct command {
+	struct command *next;
+	int flags;              // exit, suspend, && ||
+	int pid;                // pid (or exit code)
+	int argc;
+	char *argv[0];
+};
+
+// A collection of processes piped into/waiting on each other.
+struct pipeline {
+	struct pipeline *next;
+	int job_id;
+	struct command *cmd;
+	char *cmdline;         // Unparsed line for display purposes
+	int cmdlinelen;        // How long is cmdline?
+};
+
+// Parse one word from the command line, appending one or more argv[] entries
+// to struct command.  Handles environment variable substitution and
+// substrings.  Returns pointer to next used byte, or NULL if it
+// hit an ending token.
+static char *parse_word(char *start, struct command **cmd)
+{
+	char *end;
+
+	// Detect end of line (and truncate line at comment)
+	if (CFG_TOYSH_PIPES && strchr("><&|(;", *start)) return 0;
+
+	// Grab next word.  (Add dequote and envvar logic here)
+	end = start;
+	while (*end && !isspace(*end)) end++;
+	(*cmd)->argv[(*cmd)->argc++] = xstrndup(start, end-start);
+
+	// Allocate more space if there's no room for NULL terminator.
+
+	if (!((*cmd)->argc & 7))
+		*cmd=xrealloc(*cmd,
+				sizeof(struct command) + ((*cmd)->argc+8)*sizeof(char *));
+	(*cmd)->argv[(*cmd)->argc] = 0;
+	return end;
+}
+
+// Parse a line of text into a pipeline.
+// Returns a pointer to the next line.
+
+static char *parse_pipeline(char *cmdline, struct pipeline *line)
+{
+	struct command **cmd = &(line->cmd);
+	char *start = line->cmdline = cmdline;
+
+	if (!cmdline) return 0;
+
+	if (CFG_TOYSH_JOBCTL) line->cmdline = cmdline;
+
+	// Parse command into argv[]
+	for (;;) {
+		char *end;
+
+		// Skip leading whitespace and detect end of line.
+		while (isspace(*start)) start++;
+		if (!*start || *start=='#') {
+			if (CFG_TOYSH_JOBCTL) line->cmdlinelen = start-cmdline;
+			return 0;
+		}
+
+		// Allocate next command structure if necessary
+		if (!*cmd) *cmd = xzalloc(sizeof(struct command)+8*sizeof(char *));
+
+		// Parse next argument and add the results to argv[]
+		end = parse_word(start, cmd);
+
+		// If we hit the end of this command, how did it end?
+		if (!end) {
+			if (CFG_TOYSH_PIPES && *start) {
+				if (*start==';') {
+					start++;
+					break;
+				}
+				// handle | & < > >> << || &&
+			}
+			break;
+		}
+		start = end;
+	}
+
+	if (CFG_TOYSH_JOBCTL) line->cmdlinelen = start-cmdline;
+
+	return start;
+}
+
+// Execute the commands in a pipeline
+static void run_pipeline(struct pipeline *line)
+{
+	struct toy_list *tl;
+	struct command *cmd = line->cmd;
+	if (!cmd || !cmd->argc) return;
+
+	tl = toy_find(cmd->argv[0]);
+	// Is this command a builtin that should run in this process?
+	if (tl && (tl->flags & TOYFLAG_NOFORK)) {
+		struct toy_context temp;
+
+		// This fakes lots of what toybox_main() does.
+		memcpy(&temp, &toys, sizeof(struct toy_context));
+		memset(&toys, 0, sizeof(struct toy_context));
+		toy_init(tl, cmd->argv);
+		tl->toy_main();
+		cmd->pid = toys.exitval;
+		free(toys.optargs);
+		if (toys.old_umask) umask(toys.old_umask);
+		memcpy(&toys, &temp, sizeof(struct toy_context));
+	} else {
+		int status;
+
+		cmd->pid = vfork();
+		if (!cmd->pid) xexec(cmd->argv);
+		else waitpid(cmd->pid, &status, 0);
+
+		if (CFG_TOYSH_FLOWCTL || CFG_TOYSH_PIPES) {
+			if (WIFEXITED(status)) cmd->pid = WEXITSTATUS(status);
+			if (WIFSIGNALED(status)) cmd->pid = WTERMSIG(status);
+		}
+	}
+
+	return;
+}
+
+// Free the contents of a command structure
+static void free_cmd(void *data)
+{
+	struct command *cmd=(struct command *)data;
+
+	while(cmd->argc) free(cmd->argv[--cmd->argc]);
+}
+
+
+// Parse a command line and do what it says to do.
+static void handle(char *command)
+{
+	struct pipeline line;
+	char *start = command;
+
+	// Loop through commands in this line
+
+	for (;;) {
+
+		// Parse a group of connected commands
+
+		memset(&line,0,sizeof(struct pipeline));
+		start = parse_pipeline(start, &line);
+		if (!line.cmd) break;
+
+		// Run those commands
+
+		run_pipeline(&line);
+		llist_traverse(line.cmd, free_cmd);
+	}
+}
+
+void cd_main(void)
+{
+	char *dest = *toys.optargs ? *toys.optargs : getenv("HOME");
+	xchdir(dest);
+}
+
+void exit_main(void)
+{
+	exit(*toys.optargs ? atoi(*toys.optargs) : 0);
+}
+
+void toysh_main(void)
+{
+	FILE *f;
+
+	// Set up signal handlers and grab control of this tty.
+	if (CFG_TOYSH_TTY) {
+		if (isatty(0)) toys.optflags |= 1;
+	}
+	f = *toys.optargs ? xfopen(*toys.optargs, "r") : NULL;
+	if (TT.command) handle(TT.command);
+	else {
+		size_t cmdlen = 0;
+		for (;;) {
+			char *command = 0;
+			if (!f) xputc('$');
+			if (1 > getline(&command, &cmdlen, f ? f : stdin)) break;
+			handle(command);
+			free(command);
+		}
+	}
+
+	toys.exitval = 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/truncate.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,47 @@
+/* vi: set sw=4 ts=4:
+ *
+ * truncate.c - set file length, extending sparsely if necessary
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv4
+
+USE_TRUNCATE(NEWTOY(truncate, "<1s#|c", TOYFLAG_BIN))
+
+config TRUNCATE
+	bool "truncate"
+	default y
+	help
+	  usage: truncate [-c] -s file...
+	  Set length of file(s), extending sparsely if necessary.
+
+	  -c	Don't create file if it doesn't exist.
+	  -s	New size
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	long size;
+)
+
+#define TT this.truncate
+
+static void do_truncate(int fd, char *name)
+{
+	if (fd<0) return;
+	if (ftruncate(fd, TT.size)) {
+		perror_msg("failed to set '%s' to '%ld'", name, TT.size);
+		toys.exitval = EXIT_FAILURE;
+	}
+}
+
+void truncate_main(void)
+{
+	int cr = !(toys.optflags&1);
+
+	// Create files with mask rwrwrw.
+	// Nonexistent files are only an error if we're supposed to create them.
+	loopfiles_rw(toys.optargs, O_WRONLY|(cr ? O_CREAT : 0), 0666, cr,
+		do_truncate);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/unshare.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4:
+ *
+ * unshare.c - run command in new context
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv4.
+
+USE_UNSHARE(NEWTOY(unshare, "<1^nium", TOYFLAG_USR|TOYFLAG_BIN))
+
+config UNSHARE
+	bool "unshare"
+	default y
+	depends on TOYBOX_CONTAINER
+	help
+	  usage: unshare [-muin] COMMAND...
+
+	  Create new namespace(s) for this process and its children, so some
+	  attribute is not shared with the parent process.  This is part of
+	  Linux Containers.  Each process can have its own:
+
+	  -m	Mount/unmount tree
+	  -u	Host and domain names
+	  -i	SysV IPC (message queues, semaphores, shared memory)
+	  -n	Network address, sockets, routing, iptables
+*/
+
+#include "toys.h"
+#include <linux/sched.h>
+extern int unshare (int __flags);
+
+void unshare_main(void)
+{
+	unsigned flags[]={CLONE_NEWNS, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWNET,0};
+	unsigned f=0;
+	int i;
+
+	for (i=0; flags[i]; i++)
+		if (toys.optflags & (1<<i))
+			f |= flags[i];
+
+	if(unshare(f)) perror_exit("failed");
+
+	xexec(toys.optargs);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/uptime.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,52 @@
+/* vi: set sw=4 ts=4:
+ *
+ * uptime.c - Tell how long the system has been running.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_UPTIME(NEWTOY(uptime, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+
+config UPTIME
+	bool "uptime"
+	default y
+	help
+	  usage: uptime
+
+	  Tell how long the system has been running and the system load
+	  averages for the past 1, 5 and 15 minutes.
+*/
+
+#include "toys.h"
+
+void uptime_main(void)
+{
+	struct sysinfo info;
+	time_t tmptime;
+	struct tm * now;
+	unsigned int days, hours, minutes;
+
+	// Obtain the data we need.
+	sysinfo(&info);
+	time(&tmptime);
+	now = localtime(&tmptime);
+
+	// Time
+	xprintf(" %02d:%02d:%02d up ", now->tm_hour, now->tm_min, now->tm_sec);
+	// Uptime
+	info.uptime /= 60;
+	minutes = info.uptime%60;
+	info.uptime /= 60;
+	hours = info.uptime%24;
+	days = info.uptime/24;
+	if (days) xprintf("%d day%s, ", days, (days!=1)?"s":"");
+	if (hours)
+		xprintf("%2d:%02d, ", hours, minutes);
+	else
+		printf("%d min, ", minutes);
+
+	printf(" load average: %.02f %.02f %.02f\n", info.loads[0]/65536.0,
+		info.loads[1]/65536.0, info.loads[2]/65536.0);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/usleep.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4:
+ *
+ * usleep.c - Wait for a number of microseconds.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * No standard.
+
+USE_USLEEP(NEWTOY(usleep, "<1", TOYFLAG_BIN))
+
+config USLEEP
+	bool "usleep"
+	default y
+	help
+	  usage: usleep MICROSECONDS
+
+	  Pause for MICROSECONDS microseconds.
+
+*/
+
+#include "toys.h"
+
+void usleep_main(void)
+{
+    struct timespec tv;
+    long delay = atol(*toys.optargs);
+    
+    tv.tv_sec = delay/1000000;
+    tv.tv_nsec = (delay%1000000) * 1000;
+    toys.exitval = !!nanosleep(&tv, NULL);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/vmstat.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,191 @@
+/* vi: set sw=4 ts=4:
+ *
+ * vmstat.c - Report virtual memory statistics.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_VMSTAT(NEWTOY(vmstat, ">2n", TOYFLAG_BIN))
+
+config VMSTAT
+	bool "vmstat"
+	default y
+	help
+	  usage: vmstat [-n] [delay [count]]
+	  -n Display the header only once
+	  delay The delay between updates in seconds, when not specified
+	        the average since boot is displayed.
+	  count Number of updates to display, the default is inifinite.
+*/
+
+#include "toys.h"
+
+void read_proc_stat(unsigned int * proc_running, unsigned int * proc_blocked,
+		uint64_t * sys_irq, uint64_t * sys_ctxt,
+		uint64_t * cpu_user, uint64_t * cpu_sys, uint64_t * cpu_idle, uint64_t * cpu_wait)
+{
+	char * off;
+	uint64_t c_user, c_nice, c_sys, c_irq, c_sirq;
+	int fd = xopen("/proc/stat", O_RDONLY);
+	size_t s = xread(fd, toybuf, sizeof(toybuf)-1);
+	toybuf[s] = 0;
+	if ( s == sizeof(toybuf)-1)
+		error_exit("/proc/stat is too large");
+
+	off = strstr(toybuf, "cpu ");
+	// Ignoring steal and guest fields for now.
+	if (off) sscanf(off, "cpu  %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 \
+		" %"PRIu64" %"PRIu64" %"PRIu64, &c_user, &c_nice, &c_sys, cpu_idle,
+		cpu_wait, &c_irq, &c_sirq);
+	*cpu_user = c_user + c_nice;
+	*cpu_sys = c_sys + c_irq + c_sirq;
+	off = strstr(toybuf, "intr");
+	if (off) sscanf(off, "intr %"PRIu64, sys_irq);
+
+	off = strstr(toybuf, "ctxt");
+	if (off) sscanf(off, "ctxt %"PRIu64, sys_ctxt);
+
+	off = strstr(toybuf, "procs_running");
+	if (off) sscanf(off, "procs_running %u", proc_running);
+	(*proc_running)--; // look, i'm invisible.
+
+	off = strstr(toybuf, "procs_blocked");
+	if (off) sscanf(off, "procs_blocked %u", proc_blocked);
+
+	close(fd);
+}
+
+void read_proc_meminfo(unsigned long * mem_swapped, unsigned long * mem_free,
+			unsigned long * mem_buff, unsigned long * mem_cache)
+{
+	char * off;
+	unsigned long swap_total, swap_free;
+	int fd = xopen("/proc/meminfo", O_RDONLY);
+	size_t s = xread(fd, toybuf, sizeof(toybuf)-1);
+	toybuf[s] = 0;
+	if ( s == sizeof(toybuf)-1)
+		error_exit("/proc/meminfo is too large");
+
+	off = strstr(toybuf, "MemFree");
+	if (off) sscanf(off, "MemFree: %lu kB", mem_free);
+
+	off = strstr(toybuf, "Buffers");
+	if (off) sscanf(off, "Buffers: %lu kB", mem_buff);
+
+	off = strstr(toybuf, "Cached");
+	if (off) sscanf(off, "Cached: %lu kB", mem_cache);
+
+	off = strstr(toybuf, "SwapFree");
+	if (off) sscanf(off, "SwapFree: %lu kB", &swap_free); 
+
+	off = strstr(toybuf, "SwapTotal");
+	if (off) sscanf(off, "SwapTotal: %lu kB", &swap_total);
+	*mem_swapped = swap_total - swap_free;
+
+	close(fd);
+}
+
+void read_proc_vmstat(unsigned long * io_pages_in, unsigned long * io_pages_out,
+			unsigned long * swap_bytes_in, unsigned long * swap_bytes_out)
+{
+	char * off;
+	unsigned long s_pages_in, s_pages_out;
+	unsigned long pagesize_kb = sysconf(_SC_PAGESIZE) / 1024L;
+	int fd = xopen("/proc/vmstat", O_RDONLY);
+	size_t s = xread(fd, toybuf, sizeof(toybuf)-1);
+	toybuf[s] = 0;
+	if ( s == sizeof(toybuf)-1)
+		error_exit("/proc/vmstat is too large");
+
+	off = strstr(toybuf, "pgpgin");
+	if (off) sscanf(off, "pgpgin %lu", io_pages_in);
+
+	off = strstr(toybuf, "pgpgout");
+	if (off) sscanf(off, "pgpgout %lu", io_pages_out);
+
+	off = strstr(toybuf, "pswpin");
+	if (off) sscanf(off, "pswpin %lu", &s_pages_in);
+	*swap_bytes_in = s_pages_in * pagesize_kb;
+
+	off = strstr(toybuf, "pswpout");
+	if (off) sscanf(off, "pswpout %lu", &s_pages_out);
+	*swap_bytes_out = s_pages_out * pagesize_kb;
+
+	close(fd);
+}
+
+void vmstat_main(void)
+{
+	const char fmt[] = "%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n";
+	unsigned int loop_num = 0, loop_max_num = 0, loop_delay = 0;
+	unsigned int running = 0, blocked = 0;
+	unsigned long mem_swap = 0, mem_free = 0, mem_buff = 0, mem_cache = 0;
+	unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2];
+	uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2];
+	int first_run = 1;
+	int no_header = toys.optflags & 0x1;
+	unsigned num_rows = 22;
+
+	if (toys.optc >= 1)
+		loop_delay = atoi(toys.optargs[0]);
+	if (toys.optc >= 2)
+		loop_max_num = atoi(toys.optargs[1]);
+
+	if (loop_max_num < 0 || loop_delay < 0)
+		error_exit("Invalid arguments");
+
+	while(1) {
+		uint64_t total_jif;
+		int idx = loop_num%2;
+
+		if(first_run || (!(loop_num % num_rows) && !no_header)) {
+			unsigned rows = 0, cols = 0;
+			terminal_size(&cols, &rows);
+			num_rows = (rows > 3)? rows - 3 : 22;
+			printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n");
+			printf(" r  b   swpd   free   buff  cache   si   so	bi	bo   in   cs us sy id wa\n");
+		}
+
+		read_proc_stat(&running, &blocked, &sys_irq[idx], &sys_ctxt[idx], &cpu_user[idx],
+					   &cpu_sys[idx], &cpu_idle[idx], &cpu_wait[idx]);
+		read_proc_meminfo(&mem_swap, &mem_free, &mem_buff, &mem_cache);
+		read_proc_vmstat(&io_pages_in[idx], &io_pages_out[idx], &swap_bytes_in[idx], &swap_bytes_out[idx]);
+
+		if (first_run) {
+			struct sysinfo inf;
+			sysinfo(&inf);
+			first_run = 0;
+			total_jif = cpu_user[idx] + cpu_idle[idx] + cpu_wait[idx];
+			printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache,
+				   (unsigned) (swap_bytes_in[idx]/inf.uptime),
+				   (unsigned) (swap_bytes_out[idx]/inf.uptime),
+				   (unsigned) (io_pages_in[idx]/inf.uptime),
+				   (unsigned) (io_pages_out[idx]/inf.uptime),
+				   (unsigned) (sys_irq[idx]/inf.uptime),
+				   (unsigned) (sys_ctxt[idx]/inf.uptime),
+				   (unsigned) (100*cpu_user[idx]/total_jif),
+				   (unsigned) (100*cpu_sys[idx]/total_jif),
+				   (unsigned) (100*cpu_idle[idx]/total_jif),
+				   (unsigned) (100*cpu_wait[idx]/total_jif));
+		}else{
+			total_jif = cpu_user[idx] - cpu_user[!idx] + cpu_idle[idx] - cpu_idle[!idx] + cpu_wait[idx] - cpu_wait[!idx];
+			printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache,
+				   (unsigned) ((swap_bytes_in[idx] - swap_bytes_in[!idx])/loop_delay),
+				   (unsigned) ((swap_bytes_out[idx] - swap_bytes_out[!idx])/loop_delay),
+				   (unsigned) ((io_pages_in[idx] - io_pages_in[!idx])/loop_delay),
+				   (unsigned) ((io_pages_out[idx] - io_pages_out[!idx])/loop_delay),
+				   (unsigned) ((sys_irq[idx] - sys_irq[!idx])/loop_delay),
+				   (unsigned) ((sys_ctxt[idx] - sys_ctxt[!idx])/loop_delay),
+				   (unsigned) (100*(cpu_user[idx] - cpu_user[!idx])/total_jif),
+				   (unsigned) (100*(cpu_sys[idx]  - cpu_sys[!idx]) /total_jif),
+				   (unsigned) (100*(cpu_idle[idx] - cpu_idle[!idx])/total_jif),
+				   (unsigned) (100*(cpu_wait[idx] - cpu_wait[!idx])/total_jif));
+		}
+
+		loop_num++;
+		if (loop_delay == 0 || (loop_max_num != 0 && loop_num >= loop_max_num))
+			break;
+		sleep(loop_delay);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/w.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,36 @@
+/* vi: set sw=4 ts=4:
+ *
+ * w.c - shows logged in users
+ *
+ * Copyright 2012 Gaurang Shastri <gmshastri@gmail.com>
+ *
+ * Not in SUSv4.
+
+USE_W(NEWTOY(w, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+
+config W
+	bool "w"
+	default y
+	help
+	  usage: w 
+
+	  Show who is logged on and since how long they logged in.
+*/
+
+#include "toys.h"
+
+void w_main(void)
+{
+    struct utmpx *x;
+
+    xprintf("USER     TTY             LOGIN@              FROM");
+    setutxent();
+    while ((x=getutxent()) != NULL)
+        if (x->ut_type==7) {
+            time_t tt = x->ut_tv.tv_sec;
+
+            xprintf("\n%-9.8s%-9.8s %-4.24s (%-1.12s)", x->ut_user, x->ut_line,
+                ctime(&tt), x->ut_host);
+        }
+    xputc('\n');
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/which.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,71 @@
+/* vi: set sw=4 ts=4:
+ *
+ * which.c - Find executable files in $PATH.
+ *
+ * Copyright 2006 Rob landley <rob@landley.net>
+ *
+ * Not in SUSv3.
+
+USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
+
+config WHICH
+	bool "which"
+	default y
+	help
+	  usage: which [-a] filename ...
+
+	  Search $PATH for executable files matching filename(s).
+
+	  -a	Show all matches
+*/
+#include "toys.h"
+
+// Find an exectuable file either at a path with a slash in it (absolute or
+// relative to current directory), or in $PATH.  Returns absolute path to file,
+// or NULL if not found.
+
+static int which_in_path(char *filename)
+{
+	struct string_list *list;
+
+	// If they gave us a path, don't worry about $PATH or -a
+
+	if (strchr(filename, '/')) {
+		// Confirm it has the executable bit set, and it's not a directory.
+		if (!access(filename, X_OK)) {
+			struct stat st;
+
+			if (!stat(filename, &st) && S_ISREG(st.st_mode)) {
+				puts(filename);
+				return 0;
+			}
+			return 1;
+		}
+	}
+
+	// Search $PATH for matches.
+	list = find_in_path(getenv("PATH"), filename);
+	if (!list) return 1;
+
+	// Print out matches
+	while (list) {
+		if (!access(list->str, X_OK)) {
+			puts(list->str);
+			// If we should stop at one match, do so
+			if (!toys.optflags) {
+				llist_traverse(list, free);
+				break;
+			}
+		}
+		free(llist_pop(&list));
+	}
+
+	return 0;
+}
+
+void which_main(void)
+{
+	int i;
+	for (i=0; toys.optargs[i]; i++)
+		toys.exitval |= which_in_path(toys.optargs[i]);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/whoami.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4:
+ *
+ * whoami.c - Print effective user name
+ *
+ * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
+ *
+
+USE_WHOAMI(NEWTOY(whoami, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+
+config WHOAMI
+	bool "whoami"
+	default y
+	help
+	  usage: whoami
+
+	  Print effective user name.
+*/
+
+#include "toys.h"
+
+void whoami_main(void)
+{
+	struct passwd *pw = getpwuid(geteuid());
+
+	if (!pw) {
+		perror("getpwuid");
+		toys.exitval = 1;
+		return;
+	}
+
+	xputs(pw->pw_name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/yes.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,33 @@
+/* vi: set sw=4 ts=4:
+ *
+ * yes.c - Repeatedly output a string.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv3.
+
+USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+
+config YES
+	bool "yes"
+	default y
+	help
+	  usage: yes [args...]
+
+	  Repeatedly output line until killed.  If no args, output 'y'.
+*/
+
+#include "toys.h"
+
+void yes_main(void)
+{
+	for (;;) {
+		int i;
+		for (i=0; toys.optargs[i]; i++) {
+			if (i) xputc(' ');
+			xprintf("%s", toys.optargs[i]);
+		}
+		if (!i) xputc('y');
+		xputc('\n');
+	}
+}
--- a/toys/passwd.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * passwd.c - Program to upadte user password.
- *
- * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com>
- * Modified 2012 Jason Kyungwan Han <asura321@gmail.com>
- *
- * Not in SUSv4.
-
-USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
-
-config PASSWD
-	bool "passwd"
-	default y
-	help
-	  usage: passwd [-a ALGO] [-d] [-l] [-u] <account name>
-
-	  update user’s authentication tokens. Default : current user
-
-	  -a ALGO	Encryption method (des, md5, sha256, sha512) default: des
-	  -d		Set password to ''
-	  -l		Lock (disable) account
-	  -u 		Unlock (enable) account
-
-*/
-
-#include "toys.h"
-#include <time.h>
-
-
-DEFINE_GLOBALS(
-	char *algo;
-)
-
-#define TT this.passwd
-
-#define FLAG_u	(1 << 0)
-#define FLAG_l	(1 << 1)
-#define FLAG_d	(1 << 2)
-#define FLAG_a	(1 << 3)
-
-#define MAX_SALT_LEN  20 //3 for id, 16 for key, 1 for '\0'
-#define URANDOM_PATH    "/dev/urandom"
-
-#ifndef _GNU_SOURCE
-char *strcasestr(const char *haystack, const char *needle);
-#endif
-
-unsigned int random_number_generator(int fd)
-{
-    unsigned int randnum;
-    xreadall(fd, &randnum, sizeof(randnum));
-	return randnum;
-}
-
-
-
-char inttoc(int i)
-{
-	// salt value uses 64 chracters in "./0-9a-zA-Z"
-	const char character_set[]="./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-    i &= 0x3f; // masking for using 10 bits only
-	return character_set[i];
-}
-
-int get_salt(char *salt)
-{                     
-	int i, salt_length = 0;
-    int randfd;
-	if(!strncmp(TT.algo,"des",3)){
-		// 2 bytes salt value is used in des
-		salt_length = 2;
-	} else {
-		*salt++ = '$';
-		if(!strncmp(TT.algo,"md5",3)){
-			*salt++ = '1';
-			// 8 bytes salt value is used in md5
-			salt_length = 8;
-		} else if(!strncmp(TT.algo,"sha256",6)){
-			*salt++ = '5';
-			// 16 bytes salt value is used in sha256
-			salt_length = 16;
-		} else if(!strncmp(TT.algo,"sha512",6)){
-			*salt++ = '6';
-			// 16 bytes salt value is used in sha512
-			salt_length = 16;
-		} else return 1;
-
-		*salt++ = '$';
-	}
-
-    randfd = xopen(URANDOM_PATH, O_RDONLY);
-	for(i=0; i<salt_length; i++)
-		salt[i] = inttoc(random_number_generator(randfd));
-	salt[salt_length+1] = '\0';
-    xclose(randfd);
-
-	return 0;
-}
-
-static int str_check(char *s, char *p)
-{
-    if((strcasestr(s, p) != NULL) || (strcasestr(p, s) != NULL))
-        return 1;
-    return 0;
-}
-
-static void strength_check(char *newp, char *oldp, char *user)
-{
-    char *msg = NULL;
-    if(strlen(newp) < 6) { //Min passwd len
-        msg = "too short";
-        xprintf("BAD PASSWORD: %s\n",msg);
-    }
-    if(!newp[0])
-        return; //passwd is empty
-
-    if(str_check(newp, user)) {
-        msg = "user based password";
-        xprintf("BAD PASSWORD: %s\n",msg);
-    }
-
-    if(oldp[0] && str_check(newp, oldp)) {
-        msg = "based on old passwd";
-        xprintf("BAD PASSWORD: %s\n",msg);
-    }
-}
-
-static int verify_passwd(char * pwd)
-{    
-    char * pass;
-
-    if (!pwd) return 1;
-    if (pwd[0] == '!' || pwd[0] == '*') return 1;
-
-    pass = crypt(toybuf, pwd);
-    if (pass != NULL && strcmp(pass, pwd)==0)
-        return 0;
-
-    return 1;
-}
-
-static char *new_password(char *oldp, char *user)
-{
-    char *newp = NULL;
-
-    if(read_password(toybuf, sizeof(toybuf), "New password:"))
-        return NULL; //may be due to Ctrl-C
-
-    newp = xstrdup(toybuf);
-    strength_check(newp, oldp, user);
-    if(read_password(toybuf, sizeof(toybuf), "Retype password:")) {
-        free(newp);
-        return NULL; //may be due to Ctrl-C
-    }
-
-    if(strcmp(newp, toybuf) == 0)
-        return newp;
-    else error_msg("Passwords do not match.\n");
-    /*Failure Case */
-    free(newp);
-    return NULL;
-}
-
-
-void passwd_main(void)
-{
-    uid_t myuid;
-    struct passwd *pw;
-    struct spwd *sp;
-    char *name = NULL;
-    char *pass = NULL, *encrypted = NULL, *newp = NULL;
-    char *orig = (char *)"";
-    char salt[MAX_SALT_LEN];
-    int ret = -1;
-
-    myuid = getuid();
-    if((myuid != 0) && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d)))
-        error_exit("You need to be root to do these actions\n");
-
-    pw = getpwuid(myuid);
-
-    if(!pw)
-        error_exit("Unknown uid '%u'",myuid);
-
-    if(toys.optargs[0])
-        name = toys.optargs[0];
-    else
-        name = xstrdup(pw->pw_name);
-
-    pw = getpwnam(name);
-    if(!pw) error_exit("Unknown user '%s'",name);
-
-    if(myuid != 0 && (myuid != pw->pw_uid))
-        error_exit("You need to be root to change '%s' password\n", name);
-
-    pass = pw->pw_passwd;
-    if(pw->pw_passwd[0] == 'x') {
-        /*get shadow passwd */
-        sp = getspnam(name);
-        if(sp)
-            pass = sp->sp_pwdp;
-    }
-
-
-    if(!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) {
-        printf("Changing password for %s\n",name);
-        if(pass[0] == '!') 
-            error_exit("Can't change, password is locked for %s",name);
-        if(myuid != 0) {
-            /*Validate user */
-
-            if(read_password(toybuf, sizeof(toybuf), "Origial password:")) {
-                if(!toys.optargs[0]) free(name);
-                return;
-            }
-            orig = toybuf;
-            if(verify_passwd(pass))
-                error_exit("Authentication failed\n");
-        }
-
-        orig = xstrdup(orig);
-
-        /*Get new password */
-        newp = new_password(orig, name);
-        if(!newp) {
-            free(orig);
-            if(!toys.optargs[0]) free(name);
-            return; //new password is not set well.
-        }
-
-        /*Encrypt the passwd */
-        if(!(toys.optflags & FLAG_a)) TT.algo = "des";
-
-		if(get_salt(salt))
-			error_exit("Error: Unkown encryption algorithm\n");
-		
-        encrypted = crypt(newp, salt);
-        free(newp);
-        free(orig);
-    }
-    else if(toys.optflags & FLAG_l) {
-        if(pass[0] == '!')
-            error_exit("password is already locked for %s",name);
-        printf("Locking password for %s\n",name);
-        encrypted = xmsprintf("!%s",pass);
-    }
-    else if(toys.optflags & FLAG_u) {
-        if(pass[0] != '!')         
-            error_exit("password is already unlocked for %s",name);
-
-        printf("Unlocking password for %s\n",name);
-        encrypted = xstrdup(&pass[1]);
-    }
-    else if(toys.optflags & FLAG_d) {
-        printf("Deleting password for %s\n",name);
-        encrypted = (char*)xzalloc(sizeof(char)*2); //1 = "", 2 = '\0'
-    }
-
-    /*Update the passwd */
-    if(pw->pw_passwd[0] == 'x')
-        ret = update_password("/etc/shadow", name, encrypted);
-    else
-        ret = update_password("/etc/passwd", name, encrypted);
-
-    if((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) 
-        free(encrypted);
-
-    if(!toys.optargs[0]) free(name);
-    if(!ret)
-        error_msg("Success");
-    else
-        error_msg("Failure");
-}
--- a/toys/patch.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,412 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * patch.c - Apply a "universal" diff.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * see http://www.opengroup.org/onlinepubs/009695399/utilities/patch.html
- * (But only does -u, because who still cares about "ed"?)
- *
- * TODO:
- * -b backup
- * -l treat all whitespace as a single space
- * -N ignore already applied
- * -d chdir first
- * -D define wrap #ifdef and #ifndef around changes
- * -o outfile output here instead of in place
- * -r rejectfile write rejected hunks to this file
- *
- * -E remove empty files --remove-empty-files
- * -f force (no questions asked)
- * -F fuzz (number, default 2)
- * [file] which file to patch
-
-USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"up#i:R", TOYFLAG_USR|TOYFLAG_BIN))
-
-config PATCH
-	bool "patch"
-	default y
-	help
-	  usage: patch [-i file] [-p depth] [-Ru]
-
-	  Apply a unified diff to one or more files.
-
-	  -i	Input file (defaults=stdin)
-	  -p	number of '/' to strip from start of file paths (default=all)
-	  -R	Reverse patch.
-	  -u	Ignored (only handles "unified" diffs)
-
-	  This version of patch only handles unified diffs, and only modifies
-	  a file when all all hunks to that file apply.  Patch prints failed
-	  hunks to stderr, and exits with nonzero status if any hunks fail.
-
-	  A file compared against /dev/null (or with a date <= the epoch) is
-	  created/deleted as appropriate.
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	char *infile;
-	long prefix;
-
-	struct double_list *current_hunk;
-	long oldline, oldlen, newline, newlen;
-	long linenum;
-	int context, state, filein, fileout, filepatch, hunknum;
-	char *tempname;
-)
-
-#define TT this.patch
-
-#define FLAG_REVERSE 1
-#define FLAG_PATHLEN 4
-
-// Dispose of a line of input, either by writing it out or discarding it.
-
-// state < 2: just free
-// state = 2: write whole line to stderr
-// state = 3: write whole line to fileout
-// state > 3: write line+1 to fileout when *line != state
-
-#define PATCH_DEBUG (CFG_TOYBOX_DEBUG && (toys.optflags & 16))
-
-static void do_line(void *data)
-{
-	struct double_list *dlist = (struct double_list *)data;
-
-	if (TT.state>1 && *dlist->data != TT.state) {
-		char *s = dlist->data+(TT.state>3 ? 1 : 0);
-		int i = TT.state == 2 ? 2 : TT.fileout;
-
-		xwrite(i, s, strlen(s));
-		xwrite(i, "\n", 1);
-	}
-
-	if (PATCH_DEBUG) fprintf(stderr, "DO %d: %s\n", TT.state, dlist->data);
-
-	free(dlist->data);
-	free(data);
-}
-
-static void finish_oldfile(void)
-{
-	if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname);
-	TT.fileout = TT.filein = -1;
-}
-
-static void fail_hunk(void)
-{
-	if (!TT.current_hunk) return;
-	TT.current_hunk->prev->next = 0;
-
-	fprintf(stderr, "Hunk %d FAILED %ld/%ld.\n",
-			TT.hunknum, TT.oldline, TT.newline);
-	toys.exitval = 1;
-
-	// If we got to this point, we've seeked to the end.  Discard changes to
-	// this file and advance to next file.
-
-	TT.state = 2;
-	llist_traverse(TT.current_hunk, do_line);
-	TT.current_hunk = NULL;
-	delete_tempfile(TT.filein, TT.fileout, &TT.tempname);
-	TT.state = 0;
-}
-
-// Given a hunk of a unified diff, make the appropriate change to the file.
-// This does not use the location information, but instead treats a hunk
-// as a sort of regex.  Copies data from input to output until it finds
-// the change to be made, then outputs the changed data and returns.
-// (Finding EOF first is an error.)  This is a single pass operation, so
-// multiple hunks must occur in order in the file.
-
-static int apply_one_hunk(void)
-{
-	struct double_list *plist, *buf = NULL, *check;
-	int matcheof = 0, reverse = toys.optflags & FLAG_REVERSE, backwarn = 0;
-
-	// Break doubly linked list so we can use singly linked traversal function.
-	TT.current_hunk->prev->next = NULL;
-
-	// Match EOF if there aren't as many ending context lines as beginning
-	for (plist = TT.current_hunk; plist; plist = plist->next) {
-		if (plist->data[0]==' ') matcheof++;
-		else matcheof = 0;
-		if (PATCH_DEBUG) fprintf(stderr, "HUNK:%s\n", plist->data);
-	}
-	matcheof = matcheof < TT.context;
-
-	if (PATCH_DEBUG) fprintf(stderr,"MATCHEOF=%c\n", matcheof ? 'Y' : 'N');
-
-	// Loop through input data searching for this hunk.  Match all context
-	// lines and all lines to be removed until we've found the end of a
-	// complete hunk.
-	plist = TT.current_hunk;
-	buf = NULL;
-	if (TT.context) for (;;) {
-		char *data = get_line(TT.filein);
-
-		TT.linenum++;
-
-		// Figure out which line of hunk to compare with next.  (Skip lines
-		// of the hunk we'd be adding.)
-		while (plist && *plist->data == "+-"[reverse]) {
-			if (data && !strcmp(data, plist->data+1)) {
-				if (!backwarn) backwarn = TT.linenum;
-			}
-			plist = plist->next;
-		}
-
-		// Is this EOF?
-		if (!data) {
-			if (PATCH_DEBUG) fprintf(stderr, "INEOF\n");
-
-			// Does this hunk need to match EOF?
-			if (!plist && matcheof) break;
-
-			if (backwarn)
-				fprintf(stderr, "Possibly reversed hunk %d at %ld\n",
-						TT.hunknum, TT.linenum);
-
-			// File ended before we found a place for this hunk.
-			fail_hunk();
-			goto done;
-		} else if (PATCH_DEBUG) fprintf(stderr, "IN: %s\n", data);
-		check = dlist_add(&buf, data);
-
-		// Compare this line with next expected line of hunk.
-		// todo: teach the strcmp() to ignore whitespace.
-
-		// A match can fail because the next line doesn't match, or because
-		// we hit the end of a hunk that needed EOF, and this isn't EOF.
-
-		// If match failed, flush first line of buffered data and
-		// recheck buffered data for a new match until we find one or run
-		// out of buffer.
-
-		for (;;) {
-			if (!plist || strcmp(check->data, plist->data+1)) {
-				// Match failed.  Write out first line of buffered data and
-				// recheck remaining buffered data for a new match.
-	
-				if (PATCH_DEBUG)
-					fprintf(stderr, "NOT: %s\n", plist->data);
-
-				TT.state = 3;
-				check = llist_pop(&buf);
-				check->prev->next = buf;
-				buf->prev = check->prev;
-				do_line(check);
-				plist = TT.current_hunk;
-
-				// If we've reached the end of the buffer without confirming a
-				// match, read more lines.
-				if (check==buf) {
-					buf = 0;
-					break;
-				}
-				check = buf;
-			} else {
-				if (PATCH_DEBUG)
-					fprintf(stderr, "MAYBE: %s\n", plist->data);
-				// This line matches.  Advance plist, detect successful match.
-				plist = plist->next;
-				if (!plist && !matcheof) goto out;
-				check = check->next;
-				if (check == buf) break;
-			}
-		}
-	}
-out:
-	// We have a match.  Emit changed data.
-	TT.state = "-+"[reverse];
-	llist_traverse(TT.current_hunk, do_line);
-	TT.current_hunk = NULL;
-	TT.state = 1;
-done:
-	if (buf) {
-		buf->prev->next = NULL;
-		llist_traverse(buf, do_line);
-	}
-
-	return TT.state;
-}
-
-// Read a patch file and find hunks, opening/creating/deleting files.
-// Call apply_one_hunk() on each hunk.
-
-// state 0: Not in a hunk, look for +++.
-// state 1: Found +++ file indicator, look for @@
-// state 2: In hunk: counting initial context lines
-// state 3: In hunk: getting body
-
-void patch_main(void)
-{
-	int reverse = toys.optflags&FLAG_REVERSE, state = 0, patchlinenum = 0,
-		strip = 0;
-	char *oldname = NULL, *newname = NULL;
-
-	if (TT.infile) TT.filepatch = xopen(TT.infile, O_RDONLY);
-	TT.filein = TT.fileout = -1;
-
-	// Loop through the lines in the patch
-	for (;;) {
-		char *patchline;
-
-		patchline = get_line(TT.filepatch);
-		if (!patchline) break;
-
-		// Other versions of patch accept damaged patches,
-		// so we need to also.
-		if (strip || !patchlinenum++) {
-			int len = strlen(patchline);
-			if (patchline[len-1] == '\r') {
-				if (!strip) fprintf(stderr, "Removing DOS newlines\n");
-				strip = 1;
-				patchline[len-1]=0;
-			}
-		}
-		if (!*patchline) {
-			free(patchline);
-			patchline = xstrdup(" ");
-		}
-
-		// Are we assembling a hunk?
-		if (state >= 2) {
-			if (*patchline==' ' || *patchline=='+' || *patchline=='-') {
-				dlist_add(&TT.current_hunk, patchline);
-
-				if (*patchline != '+') TT.oldlen--;
-				if (*patchline != '-') TT.newlen--;
-
-				// Context line?
-				if (*patchline==' ' && state==2) TT.context++;
-				else state=3;
-
-				// If we've consumed all expected hunk lines, apply the hunk.
-
-				if (!TT.oldlen && !TT.newlen) state = apply_one_hunk();
-				continue;
-			}
-			fail_hunk();
-			state = 0;
-			continue;
-		}
-
-		// Open a new file?
-		if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) {
-			char *s, **name = &oldname;
-			int i;
-
-			if (*patchline == '+') {
-				name = &newname;
-				state = 1;
-			}
-
-			free(*name);
-			finish_oldfile();
-
-			// Trim date from end of filename (if any).  We don't care.
-			for (s = patchline+4; *s && *s!='\t'; s++)
-				if (*s=='\\' && s[1]) s++;
-			i = atoi(s);
-			if (i>1900 && i<=1970)
-				*name = xstrdup("/dev/null");
-			else {
-				*s = 0;
-				*name = xstrdup(patchline+4);
-			}
-
-			// We defer actually opening the file because svn produces broken
-			// patches that don't signal they want to create a new file the
-			// way the patch man page says, so you have to read the first hunk
-			// and _guess_.
-
-		// Start a new hunk?  Usually @@ -oldline,oldlen +newline,newlen @@
-		// but a missing ,value means the value is 1.
-		} else if (state == 1 && !strncmp("@@ -", patchline, 4)) {
-			int i;
-			char *s = patchline+4;
-
-			// Read oldline[,oldlen] +newline[,newlen]
-
-			TT.oldlen = TT.newlen = 1;
-			TT.oldline = strtol(s, &s, 10);
-			if (*s == ',') TT.oldlen=strtol(s+1, &s, 10);
-			TT.newline = strtol(s+2, &s, 10);
-			if (*s == ',') TT.newlen = strtol(s+1, &s, 10);
-
-			TT.context = 0;
-			state = 2;
-
-			// If this is the first hunk, open the file.
-			if (TT.filein == -1) {
-				int oldsum, newsum, del = 0;
-				char *name;
-
- 				oldsum = TT.oldline + TT.oldlen;
-				newsum = TT.newline + TT.newlen;
-
-				name = reverse ? oldname : newname;
-
-				// We're deleting oldname if new file is /dev/null (before -p)
-				// or if new hunk is empty (zero context) after patching
-				if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum))
-				{
-					name = reverse ? newname : oldname;
-					del++;
-				}
-
-				// handle -p path truncation.
-				for (i = 0, s = name; *s;) {
-					if ((toys.optflags & FLAG_PATHLEN) && TT.prefix == i) break;
-					if (*s++ != '/') continue;
-					while (*s == '/') s++;
-					name = s;
-					i++;
-				}
-
-				if (del) {
-					printf("removing %s\n", name);
-					xunlink(name);
-					state = 0;
-				// If we've got a file to open, do so.
-				} else if (!(toys.optflags & FLAG_PATHLEN) || i <= TT.prefix) {
-					// If the old file was null, we're creating a new one.
-					if (!strcmp(oldname, "/dev/null") || !oldsum) {
-						printf("creating %s\n", name);
-						s = strrchr(name, '/');
-						if (s) {
-							*s = 0;
-							xmkpath(name, -1);
-							*s = '/';
-						}
-						TT.filein = xcreate(name, O_CREAT|O_EXCL|O_RDWR, 0666);
-					} else {
-						printf("patching %s\n", name);
-						TT.filein = xopen(name, O_RDWR);
-					}
-					TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname);
-					TT.linenum = 0;
-					TT.hunknum = 0;
-				}
-			}
-
-			TT.hunknum++;
-
-			continue;
-		}
-
-		// If we didn't continue above, discard this line.
-		free(patchline);
-	}
-
-	finish_oldfile();
-
-	if (CFG_TOYBOX_FREE) {
-		close(TT.filepatch);
-		free(oldname);
-		free(newname);
-	}
-}
--- a/toys/pidof.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * pidof.c - Print the PIDs of all processes with the given names.
- *
- * Copyright 2012 Andreas Heck <aheck@gmx.de>
- *
- * Not in SUSv4.
-
-USE_PIDOF(NEWTOY(pidof, "<1", TOYFLAG_USR|TOYFLAG_BIN))
-
-config PIDOF
-	bool "pidof"
-	default y
-	help
-	  usage: pidof [NAME]...
-
-	  Print the PIDs of all processes with the given names.
-*/
-
-#include "toys.h"
-
-static void print_pid(pid_t pid) {
-    xprintf("%s%ld", toys.exitval ? "" : " ", (long)pid);
-    toys.exitval = 0;
-}
-
-void pidof_main(void)
-{
-    toys.exitval = 1;
-    for_each_pid_with_name_in(toys.optargs, print_pid);
-    if (!toys.exitval) xputc('\n');
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/basename.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4:
+ *
+ * basename.c - Return non-directory portion of a pathname
+ *
+ * Copyright 2012 Tryn Mirell <tryn@mirell.org>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/basename.html
+
+
+USE_BASENAME(NEWTOY(basename, "<1>2", TOYFLAG_USR|TOYFLAG_BIN))
+
+config BASENAME
+	bool "basename"
+	default y
+	help
+        usage: basename string [suffix]
+
+        Return non-directory portion of a pathname removing suffix
+*/
+
+#include "toys.h"
+
+void basename_main(void)
+{
+    char *arg = toys.optargs[0], *suffix = toys.optargs[1], *base;
+
+    while ((base = strrchr(arg, '/'))) {
+        if (base == arg) break;
+        if (!base[1]) *base = 0;
+        else {
+            base++;
+            break;
+        }
+    }
+
+    if (!base) base = arg;
+    
+    // chop off the suffix if provided
+    if (suffix) {
+        arg = base + strlen(base) - strlen(suffix);
+        if (arg > base && !strcmp(arg, suffix)) *arg = 0;
+    }
+ 
+    puts(base);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/cal.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,134 @@
+/* vi: set sw=4 ts=4:
+ *
+ * cal.c - show calendar.
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/cal.html
+
+USE_CAL(NEWTOY(cal, ">2", TOYFLAG_USR|TOYFLAG_BIN))
+
+config CAL
+	bool "cal"
+	default y
+	help
+	  usage: cal [[month] year]
+	  Print a calendar.
+
+	  With one argument, prints all months of the specified year.
+	  With two arguments, prints calendar for month and year.
+*/
+
+#include "toys.h"
+
+// Write calendar into buffer: each line is 20 chars wide, end indicated
+// by empty string.
+
+static char *calstrings(char *buf, struct tm *tm)
+{
+	char temp[21];
+	int wday, mday, start, len, line;
+
+	// header
+	len = strftime(temp, 21, "%B %Y", tm);
+	len += (20-len)/2;
+	buf += sprintf(buf, "%*s%*s ", len, temp, 20-len, "");
+	buf++;
+	buf += sprintf(buf, "Su Mo Tu We Th Fr Sa ");
+	buf++;
+
+	// What day of the week does this month start on?
+	if (tm->tm_mday>1)
+		start = (36+tm->tm_wday-tm->tm_mday)%7;
+	else start = tm->tm_wday;
+
+	// What day does this month end on?  Alas, libc doesn't tell us...
+	len = 31;
+	if (tm->tm_mon == 1) {
+		int year = tm->tm_year;
+		len = 28;
+		if (!(year & 3) && !((year&100) && !(year&400))) len++;
+	} else if ((tm->tm_mon+(tm->tm_mon>6 ? 1 : 0)) & 1) len = 30;
+
+	for (mday=line=0;line<6;line++) {
+		for (wday=0; wday<7; wday++) {
+			char *pat = "   ";
+			if (!mday ? wday==start : mday<len) {
+				pat = "%2d ";
+				mday++;
+			}
+			buf += sprintf(buf, pat, mday);
+		}
+		buf++;
+	}
+
+	return buf;
+}
+
+void xcheckrange(long val, long low, long high)
+{
+	char *err = "%ld %s than %ld";
+
+	if (val < low) error_exit(err, val, "less", low);
+	if (val > high) error_exit(err, val, "greater", high);
+}
+
+// Worst case scenario toybuf usage: sizeof(struct tm) plus 21 bytes/line
+// plus 8 lines/month plus 12 months, comes to a bit over 2k of our 4k buffer.
+
+void cal_main(void)
+{
+	struct tm *tm;
+	char *buf = toybuf;
+
+	if (toys.optc) {
+		// Conveniently starts zeroed
+		tm = (struct tm *)toybuf;
+		buf += sizeof(struct tm);
+
+		// Last argument is year, one before that (if any) is month.
+		xcheckrange(tm->tm_year = atol(toys.optargs[--toys.optc]),1,9999);
+		tm->tm_year -= 1900;
+		tm->tm_mday = 1;
+		tm->tm_hour = 12;  // noon to avoid timezone weirdness
+		if (toys.optc) {
+			xcheckrange(tm->tm_mon = atol(toys.optargs[--toys.optc]),1,12);
+			tm->tm_mon--;
+
+		// Print 12 months of the year
+
+		} else {
+			char *bufs[12];
+			int i, j, k;
+
+			for (i=0; i<12; i++) {
+				tm->tm_mon=i;
+				mktime(tm);
+				buf = calstrings(bufs[i]=buf, tm);
+			}
+
+			// 4 rows, 6 lines each, 3 columns
+			for (i=0; i<4; i++) {
+				for (j=0; j<8; j++) {
+					for(k=0; k<3; k++) {
+						char **b = bufs+(k+i*3);
+						*b += printf("%s ", *b);
+					}
+					puts("");
+				}
+			}
+			return;
+		}
+
+		// What day of the week does that start on?
+		mktime(tm);
+
+	} else {
+		time_t now;
+		time(&now);
+		tm = localtime(&now);
+	}
+
+	calstrings(buf, tm);
+	while (*buf) buf += printf("%s\n", buf);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/cat.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,42 @@
+/* vi: set sw=4 ts=4:
+ *
+ * cat.c - copy inputs to stdout.
+ *
+ * Copyright 2006 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/cat.html
+
+USE_CAT(NEWTOY(cat, "u", TOYFLAG_BIN))
+
+config CAT
+	bool "cat"
+	default y
+	help
+	  usage: cat [-u] [file...]
+	  Copy (concatenate) files to stdout.  If no files listed, copy from stdin.
+	  Filename "-" is a synonym for stdin.
+
+	  -u	Copy one byte at a time (slow).
+*/
+
+#include "toys.h"
+
+static void do_cat(int fd, char *name)
+{
+	int len, size=toys.optflags ? 1 : sizeof(toybuf);
+
+	for (;;) {
+		len = read(fd, toybuf, size);
+		if (len<0) {
+			perror_msg("%s",name);
+			toys.exitval = EXIT_FAILURE;
+		}
+		if (len<1) break;
+		xwrite(1, toybuf, len);
+	}
+}
+
+void cat_main(void)
+{
+	loopfiles(toys.optargs, do_cat);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/chgrp.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,124 @@
+/* vi: set sw=4 ts=4:
+ *
+ * chown.c - Change ownership
+ *
+ * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/chown.html
+ * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/chgrp.html
+ *
+ * TODO: group only one of [HLP]
+
+USE_CHGRP(NEWTOY(chgrp, "<2hPLHRfv", TOYFLAG_BIN))
+USE_CHGRP(OLDTOY(chown, chgrp, "<2hPLHRfv", TOYFLAG_BIN))
+
+config CHGRP
+	bool "chgrp/chown"
+	default y
+	help
+	  usage: chown [-RHLP] [-fvh] [owner][:group] file...
+	  usage: chgrp [-RHLP] [-fvh] group file...
+
+	  Change ownership of one or more files.
+
+	  -f	suppress most error messages.
+	  -h	change symlinks instead of what they point to
+	  -R	recurse into subdirectories (implies -h).
+  	  -H	with -R change target of symlink, follow command line symlinks
+	  -L	with -R change target of symlink, follow all symlinks
+	  -P	with -R change symlink, do not follow symlinks (default)
+	  -v	verbose output.
+*/
+
+#include "toys.h"
+
+#define FLAG_v 1
+#define FLAG_f 2
+#define FLAG_R 4
+#define FLAG_H 8
+#define FLAG_L 16
+#define FLAG_P 32
+#define FLAG_h 64
+
+DEFINE_GLOBALS(
+	uid_t owner;
+	gid_t group;
+	char *owner_name, *group_name;
+	int symfollow;
+)
+
+#define TT this.chgrp
+
+static int do_chgrp(struct dirtree *node)
+{
+	int fd, ret, flags = toys.optflags;
+
+	// Depth first search
+	if (!dirtree_notdotdot(node)) return 0;
+	if ((flags & FLAG_R) && node->data != -1 && S_ISDIR(node->st.st_mode))
+		return DIRTREE_COMEAGAIN|((flags&FLAG_L) ? DIRTREE_SYMFOLLOW : 0);
+
+	fd = dirtree_parentfd(node);
+	ret = fchownat(fd, node->name, TT.owner, TT.group,
+		(flags&(FLAG_L|FLAG_H)) || !(flags&(FLAG_h|FLAG_R))
+			? 0 : AT_SYMLINK_NOFOLLOW);
+
+	if (ret || (flags & FLAG_v)) {
+		char *path = dirtree_path(node, 0);
+		if (flags & FLAG_v)
+			xprintf("%s %s%s%s %s\n", toys.which->name,
+				TT.owner_name ? TT.owner_name : "",
+				toys.which->name[2]=='o' && TT.group_name ? ":" : "",
+				TT.group_name ? TT.group_name : "", path);
+		if (ret == -1 && !(toys.optflags & FLAG_f))
+			perror_msg("changing owner:group of '%s' to '%s:%s'", path,
+				TT.owner_name, TT.group_name);
+		free(path);
+	}
+	toys.exitval |= ret;
+
+	return 0;
+}
+
+void chgrp_main(void)
+{
+	int ischown = toys.which->name[2] == 'o';
+	char **s, *own;
+
+	// Distinguish chown from chgrp
+	if (ischown) {
+		char *grp;
+		struct passwd *p;
+
+		own = xstrdup(*toys.optargs);
+		if ((grp = strchr(own, ':')) || (grp = strchr(own, '.'))) {
+			*(grp++) = 0;
+			TT.group_name = grp;
+		}
+		if (*own) {
+			TT.owner_name = own;
+			p = getpwnam(own);
+			// TODO: trailing garbage?
+			if (!p && isdigit(*own)) p=getpwuid(atoi(own));
+			if (!p) error_exit("no user '%s'", own);
+			TT.owner = p->pw_uid;
+		}
+	} else TT.group_name = *toys.optargs;
+
+	if (TT.group_name) {
+		struct group *g;
+		g = getgrnam(TT.group_name);
+		if (!g) g=getgrgid(atoi(TT.group_name));
+		if (!g) error_exit("no group '%s'", TT.group_name);
+		TT.group = g->gr_gid;
+	}
+
+	for (s=toys.optargs+1; *s; s++) {
+		struct dirtree *new = dirtree_add_node(AT_FDCWD, *s,
+			toys.optflags&(FLAG_H|FLAG_L));
+		if (new) handle_callback(new, do_chgrp);
+		else toys.exitval = 1;
+	}
+
+	if (CFG_TOYBOX_FREE) free(own);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/chmod.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,72 @@
+/* vi: set sw=4 ts=4:
+ *
+ * chmod.c - Change file mode bits
+ *
+ * Copyright 2012 Rob Landley <rob@landley.net>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/chmod.html
+ *
+
+USE_CHMOD(NEWTOY(chmod, "<2?vR", TOYFLAG_BIN))
+
+config CHMOD
+    bool "chmod"
+    default y
+    help
+        usage: chmod [-R] MODE FILE...
+
+        Change mode of listed file[s] (recursively with -R).
+
+        MODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo]
+
+        Stanzas are applied in order: For each category (u = user,
+        g = group, o = other, a = all three, if none specified default is a),
+        set (+), clear (-), or copy (=), r = read, w = write, x = execute.
+        s = u+s = suid, g+s = sgid, o+s = sticky. (+t is an alias for o+s).
+        suid/sgid: execute as the user/group who owns the file.
+        sticky: can't delete files you don't own out of this directory
+        X = x for directories or if any category already has x set.
+
+        Or MODE can be an octal value up to 7777	ug uuugggooo	top +
+        bit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1	sstrwxrwxrwx	bottom
+
+        Examples:
+        chmod u+w file - allow owner of "file" to write to it.
+        chmod 744 file - user can read/write/execute, everyone else read only
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+    char *mode;
+)
+
+#define TT this.chmod
+
+#define FLAG_R 1
+#define FLAG_v 2
+
+int do_chmod(struct dirtree *try)
+{
+    mode_t mode;
+
+    if (!dirtree_notdotdot(try)) return 0;
+
+    mode = string_to_mode(TT.mode, try->st.st_mode);
+    if (toys.optflags & FLAG_v) {
+        char *s = dirtree_path(try, 0);
+        printf("chmod '%s' to %04o\n", s, mode);
+        free(s);
+    }
+    wfchmodat(dirtree_parentfd(try), try->name, mode);
+
+    return (toys.optflags & FLAG_R) ? DIRTREE_RECURSE : 0;
+}
+
+void chmod_main(void)
+{
+    TT.mode = *toys.optargs;
+    char **file;
+
+    for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chmod);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/cksum.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,87 @@
+/* vi: set sw=4 ts=4:
+ *
+ * cksum.c - produce crc32 checksum value for each input
+ *
+ * Copyright 2008 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/cksum.html
+
+USE_CKSUM(NEWTOY(cksum, "IPLN", TOYFLAG_BIN))
+
+config CKSUM
+	bool "cksum"
+	default y
+	help
+	  usage: cksum [-IPLN] [file...]
+
+	  For each file, output crc32 checksum value, length and name of file.
+	  If no files listed, copy from stdin.  Filename "-" is a synonym for stdin.
+
+	  -L	Little endian (defaults to big endian)
+	  -P	Pre-inversion
+	  -I	Skip post-inversion
+	  -N	Do not include length in CRC calculation
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	unsigned crc_table[256];
+)
+
+#define TT this.cksum
+
+static unsigned cksum_be(unsigned crc, unsigned char c)
+{
+	return (crc<<8)^TT.crc_table[(crc>>24)^c];
+}
+
+static unsigned cksum_le(unsigned crc, unsigned char c)
+{
+	return TT.crc_table[(crc^c)&0xff] ^ (crc>>8);
+}
+
+static void do_cksum(int fd, char *name)
+{
+	unsigned crc = (toys.optflags&4) ? 0xffffffff : 0;
+	uint64_t llen = 0, llen2;
+	unsigned (*cksum)(unsigned crc, unsigned char c);
+
+
+	cksum = (toys.optflags&2) ? cksum_le : cksum_be;
+	// CRC the data
+
+	for (;;) {
+		int len, i;
+
+		len = read(fd, toybuf, sizeof(toybuf));
+		if (len<0) {
+			perror_msg("%s",name);
+			toys.exitval = EXIT_FAILURE;
+		}
+		if (len<1) break;
+
+		llen += len;
+		for (i=0; i<len; i++) crc=cksum(crc, toybuf[i]);
+	}
+
+	// CRC the length
+
+	llen2 = llen;
+	if (!(toys.optflags&1)) {
+		while (llen) {
+			crc = cksum(crc, llen);
+			llen >>= 8;
+		}
+	}
+
+	printf("%u %"PRIu64, (toys.optflags&8) ? crc : ~crc, llen2);
+	if (strcmp("-", name)) printf(" %s", name);
+	xputc('\n');
+}
+
+void cksum_main(void)
+{
+	crc_init(TT.crc_table, toys.optflags&2);
+	loopfiles(toys.optargs, do_cksum);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/cmp.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,92 @@
+/* vi: set sw=4 ts=4:
+ *
+ * cmp.c - Compare two files.
+ *
+ * Copyright 2012 Timothy Elliott <tle@holymonkey.com>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cmp.html
+
+USE_CMP(NEWTOY(cmp, "<2>2ls", TOYFLAG_USR|TOYFLAG_BIN))
+
+config CMP
+	bool "cmp"
+	default y
+	help
+	  usage: cmp [-l] [-s] FILE1 FILE2
+
+	  Compare the contents of two files.
+
+	  -l show all differing bytes
+	  -s silent
+*/
+
+#include "toys.h"
+
+#define FLAG_s	1
+#define FLAG_l	2
+
+DEFINE_GLOBALS(
+	int fd;
+	char *name;
+)
+
+#define TT this.cmp
+
+// This handles opening the file and 
+
+void do_cmp(int fd, char *name)
+{
+	int i, len1, len2, min_len, size = sizeof(toybuf)/2;
+	long byte_no = 1, line_no = 1;
+	char *buf2 = toybuf+size;
+
+	// First time through, cache the data and return.
+	if (!TT.fd) {
+		TT.name = name;
+		// On return the old filehandle is closed, and this assures that even
+		// if we were called with stdin closed, the new filehandle != 0.
+		TT.fd = dup(fd);
+		return;
+	}
+
+	for (;;) {
+		len1 = readall(TT.fd, toybuf, size);
+		len2 = readall(fd, buf2, size);
+
+		min_len = len1 < len2 ? len1 : len2;
+		for (i=0; i<min_len; i++) {
+			if (toybuf[i] != buf2[i]) {
+				toys.exitval = 1;
+				if (toys.optflags & FLAG_l)
+					printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]);
+				else {
+					if (!(toys.optflags & FLAG_s)) {
+						printf("%s %s differ: char %ld, line %ld\n",
+							TT.name, name, byte_no, line_no);
+						toys.exitval++;
+					}
+					goto out;
+				}
+			}
+			byte_no++;
+			if (toybuf[i] == '\n') line_no++;
+		}
+		if (len1 != len2) {
+			if (!(toys.optflags & FLAG_s)) {
+				fprintf(stderr, "cmp: EOF on %s\n",
+					len1 < len2 ? TT.name : name);
+			}
+			toys.exitval = 1;
+			break;
+		}
+		if (len1 < 1) break;
+	}
+out:
+	if (CFG_TOYBOX_FREE) close(TT.fd);
+}
+
+void cmp_main(void)
+{
+	loopfiles_rw(toys.optargs, O_RDONLY, 0, toys.optflags&FLAG_s, do_cmp);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/comm.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,85 @@
+/* vi: set sw=4 ts=4:
+ *
+ * comm.c - select or reject lines common to two files
+ *
+ * Copyright 2012 Ilya Kuzmich <ikv@safe-mail.net>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/comm.html
+
+// <# and ># take single digit, so 321 define flags
+USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
+
+config COMM
+	bool "comm"
+	default y
+	help
+	  usage: comm [-123] FILE1 FILE2
+
+	  Reads FILE1 and FILE2, which should be ordered, and produces three text
+	  columns as output: lines only in FILE1; lines only in FILE2; and lines
+	  in both files. Filename "-" is a synonym for stdin.
+
+	  -1 suppress the output column of lines unique to FILE1
+	  -2 suppress the output column of lines unique to FILE2
+	  -3 suppress the output column of lines duplicated in FILE1 and FILE2
+*/
+
+#include "toys.h"
+
+#define FLAG_1 1
+#define FLAG_2 2
+#define FLAG_3 4
+
+static void writeline(const char *line, int col)
+{
+	if (col == 0 && toys.optflags & FLAG_1) return;
+	else if (col == 1) {
+		if (toys.optflags & FLAG_2) return;
+		if (!(toys.optflags & FLAG_1)) putchar('\t');
+	} else if (col == 2) {
+		if (toys.optflags & FLAG_3) return;
+		if (!(toys.optflags & FLAG_1)) putchar('\t');
+		if (!(toys.optflags & FLAG_2)) putchar('\t');
+	}
+	puts(line);
+}
+
+void comm_main(void)
+{
+	int file[2];
+	char *line[2];
+	int i;
+
+	if (toys.optflags == 7) return;
+
+	for (i = 0; i < 2; i++) {
+		file[i] = strcmp("-", toys.optargs[i]) ? xopen(toys.optargs[i], O_RDONLY) : 0;
+		line[i] = get_line(file[i]);
+	}
+
+	while (line[0] && line[1]) {
+		int order = strcmp(line[0], line[1]);
+
+		if (order == 0) {
+			writeline(line[0], 2);
+			for (i = 0; i < 2; i++) {
+				free(line[i]);
+				line[i] = get_line(file[i]);
+			}
+		} else {
+			i = order < 0 ? 0 : 1;
+			writeline(line[i], i);
+			free(line[i]);
+			line[i] = get_line(file[i]);
+		}
+	}
+
+	/* print rest of the longer file */
+	for (i = line[0] ? 0 : 1; line[i];) {
+		writeline(line[i], i);
+		free(line[i]);
+		line[i] = get_line(file[i]);
+	}
+
+	if (CFG_TOYBOX_FREE) for (i = 0; i < 2; i--) xclose(file[i]);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/cp.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,224 @@
+/* vi: set sw=4 ts=4:
+ *
+ * cp.c - Copy files.
+ *
+ * Copyright 2008 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/cp.html
+ *
+ * "R+ra+d+p+r"
+USE_CP(NEWTOY(cp, "<2vslrRdpaHLPif", TOYFLAG_BIN))
+
+config CP
+	bool "cp (broken by dirtree changes)"
+	default n
+	help
+	  usage: cp -fiprdal SOURCE... DEST
+
+	  Copy files from SOURCE to DEST.  If more than one SOURCE, DEST must
+	  be a directory.
+
+		-f	force copy by deleting destination file
+		-i	interactive, prompt before overwriting existing DEST
+		-p	preserve timestamps, ownership, and permissions
+		-r	recurse into subdirectories (DEST must be a directory)
+		-d	don't dereference symlinks
+		-a	same as -dpr
+		-l	hard link instead of copying
+		-v	verbose
+*/
+
+#include "toys.h"
+
+#define FLAG_f 1
+#define FLAG_i 2
+#define FLAG_P 4	// todo
+#define FLAG_L 8	// todo
+#define FLAG_H 16	// todo
+#define FLAG_a 32
+#define FLAG_p 64
+#define FLAG_d 128	// todo
+#define FLAG_R 256
+#define FLAG_r 512
+#define FLAG_l 1024	// todo
+#define FLAG_s 2048	// todo
+#define FLAG_v 4098
+
+DEFINE_GLOBALS(
+	char *destname;
+	int destisdir;
+	int destisnew;
+	int keep_symlinks;
+)
+
+#define TT this.cp
+
+// Copy an individual file or directory to target.
+
+void cp_file(char *src, char *dst, struct stat *srcst)
+{
+	int fdout = -1;
+
+	// -i flag is specified and dst file exists.
+	if ((toys.optflags&FLAG_i) && !access(dst, R_OK)
+		&& !yesno("cp: overwrite", 1))
+			return;
+
+	if (toys.optflags & FLAG_v)
+		printf("'%s' -> '%s'\n", src, dst);
+
+	// Copy directory or file to destination.
+
+	if (S_ISDIR(srcst->st_mode)) {
+		struct stat st2;
+
+		// Always make directory writeable to us, so we can create files in it.
+		//
+		// Yes, there's a race window between mkdir() and open() so it's
+		// possible that -p can be made to chown a directory other than the one
+		// we created.  The closest we can do to closing this is make sure
+		// that what we open _is_ a directory rather than something else.
+
+		if ((mkdir(dst, srcst->st_mode | 0200) && errno != EEXIST)
+			|| 0>(fdout=open(dst, 0)) || fstat(fdout, &st2)
+			|| !S_ISDIR(st2.st_mode))
+		{
+			perror_exit("mkdir '%s'", dst);
+		}
+	} else if (TT.keep_symlinks && S_ISLNK(srcst->st_mode)) {
+		char *link = xreadlink(src);
+
+		// Note: -p currently has no effect on symlinks.  How do you get a
+		// filehandle to them?  O_NOFOLLOW causes the open to fail.
+		if (!link || symlink(link, dst)) perror_msg("link '%s'", dst);
+		free(link);
+		return;
+	} else if (toys.optflags & FLAG_l) {
+		if (link(src, dst)) perror_msg("link '%s'");
+		return;
+	} else {
+		int fdin, i;
+
+		fdin = xopen(src, O_RDONLY);
+		for (i=2 ; i; i--) {
+			fdout = open(dst, O_RDWR|O_CREAT|O_TRUNC, srcst->st_mode);
+			if (fdout>=0 || !(toys.optflags & FLAG_f)) break;
+			unlink(dst);
+		}
+		if (fdout<0) perror_exit("%s", dst);
+		xsendfile(fdin, fdout);
+		close(fdin);
+	}
+
+	// Inability to set these isn't fatal, some require root access.
+	// Can't do fchmod() etc here because -p works on mkdir, too.
+
+	if (toys.optflags & (FLAG_p|FLAG_a)) {
+		int mask = umask(0);
+		struct utimbuf ut;
+
+		(void) fchown(fdout,srcst->st_uid, srcst->st_gid);
+		ut.actime = srcst->st_atime;
+		ut.modtime = srcst->st_mtime;
+		utime(dst, &ut);
+		umask(mask);
+	}
+	xclose(fdout);
+}
+
+// Callback from dirtree_read() for each file/directory under a source dir.
+
+int cp_node(struct dirtree *node)
+{
+	char *path = dirtree_path(node, 0); // TODO: use openat() instead
+	char *s = path+strlen(path);
+	struct dirtree *n;
+
+	// Find appropriate chunk of path for destination.
+
+	n = node;
+	if (!TT.destisdir) n = n->parent;
+	for (;;n = n->parent) {
+		while (s!=path) {
+			if (*(--s)=='/') break;
+		}
+		if (!n) break;
+	}
+	if (s != path) s++;
+
+	s = xmsprintf("%s/%s", TT.destname, s);
+	cp_file(path, s, &(node->st));
+	free(s);
+	free(path); // redo this whole darn function.
+
+	return 0;
+}
+
+void cp_main(void)
+{
+	struct stat st;
+	int i;
+
+	// Grab target argument.  (Guaranteed to be there due to "<2" above.)
+
+	TT.destname = toys.optargs[--toys.optc];
+
+	// If destination doesn't exist, are we ok with that?
+
+	if (stat(TT.destname, &st)) {
+		if (toys.optc>1) goto error_notdir;
+		TT.destisnew++;
+
+	// If destination exists...
+
+	} else {
+		if (S_ISDIR(st.st_mode)) TT.destisdir++;
+		else if (toys.optc > 1) goto error_notdir;
+	}
+
+	// Handle sources
+
+	for (i=0; i<toys.optc; i++) {
+		char *src = toys.optargs[i];
+		char *dst;
+
+		// Skip src==dest (TODO check inodes to catch "cp blah ./blah").
+
+		if (!strcmp(src, TT.destname)) continue;
+
+		// Skip nonexistent sources.
+
+		TT.keep_symlinks = toys.optflags & (FLAG_d|FLAG_a);
+		if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st))
+		{
+			perror_msg("'%s'", src);
+			toys.exitval = 1;
+			continue;
+		}
+
+		// Copy directory or file.
+
+		if (TT.destisdir) {
+			dst = strrchr(src, '/');
+			if (dst) dst++;
+			else dst=src;
+			dst = xmsprintf("%s/%s", TT.destname, dst);
+		} else dst = TT.destname;
+		if (S_ISDIR(st.st_mode)) {
+			if (toys.optflags & (FLAG_r|FLAG_R|FLAG_a)) {
+				cp_file(src, dst, &st);
+
+				TT.keep_symlinks++;
+				strncpy(toybuf, src, sizeof(toybuf)-1);
+				toybuf[sizeof(toybuf)-1]=0;
+				dirtree_read(toybuf, cp_node);
+			} else error_msg("Skipped dir '%s'", src);
+		} else cp_file(src, dst, &st);
+		if (TT.destisdir) free(dst);
+	}
+
+	return;
+
+error_notdir:
+	error_exit("'%s' isn't a directory", TT.destname);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/date.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,95 @@
+/* vi: set sw=4 ts=4:
+ *
+ * date.c - set/get the date
+ *
+ * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/date.html
+
+USE_DATE(NEWTOY(date, "r:u", TOYFLAG_BIN))
+
+config DATE
+	bool "date"
+	default y
+	help
+	  usage: date [-u] [-r file] [+format] | mmddhhmm[[cc]yy]
+
+	  Set/get the current date/time
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+    char *file;
+)
+
+#define TT this.date
+
+#define FLAG_u 1
+#define FLAG_r 2
+
+void date_main(void)
+{
+    const char *format_string = "%a %b %e %H:%M:%S %Z %Y";
+    time_t now = time(NULL);
+    struct tm tm;
+
+    if (TT.file) {
+        struct stat st;
+
+        xstat(TT.file, &st);
+        now = st.st_mtim.tv_sec;
+    }
+    ((toys.optflags & FLAG_u) ? gmtime_r : localtime_r)(&now, &tm);
+
+    // Display the date?
+    if (!toys.optargs[0] || toys.optargs[0][0] == '+') {
+        if (toys.optargs[0]) format_string = toys.optargs[0]+1;
+        if (!strftime(toybuf, sizeof(toybuf), format_string, &tm))
+            perror_msg("bad format `%s'", format_string);
+
+        puts(toybuf);
+
+    // Set the date
+    } else {
+        struct timeval tv;
+        char *s = *toys.optargs;
+        int len = strlen(s);
+
+        if (len < 8 || len > 12 || (len & 1)) error_msg("bad date `%s'", s);
+
+        // Date format: mmddhhmm[[cc]yy]
+        memset(&tm, 0, sizeof(tm));
+        len = sscanf(s, "%2u%2u%2u%2u", &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
+               &tm.tm_min);
+        tm.tm_mon--;
+
+        // If year specified, overwrite one we fetched earlier
+        if (len > 8) {
+            sscanf(s, "%u", &tm.tm_year);
+            if (len == 12) tm.tm_year -= 1900;
+            /* 69-99 = 1969-1999, 0 - 68 = 2000-2068 */
+            else if (tm.tm_year < 69) tm.tm_year += 100;
+        }
+
+        if (toys.optflags & FLAG_u) {
+            // Get the UTC version of a struct tm
+            char *tz = CFG_TOYBOX_FREE ? getenv("TZ") : 0;
+            setenv("TZ", "UTC", 1);
+            tzset();
+            tv.tv_sec = mktime(&tm);
+            if (CFG_TOYBOX_FREE) {
+                if (tz) setenv("TZ", tz, 1);
+                else unsetenv("TZ");
+                tzset();
+            }
+        } else tv.tv_sec = mktime(&tm);
+
+        if (tv.tv_sec == (time_t)-1) error_msg("bad `%s'", toys.optargs[0]);
+        tv.tv_usec = 0;
+        if (!strftime(toybuf, sizeof(toybuf), format_string, &tm))
+            perror_msg("bad format `%s'", format_string);
+        puts(toybuf);
+        if (settimeofday(&tv, NULL) < 0) perror_msg("cannot set date");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/df.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,154 @@
+/* vi: set sw=4 ts=4:
+ *
+ * df.c - report free disk space.
+ *
+ * Copyright 2006 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/df.html
+
+USE_DF(NEWTOY(df, "Pkt*a", TOYFLAG_USR|TOYFLAG_SBIN))
+
+config DF
+	bool "df (disk free)"
+	default y
+	help
+	  usage: df [-t type] [FILESYSTEM ...]
+
+	  The "disk free" command, df shows total/used/available disk space for
+	  each filesystem listed on the command line, or all currently mounted
+	  filesystems.
+
+	  -t type
+		Display only filesystems of this type.
+
+config DF_PEDANTIC
+	bool "options -P and -k"
+	default y
+	depends on DF
+	help
+	  usage: df [-Pk]
+
+	  -P	The SUSv3 "Pedantic" option
+
+		Provides a slightly less useful output format dictated by
+		the Single Unix Specification version 3, and sets the
+		units to 512 bytes instead of the default 1024 bytes.
+
+	  -k	Sets units back to 1024 bytes (the default without -P)
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	struct arg_list *fstype;
+
+	long units;
+)
+
+#define TT this.df
+
+static void show_mt(struct mtab_list *mt)
+{
+	int len;
+	long size, used, avail, percent;
+	uint64_t block;
+
+	// Return if it wasn't found (should never happen, but with /etc/mtab...)
+	if (!mt) return;
+
+	// If we have -t, skip other filesystem types
+	if (TT.fstype) {
+		struct arg_list *al;
+
+		for (al = TT.fstype; al; al = al->next) {
+			if (!strcmp(mt->type, al->arg)) break;
+		}
+		if (!al) return;
+	}
+
+	// If we don't have -a, skip synthetic filesystems
+	if (!(toys.optflags & 1) && !mt->statvfs.f_blocks) return;
+
+	// Figure out how much total/used/free space this filesystem has,
+	// forcing 64-bit math because filesystems are big now.
+	block = mt->statvfs.f_bsize ? mt->statvfs.f_bsize : 1;
+	size = (long)((block * mt->statvfs.f_blocks) / TT.units);
+	used = (long)((block * (mt->statvfs.f_blocks-mt->statvfs.f_bfree))
+			/ TT.units);
+	avail = (long)((block
+				* (getuid() ? mt->statvfs.f_bavail : mt->statvfs.f_bfree))
+			/ TT.units);
+	percent = size ? 100-(long)((100*(uint64_t)avail)/size) : 0;
+
+	// Figure out appropriate spacing
+	len = 25 - strlen(mt->device);
+	if (len < 1) len = 1;
+	if (CFG_DF_PEDANTIC && (toys.optflags & 8)) {
+		printf("%s %ld %ld %ld %ld%% %s\n", mt->device, size, used, avail,
+				percent, mt->dir);
+	} else {
+		printf("%s% *ld % 10ld % 9ld % 3ld%% %s\n",mt->device, len,
+			size, used, avail, percent, mt->dir);
+	}
+}
+
+void df_main(void)
+{
+	struct mtab_list *mt, *mt2, *mtlist;
+
+	// Handle -P and -k
+	TT.units = 1024;
+	if (CFG_DF_PEDANTIC && (toys.optflags & 8)) {
+		// Units are 512 bytes if you select "pedantic" without "kilobytes".
+		if ((toys.optflags&3) == 1) TT.units = 512;
+		printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n",
+			TT.units);
+	} else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on");
+
+	mtlist = getmountlist(1);
+
+	// If we have a list of filesystems on the command line, loop through them.
+	if (*toys.optargs) {
+		char **next;
+
+		for(next = toys.optargs; *next; next++) {
+			struct stat st;
+
+			// Stat it (complain if we can't).
+			if(stat(*next, &st)) {
+				perror_msg("`%s'", *next);
+				toys.exitval = 1;
+				continue;
+			}
+
+			// Find and display this filesystem.  Use _last_ hit in case of
+			// -- bind mounts.
+			mt2 = NULL;
+			for (mt = mtlist; mt; mt = mt->next)
+				if (st.st_dev == mt->stat.st_dev) mt2 = mt;
+			show_mt(mt2);
+		}
+	} else {
+		// Get and loop through mount list.
+
+		for (mt = mtlist; mt; mt = mt->next) {
+			struct mtab_list *mt2, *mt3;
+
+			if (!mt->stat.st_dev) continue;
+
+			// Filter out overmounts.
+			mt3 = mt;
+			for (mt2 = mt->next; mt2; mt2 = mt2->next) {
+				if (mt->stat.st_dev == mt2->stat.st_dev) {
+					// For --bind mounts, take last match
+					if (!strcmp(mt->device, mt2->device)) mt3 = mt2;
+					// Filter out overmounts
+					mt2->stat.st_dev = 0;
+				}
+			}
+			show_mt(mt3);
+		}
+	}
+
+	if (CFG_TOYBOX_FREE) llist_traverse(mtlist, free);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/dirname.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,25 @@
+/* vi: set sw=4 ts=4:
+ *
+ * dirname.c - show directory portion of path
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/dirname.html
+
+USE_DIRNAME(NEWTOY(dirname, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+
+config DIRNAME
+	bool "dirname"
+	default y
+	help
+	  usage: dirname PATH
+
+	  Show directory portion of path.
+*/
+
+#include "toys.h"
+
+void dirname_main(void)
+{
+	puts(dirname(*toys.optargs));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/echo.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,97 @@
+/* vi: set sw=4 ts=4:
+ *
+ * echo.c - echo supporting -n and -e.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/echo.html
+
+USE_ECHO(NEWTOY(echo, "^?en", TOYFLAG_BIN))
+
+config ECHO
+	bool "echo"
+	default y
+	help
+	  usage: echo [-ne] [args...]
+
+	  Write each argument to stdout, with one space between each, followed
+	  by a newline.
+
+	  -n	No trailing newline.
+	  -e	Process the following escape sequences:
+	   \\	 backslash
+	   \0NNN octal values (1 to 3 digits)
+	   \a	 alert (beep/flash)
+	   \b	 backspace
+	   \c	 stop output here (avoids trailing newline)
+	   \f	 form feed
+	   \n	 newline
+	   \r	 carriage return
+	   \t	 horizontal tab
+	   \v	 vertical tab
+	   \xHH	 hexadecimal values (1 to 2 digits)
+*/
+
+#define THIS echo
+#include "toys.h"
+
+#define FLAG_e (1<<1)
+#define FLAG_n (1<<0)
+
+void echo_main(void)
+{
+	int i = 0, out;
+	char *arg, *from = "\\abfnrtv", *to = "\\\a\b\f\n\r\t\v", *c;
+
+	for (;;) {
+		arg = toys.optargs[i];
+		if (!arg) break;
+		if (i++) xputc(' ');
+
+		// Should we output arg verbatim?
+
+		if (!(toys.optflags&FLAG_e)) {
+			xprintf("%s", arg);
+			continue;
+		}
+
+		// Handle -e
+
+		for (c=arg;;) {
+			if (!(out = *(c++))) break;
+
+			// handle \escapes
+			if (out == '\\' && *c) {
+				int n = 0, slash = *(c++);
+				char *found = strchr(from, slash);
+				if (found) out = to[found-from];
+				else if (slash == 'c') goto done;
+				else if (slash == '0') {
+					out = 0;
+					while (*c>='0' && *c<='7' && n++<3)
+						out = (out*8)+*(c++)-'0';
+				} else if (slash == 'x') {
+					out = 0;							
+					while (n++<2) {
+						if (*c>='0' && *c<='9')
+							out = (out*16)+*(c++)-'0';
+						else {
+							int temp = tolower(*c);
+							if (temp>='a' && temp<='f') {
+								out = (out*16)+temp-'a'+10;
+								c++;
+							} else break;
+						}
+					}
+				// Slash in front of unknown character, print literal.
+				} else c--;
+			}
+			xputc(out);
+		}
+	}
+
+	// Output "\n" if no -n
+	if (!(toys.optflags&FLAG_n)) xputc('\n');
+done:
+	xflush();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/env.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,52 @@
+/* vi: set sw=4 ts=4:
+ *
+ * env.c - Set the environment for command invocation.
+ *
+ * Copyright 2012 Tryn Mirell <tryn@mirell.org>
+ * env.c
+
+USE_ENV(NEWTOY(env, "^i", TOYFLAG_USR|TOYFLAG_BIN))
+
+config ENV
+	bool "env"
+	default y
+	help
+          usage: env [-i] [NAME=VALUE...] [command [option...]]
+
+          Set the environment for command invocation.
+
+	  -i	Clear existing environment.
+*/
+
+#include "toys.h"
+
+extern char **environ;
+
+void env_main(void)
+{
+    char **ev;
+    char **command = NULL;
+    char *del = "=";
+    
+    if (toys.optflags & 1) clearenv();
+    
+    for (ev = toys.optargs; *ev != NULL; ev++) {
+        char *env, *val = NULL;
+        
+        env = strtok(*ev, del);
+        
+        if (env) val = strtok(NULL, del);
+        
+        if (val) setenv(env, val, 1);
+        else {
+            command = ev;
+            break;
+        }
+    }
+    
+    if (!command) {
+        char **ep;
+        for (ep = environ; *ep; ep++) xputs(*ep);
+        return;
+    } else xexec(command);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/false.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,23 @@
+/* vi: set sw=4 ts=4:
+ *
+ * false.c - Return nonzero.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/false.html
+
+USE_FALSE(NEWTOY(false, NULL, TOYFLAG_BIN))
+
+config FALSE
+	bool "false"
+	default y
+	help
+	  Return nonzero.
+*/
+
+#include "toys.h"
+
+void false_main(void)
+{
+	toys.exitval = 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/head.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,61 @@
+/* vi: set sw=4 ts=4:
+ *
+ * head.c - copy first lines from input to stdout.
+ *
+ * Copyright 2006 Timothy Elliott <tle@holymonkey.com>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/head.html
+
+USE_HEAD(NEWTOY(head, "n#<0=10", TOYFLAG_BIN))
+
+config HEAD
+	bool "head"
+	default y
+	help
+	  usage: head [-n number] [file...]
+
+	  Copy first lines from files to stdout. If no files listed, copy from
+	  stdin. Filename "-" is a synonym for stdin.
+
+	  -n	Number of lines to copy.
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	long lines;
+	int file_no;
+)
+
+#define TT this.head
+
+static void do_head(int fd, char *name)
+{
+	int i, len, lines=TT.lines, size=sizeof(toybuf);
+
+	if (toys.optc > 1) {
+		// Print an extra newline for all but the first file
+		if (TT.file_no++) xprintf("\n");
+		xprintf("==> %s <==\n", name);
+		xflush();
+	}
+
+	while (lines) {
+		len = read(fd, toybuf, size);
+		if (len<0) {
+			perror_msg("%s",name);
+			toys.exitval = EXIT_FAILURE;
+		}
+		if (len<1) break;
+		
+		for(i=0; i<len;)
+			if (toybuf[i++] == '\n' && !--lines) break;
+
+		xwrite(1, toybuf, i);
+	}
+}
+
+void head_main(void)
+{
+	loopfiles(toys.optargs, do_head);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/id.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,119 @@
+/* vi: set sw=4 ts=4:
+ *
+ * id.c - print real and effective user and group IDs
+ *
+ * Copyright 2012 Sony Network Entertainment, Inc.
+ *
+ * by Tim Bird <tim.bird@am.sony.com>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/id.html
+
+USE_ID(NEWTOY(id, "nGgru", TOYFLAG_BIN))
+
+config ID
+	bool "id"
+	default y
+	help
+	  usage: id [-nGgru]
+
+	  Print user and group ID.
+
+	  -n	print names instead of numeric IDs (to be used with -Ggu)
+	  -G	Show only the group IDs
+	  -g    Show only the effective group ID
+	  -r	Show real ID instead of effective ID
+	  -u    Show only the effective user ID
+*/
+
+#include "toys.h"
+
+#define FLAG_n (1<<4)
+#define FLAG_G (1<<3)
+#define FLAG_g (1<<2)
+#define FLAG_r (1<<1)
+#define FLAG_u 1
+
+static void s_or_u(char *s, unsigned u, int done)
+{
+	if (toys.optflags & FLAG_n) printf("%s", s);
+	else printf("%u", u);
+	if (done) {
+		xputc('\n');
+		exit(0);
+	}
+}
+
+static void showid(char *header, unsigned u, char *s)
+{
+	printf("%s%u(%s)", header, u, s);
+}
+
+struct passwd *xgetpwuid(uid_t uid)
+{
+	struct passwd *pwd = getpwuid(uid);
+	if (!pwd) error_exit(NULL);
+	return pwd;
+}
+
+struct group *xgetgrgid(gid_t gid)
+{
+	struct group *group = getgrgid(gid);
+	if (!group) error_exit(NULL);
+	return group;
+}
+
+void id_main(void)
+{
+	int flags = toys.optflags, i, ngroups;
+	struct passwd *pw;
+	struct group *grp;
+	uid_t uid = getuid(), euid = geteuid();
+	gid_t gid = getgid(), egid = getegid(), *groups;
+
+	/* check if a username is given */
+	if (*toys.optargs) {
+		if (!(pw = getpwnam(*toys.optargs)))
+			error_exit("no such user '%s'", *toys.optargs);
+		uid = euid = pw->pw_uid;
+		gid = egid = pw->pw_gid;
+	}
+
+	i = toys.optflags & FLAG_r;
+	pw = xgetpwuid(i ? uid : euid);
+	if (flags & FLAG_u) s_or_u(pw->pw_name, pw->pw_uid, 1);
+
+	grp = xgetgrgid(i ? gid : egid);
+	if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1);
+
+	if (!(flags & FLAG_G)) {
+		showid("uid=", pw->pw_uid, pw->pw_name);
+		showid(" gid=", grp->gr_gid, grp->gr_name);
+
+		if (!i) {
+			if (uid != euid) {
+				pw = xgetpwuid(euid);
+				showid(" euid=", pw->pw_uid, pw->pw_name);
+			}
+			if (gid != egid) {
+				grp = xgetgrgid(egid);
+				showid(" egid=", grp->gr_gid, grp->gr_name);
+			}
+		}
+
+		showid(" groups=", grp->gr_gid, grp->gr_name);
+	}
+
+
+	groups = (gid_t *)toybuf;
+	if (0 >= (ngroups = getgroups(sizeof(toybuf)/sizeof(gid_t), groups)))
+		perror_exit(0);
+
+	for (i = 0; i < ngroups; i++) {
+		xputc(' ');
+		if (!(grp = getgrgid(groups[i]))) perror_msg(0);
+		else if (flags & FLAG_G)
+			s_or_u(grp->gr_name, grp->gr_gid, 0);
+		else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name);
+	}
+	xputc('\n');
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/kill.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,74 @@
+/* vi: set sw=4 ts=4:
+ *
+ * kill.c - a program to send signals to processes
+ *
+ * Copyright 2012 Daniel Walter <d.walter@0x90.at>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/kill.html
+
+USE_KILL(NEWTOY(kill, "?s: l", TOYFLAG_BIN))
+
+config KILL
+	bool "kill"
+	default y
+	help
+	  usage: kill [-l [SIGNAL] | -s SIGNAL | -SIGNAL] pid...
+
+	  Send a signal to a process
+
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	char *signame;
+)
+
+#define TT this.kill
+
+void kill_main(void)
+{
+	int signum;
+	char *tmp, **args = toys.optargs;
+	pid_t pid;
+
+	// list signal(s)
+	if (toys.optflags & 1) {
+		if (*args) {
+			int signum = sig_to_num(*args);
+			char *s = NULL;
+
+			if (signum>=0) s = num_to_sig(signum&127);
+			puts(s ? s : "UNKNOWN");
+		} else sig_to_num(NULL);
+		return;
+	}
+
+	// signal must come before pids, so "kill -9 -1" isn't confusing.
+
+	if (!TT.signame && *args && **args=='-') TT.signame=*(args++)+1;
+	if (TT.signame) {
+		char *arg;
+		int i = strtol(TT.signame, &arg, 10);
+		if (!*arg) arg = num_to_sig(i);
+		else arg = TT.signame;
+
+		if (!arg || -1 == (signum = sig_to_num(arg)))
+			error_exit("Unknown signal '%s'", arg);
+	} else signum = SIGTERM;
+
+	if (!*args) {
+		toys.exithelp++;
+		error_exit("missing argument");
+	}
+
+	while (*args) {
+		char *arg = *(args++);
+
+		pid = strtol(arg, &tmp, 10);
+		if (*tmp || kill(pid, signum) < 0) {
+			error_msg("unknown pid '%s'", arg);
+			toys.exitval = EXIT_FAILURE;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/link.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,27 @@
+/* vi: set sw=4 ts=4:
+ *
+ * link.c - hardlink a file
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/link.html
+
+USE_LINK(NEWTOY(link, "<2>2", TOYFLAG_USR|TOYFLAG_BIN))
+
+config LINK
+	bool "link"
+	default y
+	help
+	  usage: link FILE NEWLINK
+
+	  Create hardlink to a file.
+*/
+
+#include "toys.h"
+
+void link_main(void)
+{
+	if (link(toys.optargs[0], toys.optargs[1]))
+		perror_exit("couldn't link '%s' to '%s'", toys.optargs[1],
+			toys.optargs[0]);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/ln.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,70 @@
+/* vi: set sw=4 ts=4:
+ *
+ * ln.c - Create filesystem links
+ *
+ * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ln.html
+
+USE_LN(NEWTOY(ln, "<1nfs", TOYFLAG_BIN))
+
+config LN
+	bool "ln"
+	default y
+	help
+	  usage: ln [-sf] [FROM...] TO
+
+	  Create a link between FROM and TO.
+	  With only one argument, create link in current directory.
+
+	  -s	Create a symbolic link
+	  -f	Force the creation of the link, even if TO already exists
+          -n	Symlink at destination treated as file
+*/
+
+#include "toys.h"
+
+#define FLAG_s	1
+#define FLAG_f	2
+#define FLAG_n	4
+
+void ln_main(void)
+{
+    char *dest = toys.optargs[--toys.optc], *new;
+    struct stat buf;
+    int i;
+
+    // With one argument, create link in current directory.
+    if (!toys.optc) {
+        toys.optc++;
+        dest=".";
+    }
+
+    // Is destination a directory?
+    if (((toys.optflags&FLAG_n) ? lstat : stat)(dest, &buf)
+        || !S_ISDIR(buf.st_mode))
+    {
+        if (toys.optc>1) error_exit("'%s' not a directory");
+        buf.st_mode = 0;
+    }
+
+    for (i=0; i<toys.optc; i++) {
+        int rc;
+        char *try = toys.optargs[i];
+
+        if (S_ISDIR(buf.st_mode)) {
+            new = strrchr(try, '/');
+            if (!new) new = try;
+            new = xmsprintf("%s/%s", dest, new);
+        } else new = dest;
+        /* Silently unlink the existing target. If it doesn't exist,
+         * then we just move on */
+        if (toys.optflags & FLAG_f) unlink(new);
+
+        rc = (toys.optflags & FLAG_s) ? symlink(try, new) : link(try, new);
+        if (rc)
+            perror_exit("cannot create %s link from '%s' to '%s'",
+                (toys.optflags & FLAG_s) ? "symbolic" : "hard", try, new);
+        if (new != dest) free(new);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/logname.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,29 @@
+/* vi: set sw=4 ts=4:
+ *
+ * logname.c - Print user's login name.
+ *
+ * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/logname.html
+
+USE_LOGNAME(NEWTOY(logname, ">0", TOYFLAG_BIN))
+
+config LOGNAME
+	bool "logname"
+	default y
+	help
+	  usage: logname
+
+	  Prints the calling user's name or an error when this cannot be
+	  determined.
+*/
+
+#include "toys.h"
+
+void logname_main(void)
+{
+	if (getlogin_r(toybuf, sizeof(toybuf))){
+		error_exit("no login name");
+	}
+	xputs(toybuf);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/ls.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,493 @@
+/* vi: set sw=4 ts=4:
+ *
+ * ls.c - list files
+ *
+ * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
+ * Copyright 2012 Rob Landley <rob@landley.net>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html
+
+// "[-Cl]"
+USE_LS(NEWTOY(ls, "goACFHLRSacdfiklmnpqrstux1", TOYFLAG_BIN))
+
+config LS
+	bool "ls"
+	default y
+	help
+	  usage: ls [-ACFHLRSacdfiklmnpqrstux1] [directory...]
+	  list files
+
+	  what to show:
+	  -a    all files including .hidden
+	  -c	use ctime for timestamps
+	  -d	directory, not contents
+	  -i	inode number
+	  -k	block sizes in kilobytes
+	  -p	put a '/' after directory names
+	  -q	unprintable chars as '?'
+	  -s	size (in blocks)
+	  -u	use access time for timestamps
+	  -A	list all files except . and ..
+	  -H	follow command line symlinks
+	  -L	follow symlinks
+	  -R	recursively list files in subdirectories
+	  -F    append file type indicator (/=dir, *=exe, @=symlink, |=FIFO)
+
+	  output formats:
+	  -1    list one file per line
+	  -C	columns (sorted vertically)
+	  -g	like -l but no owner
+	  -l	long (show full details for each file)
+	  -m	comma separated
+	  -n	like -l but numeric uid/gid
+	  -o	like -l but no group
+	  -x	columns (sorted horizontally)
+
+	  sorting (default is alphabetical):
+	  -f	unsorted
+	  -r	reverse
+	  -t	timestamp
+	  -S	size
+*/
+
+#include "toys.h"
+
+#define FLAG_1 (1<<0)
+#define FLAG_x (1<<1)
+#define FLAG_u (1<<2)
+#define FLAG_t (1<<3)
+#define FLAG_s (1<<4)
+#define FLAG_r (1<<5)
+#define FLAG_q (1<<6)
+#define FLAG_p (1<<7)
+#define FLAG_n (1<<8)
+#define FLAG_m (1<<9)
+#define FLAG_l (1<<10)
+#define FLAG_k (1<<11)
+#define FLAG_i (1<<12)
+#define FLAG_f (1<<13)
+#define FLAG_d (1<<14)
+#define FLAG_c (1<<15)
+#define FLAG_a (1<<16)
+#define FLAG_S (1<<17)
+#define FLAG_R (1<<18)
+#define FLAG_L (1<<19)
+#define FLAG_H (1<<20)
+#define FLAG_F (1<<21)
+#define FLAG_C (1<<22)
+#define FLAG_A (1<<23)
+#define FLAG_o (1<<24)
+#define FLAG_g (1<<25)
+
+// test sst output (suid/sticky in ls flaglist)
+
+// ls -lR starts .: then ./subdir:
+
+DEFINE_GLOBALS(
+    struct dirtree *files;
+
+    unsigned screen_width;
+    int nl_title;
+
+    // group and user can make overlapping use of the utoa() buf, so move it
+    char uid_buf[12];
+)
+
+#define TT this.ls
+
+void dlist_to_dirtree(struct dirtree *parent)
+{
+    // Turn double_list into dirtree
+    struct dirtree *dt = parent->child;
+    if (dt) {
+        dt->parent->next = NULL;
+        while (dt) {
+            dt->parent = parent;
+            dt = dt->next;
+        }
+    }
+}
+
+static char endtype(struct stat *st)
+{
+    mode_t mode = st->st_mode;
+    if ((toys.optflags&(FLAG_F|FLAG_p)) && S_ISDIR(mode)) return '/';
+    if (toys.optflags & FLAG_F) {
+        if (S_ISLNK(mode)) return '@';
+        if (S_ISREG(mode) && (mode&0111)) return '*';
+        if (S_ISFIFO(mode)) return '|';
+        if (S_ISSOCK(mode)) return '=';
+    }
+    return 0;
+}
+
+static char *getusername(uid_t uid)
+{
+    struct passwd *pw = getpwuid(uid);
+    utoa_to_buf(uid, TT.uid_buf, 12);
+    return pw ? pw->pw_name : TT.uid_buf;
+}
+
+static char *getgroupname(gid_t gid)
+{
+    struct group *gr = getgrgid(gid);
+    return gr ? gr->gr_name : utoa(gid);
+}
+
+// Figure out size of printable entry fields for display indent/wrap
+
+static void entrylen(struct dirtree *dt, unsigned *len)
+{
+    struct stat *st = &(dt->st);
+    unsigned flags = toys.optflags;
+
+    *len = strlen(dt->name);
+    if (endtype(st)) ++*len;
+    if (flags & FLAG_m) ++*len;
+
+    if (flags & FLAG_i) *len += (len[1] = numlen(st->st_ino));
+    if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) {
+        unsigned fn = flags & FLAG_n;
+        len[2] = numlen(st->st_nlink);
+        len[3] = strlen(fn ? utoa(st->st_uid) : getusername(st->st_uid));
+        len[4] = strlen(fn ? utoa(st->st_gid) : getgroupname(st->st_gid));
+        len[5] = numlen(st->st_size);
+    }
+    if (flags & FLAG_s) *len += (len[6] = numlen(st->st_blocks));
+}
+
+static int compare(void *a, void *b)
+{
+    struct dirtree *dta = *(struct dirtree **)a;
+    struct dirtree *dtb = *(struct dirtree **)b;
+    int ret = 0, reverse = (toys.optflags & FLAG_r) ? -1 : 1;
+
+    if (toys.optflags & FLAG_S) {
+        if (dta->st.st_size > dtb->st.st_size) ret = -1;
+        else if (dta->st.st_size < dtb->st.st_size) ret = 1;
+    }
+    if (toys.optflags & FLAG_t) {
+        if (dta->st.st_mtime > dtb->st.st_mtime) ret = -1;
+        else if (dta->st.st_mtime < dtb->st.st_mtime) ret = 1;
+    }
+    if (!ret) ret = strcmp(dta->name, dtb->name);
+    return ret * reverse;
+}
+
+// callback from dirtree_recurse() determining how to handle this entry.
+
+static int filter(struct dirtree *new)
+{
+    int flags = toys.optflags;
+
+    // Special case to handle enormous dirs without running out of memory.
+    if (flags == (FLAG_1|FLAG_f)) {
+        xprintf("%s\n", new->name);
+        return 0;
+    }
+
+    if (!(flags&FLAG_f)) { 
+        if (flags & FLAG_a) return 0;
+        if (!(flags & FLAG_A) && new->name[0]=='.') return 0;
+    }
+
+    if (flags & FLAG_u) new->st.st_mtime = new->st.st_atime;
+    if (flags & FLAG_c) new->st.st_mtime = new->st.st_ctime;
+    if (flags & FLAG_k) new->st.st_blocks = (new->st.st_blocks + 1) / 2;
+    return dirtree_notdotdot(new);
+}
+
+// For column view, calculate horizontal position (for padding) and return
+// index of next entry to display.
+
+static unsigned long next_column(unsigned long ul, unsigned long dtlen,
+    unsigned columns, unsigned *xpos)
+{
+    unsigned long transition;
+    unsigned height, widecols;
+
+    // Horizontal sort is easy
+    if (!(toys.optflags & FLAG_C)) {
+        *xpos = ul % columns;
+        return ul;
+    }
+
+    // vertical sort
+
+    // For -x, calculate height of display, rounded up
+    height = (dtlen+columns-1)/columns;
+
+    // Sanity check: does wrapping render this column count impossible
+    // due to the right edge wrapping eating a whole row?
+    if (height*columns - dtlen >= height) {
+        *xpos = columns;
+        return 0;
+    }
+
+    // Uneven rounding goes along right edge
+    widecols = dtlen % height;
+    if (!widecols) widecols = height;
+    transition = widecols * columns;
+    if (ul < transition) {
+        *xpos =  ul % columns;
+        return (*xpos*height) + (ul/columns);
+    }
+
+    ul -= transition;
+    *xpos = ul % (columns-1);
+
+    return (*xpos*height) + widecols + (ul/(columns-1));
+}
+
+// Display a list of dirtree entries, according to current format
+// Output types -1, -l, -C, or stream
+
+static void listfiles(int dirfd, struct dirtree *indir)
+{
+    struct dirtree *dt, **sort = 0;
+    unsigned long dtlen = 0, ul = 0;
+    unsigned width, flags = toys.optflags, totals[7], len[7],
+        *colsizes = (unsigned *)(toybuf+260), columns = (sizeof(toybuf)-260)/4;
+    
+    memset(totals, 0, sizeof(totals));
+
+    // Silently descend into single directory listed by itself on command line.
+    // In this case only show dirname/total header when given -R.
+    if (!indir->parent) {
+        if (!(dt = indir->child)) return;
+        if (S_ISDIR(dt->st.st_mode) && !dt->next && !(flags & FLAG_d)) {
+            dt->extra = 1;
+            listfiles(open(dt->name, 0), dt);
+            return;
+        }
+    } else {
+        // Read directory contents. We dup() the fd because this will close it.
+        indir->data = dup(dirfd);
+        dirtree_recurse(indir, filter, (flags&FLAG_L));
+    }
+
+    // Copy linked list to array and sort it. Directories go in array because
+    // we visit them in sorted order.
+
+    for (;;) {
+        for (dt = indir->child; dt; dt = dt->next) {
+            if (sort) sort[dtlen] = dt;
+            dtlen++;
+        }
+        if (sort) break;
+        sort = xmalloc(dtlen * sizeof(void *));
+        dtlen = 0;
+        continue;
+    }
+
+    // Label directory if not top of tree, or if -R
+    if (indir->parent && (!indir->extra || (flags & FLAG_R)))
+    {
+        char *path = dirtree_path(indir, 0);
+
+        if (TT.nl_title++) xputc('\n');
+        xprintf("%s:\n", path);
+        free(path);
+    }
+
+    if (!(flags & FLAG_f)) qsort(sort, dtlen, sizeof(void *), (void *)compare);
+
+    // Find largest entry in each field for display alignment
+    if (flags & (FLAG_C|FLAG_x)) {
+
+        // columns can't be more than toybuf can hold, or more than files,
+        // or > 1/2 screen width (one char filename, one space).
+        if (columns > TT.screen_width/2) columns = TT.screen_width/2;
+        if (columns > dtlen) columns = dtlen;
+
+        // Try to fit as many columns as we can, dropping down by one each time
+        for (;columns > 1; columns--) {
+            unsigned c, totlen = columns;
+
+            memset(colsizes, 0, columns*sizeof(unsigned));
+            for (ul=0; ul<dtlen; ul++) {
+                entrylen(sort[next_column(ul, dtlen, columns, &c)], len);
+                if (c == columns) break;
+                // Does this put us over budget?
+                if (*len > colsizes[c]) {
+                    totlen += *len-colsizes[c];
+                    colsizes[c] = *len;
+                    if (totlen > TT.screen_width) break;
+                }
+            }
+            // If it fit, stop here
+            if (ul == dtlen) break;
+        }
+    } else if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g|FLAG_s)) {
+        unsigned long blocks = 0;
+
+        for (ul = 0; ul<dtlen; ul++)
+        {
+            entrylen(sort[ul], len);
+            for (width=0; width<6; width++)
+                if (len[width] > totals[width]) totals[width] = len[width];
+            blocks += sort[ul]->st.st_blocks;
+        }
+
+        if (indir->parent) xprintf("total %lu\n", blocks);
+    }
+
+    // Loop through again to produce output.
+    memset(toybuf, ' ', 256);
+    width = 0;
+    for (ul = 0; ul<dtlen; ul++) {
+        unsigned curcol;
+        unsigned long next = next_column(ul, dtlen, columns, &curcol);
+        struct stat *st = &(sort[next]->st);
+        mode_t mode = st->st_mode;
+        char et = endtype(st);
+
+        // Skip directories at the top of the tree when -d isn't set
+        if (S_ISDIR(mode) && !indir->parent && !(flags & FLAG_d)) continue;
+        TT.nl_title=1;
+
+        // Handle padding and wrapping for display purposes
+        entrylen(sort[next], len);
+        if (ul) {
+            if (flags & FLAG_m) xputc(',');
+            if (flags & (FLAG_C|FLAG_x)) {
+                if (!curcol) xputc('\n');
+            } else if ((flags & FLAG_1) || width+1+*len > TT.screen_width) {
+                xputc('\n');
+                width = 0;
+            } else {
+                xputc(' ');
+                width++;
+            }
+        }
+        width += *len;
+
+        if (flags & FLAG_i)
+            xprintf("% *lu ", len[1], (unsigned long)st->st_ino);
+        if (flags & FLAG_s)
+            xprintf("% *lu ", len[6], (unsigned long)st->st_blocks);
+
+        if (flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) {
+            struct tm *tm;
+            char perm[11], thyme[64], c, d, *usr, *upad, *grp, *grpad;
+            int i, bit;
+
+            perm[10]=0;
+            for (i=0; i<9; i++) {
+                bit = mode & (1<<i);
+                c = i%3;
+                if (!c && (mode & (1<<((d=i/3)+9)))) {
+                    c = "tss"[d];
+                    if (!bit) c &= ~0x20;
+                } else c = bit ? "xwr"[c] : '-';
+                perm[9-i] = c;
+            }
+
+            if (S_ISDIR(mode)) c = 'd';
+            else if (S_ISBLK(mode)) c = 'b';
+            else if (S_ISCHR(mode)) c = 'c';
+            else if (S_ISLNK(mode)) c = 'l';
+            else if (S_ISFIFO(mode)) c = 'p';
+            else if (S_ISSOCK(mode)) c = 's';
+            else c = '-';
+            *perm = c;
+
+            tm = localtime(&(st->st_mtime));
+            strftime(thyme, sizeof(thyme), "%F %H:%M", tm);
+
+            if (flags&FLAG_o) grp = grpad = toybuf+256;
+            else {
+                grp = (flags&FLAG_n) ? utoa(st->st_gid)
+                      : getgroupname(st->st_gid);
+                grpad = toybuf+256-(totals[4]-len[4]);
+            }
+
+            if (flags&FLAG_g) usr = upad = toybuf+256;
+            else {
+                upad = toybuf+255-(totals[3]-len[3]);
+                if (flags&FLAG_n) {
+                    usr = TT.uid_buf;
+                    utoa_to_buf(st->st_uid, TT.uid_buf, 12);
+                } else usr = getusername(st->st_uid);
+            }
+
+            // Coerce the st types into something we know we can print.
+            xprintf("%s% *ld %s%s%s%s% *"PRId64" %s ", perm, totals[2]+1,
+                (long)st->st_nlink, usr, upad, grp, grpad, totals[5]+1,
+                (int64_t)st->st_size, thyme);
+        }
+
+        if (flags & FLAG_q) {
+            char *p;
+            for (p=sort[next]->name; *p; p++) xputc(isprint(*p) ? *p : '?');
+        } else xprintf("%s", sort[next]->name);
+        if ((flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) && S_ISLNK(mode))
+            xprintf(" -> %s", sort[next]->symlink);
+
+        if (et) xputc(et);
+
+        // Pad columns
+        if (flags & (FLAG_C|FLAG_x)) {
+            curcol = colsizes[curcol] - *len;
+            if (curcol >= 0) xprintf("%s", toybuf+255-curcol);
+        }
+    }
+
+    if (width) xputc('\n');
+
+    // Free directory entries, recursing first if necessary.
+
+    for (ul = 0; ul<dtlen; free(sort[ul++])) {
+        if ((flags & FLAG_d) || !S_ISDIR(sort[ul]->st.st_mode)
+            || !dirtree_notdotdot(sort[ul])) continue;
+
+        // Recurse into dirs if at top of the tree or given -R
+        if (!indir->parent || (flags & FLAG_R))
+            listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]);
+    }
+    free(sort);
+    if (dirfd != AT_FDCWD) close(indir->data);
+}
+
+void ls_main(void)
+{
+    char **s, *noargs[] = {".", 0};
+    struct dirtree *dt;
+
+    // Do we have an implied -1
+    if (!isatty(1) || (toys.optflags&(FLAG_l|FLAG_o|FLAG_n|FLAG_g)))
+        toys.optflags |= FLAG_1;
+    else {
+        TT.screen_width = 80;
+        terminal_size(&TT.screen_width, NULL);
+    }
+    // The optflags parsing infrastructure should really do this for us,
+    // but currently it has "switch off when this is set", so "-dR" and "-Rd"
+    // behave differently
+    if (toys.optflags & FLAG_d) toys.optflags &= ~FLAG_R;
+
+    // Iterate through command line arguments, collecting directories and files.
+    // Non-absolute paths are relative to current directory.
+    TT.files = dirtree_add_node(0, 0, 0);
+    for (s = *toys.optargs ? toys.optargs : noargs; *s; s++) {
+        dt = dirtree_add_node(AT_FDCWD, *s,
+            (toys.optflags & (FLAG_L|FLAG_H|FLAG_l))^FLAG_l);
+
+        if (!dt) {
+            toys.exitval = 1;
+            continue;
+        }
+
+        // Typecast means double_list->prev temporarirly goes in dirtree->parent
+        dlist_add_nomalloc((struct double_list **)&TT.files->child,
+                           (struct double_list *)dt);
+    }
+
+    // Turn double_list into dirtree
+    dlist_to_dirtree(TT.files);
+
+    // Display the files we collected
+    listfiles(AT_FDCWD, TT.files);
+
+    if (CFG_TOYBOX_FREE) free(TT.files);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/mkdir.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,76 @@
+/* vi: set sw=4 ts=4:
+ *
+ * mkdir.c - Make directories
+ *
+ * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/mkdir.html
+ *
+ * TODO: Add -m
+
+USE_MKDIR(NEWTOY(mkdir, "<1p", TOYFLAG_BIN))
+
+config MKDIR
+	bool "mkdir"
+	default y
+	help
+	  usage: mkdir [-p] [dirname...]
+	  Create one or more directories.
+
+	  -p	make parent directories as needed.
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	long mode;
+)
+
+#define TT this.mkdir
+
+static int do_mkdir(char *dir)
+{
+	struct stat buf;
+	char *s;
+
+	// mkdir -p one/two/three is not an error if the path already exists,
+	// but is if "three" is a file.  The others we dereference and catch
+	// not-a-directory along the way, but the last one we must explicitly
+	// test for. Might as well do it up front.
+
+	if (!stat(dir, &buf) && !S_ISDIR(buf.st_mode)) {
+		errno = EEXIST;
+		return 1;
+	}
+
+	for (s=dir; ; s++) {
+		char save=0;
+
+		// Skip leading / of absolute paths.
+		if (s!=dir && *s == '/' && toys.optflags) {
+			save = *s;
+			*s = 0;
+		} else if (*s) continue;
+
+		if (mkdir(dir, TT.mode)<0 && (!toys.optflags || errno != EEXIST))
+			return 1;
+
+		if (!(*s = save)) break;
+	}
+
+	return 0;
+}
+
+void mkdir_main(void)
+{
+	char **s;
+
+	TT.mode = 0777;
+
+	for (s=toys.optargs; *s; s++) {
+		if (do_mkdir(*s)) {
+			perror_msg("cannot create directory '%s'", *s);
+			toys.exitval = 1;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/mkfifo.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,47 @@
+/* vi: set sw=4 ts=4:
+ *
+ * mkfifo.c - Create FIFOs (named pipes)
+ *
+ * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/009695399/utilities/mkfifo.html
+ *
+ * TODO: Add -m
+
+USE_MKFIFO(NEWTOY(mkfifo, "<1m:", TOYFLAG_BIN))
+
+config MKFIFO
+	bool "mkfifo"
+	default y
+	help
+	  usage: mkfifo [fifo_name...]
+
+	  Create FIFOs (named pipes).
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	char *m_string;
+	mode_t mode;
+)
+
+#define TT this.mkfifo
+#define FLAG_m (1)
+
+void mkfifo_main(void)
+{
+	char **s;
+
+	TT.mode = 0666;
+	if (toys.optflags & FLAG_m) {
+		TT.mode = string_to_mode(TT.m_string, 0);
+	}
+
+	for (s = toys.optargs; *s; s++) {
+		if (mknod(*s, S_IFIFO | TT.mode, 0) < 0) {
+			perror_msg("cannot create fifo '%s'", *s);
+			toys.exitval = 1;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/nice.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,41 @@
+/* vi: set sw=4 ts=4:
+ *
+ * nice.c - Run a program at a different niceness level.
+ *
+ * Copyright 2010 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/9699919799/utilities/nice.html
+
+USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_USR|TOYFLAG_BIN))
+
+config NICE
+	bool "nice"
+	default y
+	help
+	  usage: nice [-n PRIORITY] command [args...]
+
+	  Run a command line at an increased or decreased scheduling priority.
+
+	  Higher numbers make a program yield more CPU time, from -20 (highest
+	  priority) to 19 (lowest).  By default processes inherit their parent's
+	  niceness (usually 0).  By default this command adds 10 to the parent's
+	  priority.  Only root can set a negative niceness level.
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	long priority;
+)
+
+#define TT this.nice
+
+void nice_main(void)
+{
+	if (!toys.optflags) TT.priority = 10;
+
+	errno = 0;
+	if (nice(TT.priority)==-1 && errno) perror_exit("Can't set priority");
+
+	xexec(toys.optargs);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/nohup.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,42 @@
+/* vi: set sw=4 ts=4:
+ *
+ * nohup.c - run commandline with SIGHUP blocked.
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/nohup.html
+
+USE_NOHUP(NEWTOY(nohup, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+
+config NOHUP
+	bool "nohup"
+	default y
+	help
+	  usage: nohup COMMAND [ARGS...]
+
+	  Run a command that survives the end of its terminal.
+	  If stdin is a tty, redirect from /dev/null
+	  If stdout is a tty, redirect to file "nohup.out"
+*/
+
+#include "toys.h"
+
+void nohup_main(void)
+{
+	signal(SIGHUP, SIG_IGN);
+	if (isatty(1)) {
+		close(1);
+		if (-1 == open("nohup.out", O_CREAT|O_APPEND|O_WRONLY,
+				S_IRUSR|S_IWUSR ))
+		{
+			char *temp = getenv("HOME");
+			temp = xmsprintf("%s/%s", temp ? temp : "", "nohup.out");
+			xcreate(temp, O_CREAT|O_APPEND|O_WRONLY, S_IRUSR|S_IWUSR);
+		}
+	}
+	if (isatty(0)) {
+		close(0);
+		open("/dev/null", O_RDONLY);
+	}
+	xexec(toys.optargs);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/od.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,274 @@
+/* vi: set sw=4 ts=4:
+ *
+ * od.c - Provide octal/hex dumps of data
+ *
+ * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
+ * Copyright 2012 Rob Landley <rob@landley.net>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/od.html
+
+USE_OD(NEWTOY(od, "j#vN#xsodcbA:t*", TOYFLAG_USR|TOYFLAG_BIN))
+
+config OD
+	bool "od"
+	default y
+	help
+          usage: od [-bdosxv] [-j #] [-N #] [-A doxn] [-t arg]
+
+	  -A	Address base (decimal, octal, hexdecimal, none)
+	  -t	output type(s) a (ascii) c (char) d (decimal) foux
+*/
+
+#include "toys.h"
+
+#define FLAG_t	(1 << 0)
+#define FLAG_A	(1 << 1)
+#define FLAG_b	(1 << 2)
+#define FLAG_c	(1 << 3)
+#define FLAG_d	(1 << 4)
+#define FLAG_o	(1 << 5)
+#define FLAG_s	(1 << 6)
+#define FLAG_x	(1 << 7)
+#define FLAG_N	(1 << 8)
+#define FLAG_v  (1 << 9)
+
+DEFINE_GLOBALS(
+	struct arg_list *output_base;
+	char *address_base;
+	long max_count;
+	long jump_bytes;
+
+	unsigned types, leftover, star, address_idx;
+	char *buf;
+	uint64_t bufs[4]; // force 64-bit alignment
+	off_t pos;
+)
+
+#define TT this.od
+
+static char *ascii = "nulsohstxetxeotenqackbel bs ht nl vt ff cr so si"
+	"dledc1dc2dc3dc4naksynetbcan emsubesc fs gs rs us sp";
+
+struct odtype {
+	int type;
+	int size;
+};
+
+static void od_outline(void)
+{
+	unsigned flags = toys.optflags;
+	char *abases[] = {"", "%07d", "%07o", "%06x"};
+	struct odtype *types = (struct odtype *)toybuf, *t;
+	int i, len;
+
+	if (TT.leftover<16) memset(TT.buf+TT.leftover, 0, 16-TT.leftover);
+
+	// Handle duplciate lines as *
+	if (!(flags&FLAG_v) && TT.jump_bytes != TT.pos && TT.leftover
+		&& !memcmp(TT.bufs, TT.bufs + 2, 16))
+	{
+		if (!TT.star) {
+			xputs("*");
+			TT.star++;
+		}
+
+	// Print line position
+	} else {
+		TT.star = 0;
+
+		xprintf(abases[TT.address_idx], TT.pos);
+		if (!TT.leftover) {
+			if (TT.address_idx) xputc('\n');
+			return;
+		}
+	}
+
+	TT.pos += len = TT.leftover;
+	TT.leftover = 0;
+	if (TT.star) return;
+
+	// For each output type, print one line
+
+	for (i=0; i<TT.types; i++) {
+		int j = 0, pad = i ? 8 : 0;
+		char buf[128];
+
+		t = types+i;
+		while (j<len) {
+			unsigned k;
+			int throw = 0;
+
+			// Handle ascii
+			if (t->type < 2) {
+				char c = TT.buf[j++];
+				pad += 4;
+
+				if (!t->type) {
+					c &= 127;
+					if (c<=32) sprintf(buf, "%.3s", ascii+(3*c));
+					else if (c==127) strcpy(buf, "del");
+					else sprintf(buf, "%c", c);
+				} else {
+					char *bfnrtav = "\b\f\n\r\t\a\v", *s = strchr(bfnrtav, c);
+					if (s) sprintf(buf, "\\%c", "bfnrtav0"[s-bfnrtav]);
+					else if (c < 32 || c >= 127) sprintf(buf, "%03o", c);
+					else {
+						// TODO: this should be UTF8 aware.
+						sprintf(buf, "%c", c);
+					}
+				}
+			} else if (CFG_TOYBOX_FLOAT && t->type == 6) {
+				long double ld;
+				union {float f; double d; long double ld;} fdl;
+
+				memcpy(&fdl, TT.buf+j, t->size);
+				j += t->size;
+				if (sizeof(float) == t->size) {
+					ld = fdl.f;
+					pad += (throw = 8)+7;
+				} else if (sizeof(double) == t->size) {
+					ld = fdl.d;
+					pad += (throw = 17)+8;
+				} else if (sizeof(long double) == t->size) {
+					ld = fdl.ld;
+					pad += (throw = 21)+9;
+				} else error_exit("bad -tf '%d'", t->size);
+
+				sprintf(buf, "%.*Le", throw, ld);
+			// Integer types
+			} else {
+				unsigned long long ll = 0, or;
+				char *c[] = {"%*lld", "%*llu", "%0*llo", "%0*llx"},
+					*class = c[t->type-2];
+
+				// Work out width of field
+				if (t->size == 8) {
+					or = -1LL;
+					if (t->type == 2) or >>= 1;
+				} else or = (1LL<<(8*t->size))-1;
+				throw = sprintf(buf, class, 0, or);
+
+				// Accumulate integer based on size argument
+				for (k=0; k < t->size; k++) {
+					or = TT.buf[j++];
+					ll |= or << (8*(IS_BIG_ENDIAN ? t->size-k-1 : k));
+				}
+
+				// Handle negative values
+				if (t->type == 2) {
+					or = sizeof(or) - t->size;
+					throw++;
+					if (or && (ll & (1l<<((8*t->size)-1))))
+						ll |= ((or<<(8*or))-1) << (8*t->size);
+				}
+
+				sprintf(buf, class, throw, ll);
+				pad += throw+1;
+			}
+			xprintf("%*s", pad, buf);
+			pad = 0;
+		}
+		xputc('\n');
+	}
+
+	// buffer toggle for "same as last time" check.
+	TT.buf = (char *)((TT.buf == (char *)TT.bufs) ? TT.bufs+2 : TT.bufs);
+}
+
+static void do_od(int fd, char *name)
+{
+	// Skip input, possibly more than one entire file.
+	if (TT.jump_bytes < TT.pos) {
+		off_t off = lskip(fd, TT.jump_bytes);
+		if (off > 0) TT.pos += off;
+		if (TT.jump_bytes < TT.pos) return;
+	}
+
+	for(;;) {
+		char *buf = TT.buf + TT.leftover;
+		int len = 16 - TT.leftover;
+
+		if (toys.optflags & FLAG_N) {
+			if (!TT.max_count) break;
+			if (TT.max_count < len) len = TT.max_count;
+		}
+
+		len = readall(fd, buf, len);
+		if (len < 0) {
+			perror_msg("%s", name);
+			break;
+		}
+		if (TT.max_count) TT.max_count -= len;
+		TT.leftover += len;
+		if (TT.leftover < 16) break;
+
+		od_outline();
+	}
+}
+
+static void append_base(char *base)
+{
+	char *s = base;
+	struct odtype *types = (struct odtype *)toybuf;
+	int type;
+
+	for (;;) {
+		int size = 1;
+
+		if (!*s) return;
+		if (TT.types >= sizeof(toybuf)/sizeof(struct odtype)) break;
+		if (-1 == (type = stridx("acduox"USE_TOYBOX_FLOAT("f"), *(s++)))) break;
+
+		if (isdigit(*s)) {
+			size = strtol(s, &s, 10);
+			if (type < 2 && size != 1) break;
+			if (CFG_TOYBOX_FLOAT && type == 6 && size == sizeof(long double));
+			else if (size < 0 || size > 8) break;
+		} else if (CFG_TOYBOX_FLOAT && type == 6) {
+			int sizes[] = {sizeof(float), sizeof(double), sizeof(long double)};
+			if (-1 == (size = stridx("FDL", *s))) size = sizeof(double);
+			else {
+				s++;
+				size = sizes[size];
+			}
+		} else if (type > 1) {
+			if (-1 == (size = stridx("CSIL", *s))) size = 4;
+			else {
+				s++;
+				size = 1 << size;
+			}
+		}
+
+		types[TT.types].type = type;
+		types[TT.types].size = size;
+		TT.types++;
+	}
+
+	error_exit("bad -t %s", base);
+}
+
+void od_main(void)
+{
+	struct arg_list *arg;
+
+	TT.buf = (char *)TT.bufs;
+
+	if (!TT.address_base) TT.address_idx = 2;
+	else if (0>(TT.address_idx = stridx("ndox", *TT.address_base)))
+		error_exit("bad -A '%c'", *TT.address_base);
+
+	// Collect -t entries
+
+	for (arg = TT.output_base; arg; arg = arg->next) append_base(arg->arg);
+	if (toys.optflags & FLAG_b) append_base("o1");
+	if (toys.optflags & FLAG_d) append_base("u2");
+	if (toys.optflags & FLAG_o) append_base("o2");
+	if (toys.optflags & FLAG_s) append_base("d2");
+	if (toys.optflags & FLAG_x) append_base("x2");
+	if (!TT.output_base) append_base("o2");
+
+	loopfiles(toys.optargs, do_od);
+
+	if (TT.leftover) od_outline();
+	od_outline();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/patch.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,412 @@
+/* vi: set sw=4 ts=4:
+ *
+ * patch.c - Apply a "universal" diff.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * see http://www.opengroup.org/onlinepubs/009695399/utilities/patch.html
+ * (But only does -u, because who still cares about "ed"?)
+ *
+ * TODO:
+ * -b backup
+ * -l treat all whitespace as a single space
+ * -N ignore already applied
+ * -d chdir first
+ * -D define wrap #ifdef and #ifndef around changes
+ * -o outfile output here instead of in place
+ * -r rejectfile write rejected hunks to this file
+ *
+ * -E remove empty files --remove-empty-files
+ * -f force (no questions asked)
+ * -F fuzz (number, default 2)
+ * [file] which file to patch
+
+USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"up#i:R", TOYFLAG_USR|TOYFLAG_BIN))
+
+config PATCH
+	bool "patch"
+	default y
+	help
+	  usage: patch [-i file] [-p depth] [-Ru]
+
+	  Apply a unified diff to one or more files.
+
+	  -i	Input file (defaults=stdin)
+	  -p	number of '/' to strip from start of file paths (default=all)
+	  -R	Reverse patch.
+	  -u	Ignored (only handles "unified" diffs)
+
+	  This version of patch only handles unified diffs, and only modifies
+	  a file when all all hunks to that file apply.  Patch prints failed
+	  hunks to stderr, and exits with nonzero status if any hunks fail.
+
+	  A file compared against /dev/null (or with a date <= the epoch) is
+	  created/deleted as appropriate.
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	char *infile;
+	long prefix;
+
+	struct double_list *current_hunk;
+	long oldline, oldlen, newline, newlen;
+	long linenum;
+	int context, state, filein, fileout, filepatch, hunknum;
+	char *tempname;
+)
+
+#define TT this.patch
+
+#define FLAG_REVERSE 1
+#define FLAG_PATHLEN 4
+
+// Dispose of a line of input, either by writing it out or discarding it.
+
+// state < 2: just free
+// state = 2: write whole line to stderr
+// state = 3: write whole line to fileout
+// state > 3: write line+1 to fileout when *line != state
+
+#define PATCH_DEBUG (CFG_TOYBOX_DEBUG && (toys.optflags & 16))
+
+static void do_line(void *data)
+{
+	struct double_list *dlist = (struct double_list *)data;
+
+	if (TT.state>1 && *dlist->data != TT.state) {
+		char *s = dlist->data+(TT.state>3 ? 1 : 0);
+		int i = TT.state == 2 ? 2 : TT.fileout;
+
+		xwrite(i, s, strlen(s));
+		xwrite(i, "\n", 1);
+	}
+
+	if (PATCH_DEBUG) fprintf(stderr, "DO %d: %s\n", TT.state, dlist->data);
+
+	free(dlist->data);
+	free(data);
+}
+
+static void finish_oldfile(void)
+{
+	if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname);
+	TT.fileout = TT.filein = -1;
+}
+
+static void fail_hunk(void)
+{
+	if (!TT.current_hunk) return;
+	TT.current_hunk->prev->next = 0;
+
+	fprintf(stderr, "Hunk %d FAILED %ld/%ld.\n",
+			TT.hunknum, TT.oldline, TT.newline);
+	toys.exitval = 1;
+
+	// If we got to this point, we've seeked to the end.  Discard changes to
+	// this file and advance to next file.
+
+	TT.state = 2;
+	llist_traverse(TT.current_hunk, do_line);
+	TT.current_hunk = NULL;
+	delete_tempfile(TT.filein, TT.fileout, &TT.tempname);
+	TT.state = 0;
+}
+
+// Given a hunk of a unified diff, make the appropriate change to the file.
+// This does not use the location information, but instead treats a hunk
+// as a sort of regex.  Copies data from input to output until it finds
+// the change to be made, then outputs the changed data and returns.
+// (Finding EOF first is an error.)  This is a single pass operation, so
+// multiple hunks must occur in order in the file.
+
+static int apply_one_hunk(void)
+{
+	struct double_list *plist, *buf = NULL, *check;
+	int matcheof = 0, reverse = toys.optflags & FLAG_REVERSE, backwarn = 0;
+
+	// Break doubly linked list so we can use singly linked traversal function.
+	TT.current_hunk->prev->next = NULL;
+
+	// Match EOF if there aren't as many ending context lines as beginning
+	for (plist = TT.current_hunk; plist; plist = plist->next) {
+		if (plist->data[0]==' ') matcheof++;
+		else matcheof = 0;
+		if (PATCH_DEBUG) fprintf(stderr, "HUNK:%s\n", plist->data);
+	}
+	matcheof = matcheof < TT.context;
+
+	if (PATCH_DEBUG) fprintf(stderr,"MATCHEOF=%c\n", matcheof ? 'Y' : 'N');
+
+	// Loop through input data searching for this hunk.  Match all context
+	// lines and all lines to be removed until we've found the end of a
+	// complete hunk.
+	plist = TT.current_hunk;
+	buf = NULL;
+	if (TT.context) for (;;) {
+		char *data = get_line(TT.filein);
+
+		TT.linenum++;
+
+		// Figure out which line of hunk to compare with next.  (Skip lines
+		// of the hunk we'd be adding.)
+		while (plist && *plist->data == "+-"[reverse]) {
+			if (data && !strcmp(data, plist->data+1)) {
+				if (!backwarn) backwarn = TT.linenum;
+			}
+			plist = plist->next;
+		}
+
+		// Is this EOF?
+		if (!data) {
+			if (PATCH_DEBUG) fprintf(stderr, "INEOF\n");
+
+			// Does this hunk need to match EOF?
+			if (!plist && matcheof) break;
+
+			if (backwarn)
+				fprintf(stderr, "Possibly reversed hunk %d at %ld\n",
+						TT.hunknum, TT.linenum);
+
+			// File ended before we found a place for this hunk.
+			fail_hunk();
+			goto done;
+		} else if (PATCH_DEBUG) fprintf(stderr, "IN: %s\n", data);
+		check = dlist_add(&buf, data);
+
+		// Compare this line with next expected line of hunk.
+		// todo: teach the strcmp() to ignore whitespace.
+
+		// A match can fail because the next line doesn't match, or because
+		// we hit the end of a hunk that needed EOF, and this isn't EOF.
+
+		// If match failed, flush first line of buffered data and
+		// recheck buffered data for a new match until we find one or run
+		// out of buffer.
+
+		for (;;) {
+			if (!plist || strcmp(check->data, plist->data+1)) {
+				// Match failed.  Write out first line of buffered data and
+				// recheck remaining buffered data for a new match.
+	
+				if (PATCH_DEBUG)
+					fprintf(stderr, "NOT: %s\n", plist->data);
+
+				TT.state = 3;
+				check = llist_pop(&buf);
+				check->prev->next = buf;
+				buf->prev = check->prev;
+				do_line(check);
+				plist = TT.current_hunk;
+
+				// If we've reached the end of the buffer without confirming a
+				// match, read more lines.
+				if (check==buf) {
+					buf = 0;
+					break;
+				}
+				check = buf;
+			} else {
+				if (PATCH_DEBUG)
+					fprintf(stderr, "MAYBE: %s\n", plist->data);
+				// This line matches.  Advance plist, detect successful match.
+				plist = plist->next;
+				if (!plist && !matcheof) goto out;
+				check = check->next;
+				if (check == buf) break;
+			}
+		}
+	}
+out:
+	// We have a match.  Emit changed data.
+	TT.state = "-+"[reverse];
+	llist_traverse(TT.current_hunk, do_line);
+	TT.current_hunk = NULL;
+	TT.state = 1;
+done:
+	if (buf) {
+		buf->prev->next = NULL;
+		llist_traverse(buf, do_line);
+	}
+
+	return TT.state;
+}
+
+// Read a patch file and find hunks, opening/creating/deleting files.
+// Call apply_one_hunk() on each hunk.
+
+// state 0: Not in a hunk, look for +++.
+// state 1: Found +++ file indicator, look for @@
+// state 2: In hunk: counting initial context lines
+// state 3: In hunk: getting body
+
+void patch_main(void)
+{
+	int reverse = toys.optflags&FLAG_REVERSE, state = 0, patchlinenum = 0,
+		strip = 0;
+	char *oldname = NULL, *newname = NULL;
+
+	if (TT.infile) TT.filepatch = xopen(TT.infile, O_RDONLY);
+	TT.filein = TT.fileout = -1;
+
+	// Loop through the lines in the patch
+	for (;;) {
+		char *patchline;
+
+		patchline = get_line(TT.filepatch);
+		if (!patchline) break;
+
+		// Other versions of patch accept damaged patches,
+		// so we need to also.
+		if (strip || !patchlinenum++) {
+			int len = strlen(patchline);
+			if (patchline[len-1] == '\r') {
+				if (!strip) fprintf(stderr, "Removing DOS newlines\n");
+				strip = 1;
+				patchline[len-1]=0;
+			}
+		}
+		if (!*patchline) {
+			free(patchline);
+			patchline = xstrdup(" ");
+		}
+
+		// Are we assembling a hunk?
+		if (state >= 2) {
+			if (*patchline==' ' || *patchline=='+' || *patchline=='-') {
+				dlist_add(&TT.current_hunk, patchline);
+
+				if (*patchline != '+') TT.oldlen--;
+				if (*patchline != '-') TT.newlen--;
+
+				// Context line?
+				if (*patchline==' ' && state==2) TT.context++;
+				else state=3;
+
+				// If we've consumed all expected hunk lines, apply the hunk.
+
+				if (!TT.oldlen && !TT.newlen) state = apply_one_hunk();
+				continue;
+			}
+			fail_hunk();
+			state = 0;
+			continue;
+		}
+
+		// Open a new file?
+		if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) {
+			char *s, **name = &oldname;
+			int i;
+
+			if (*patchline == '+') {
+				name = &newname;
+				state = 1;
+			}
+
+			free(*name);
+			finish_oldfile();
+
+			// Trim date from end of filename (if any).  We don't care.
+			for (s = patchline+4; *s && *s!='\t'; s++)
+				if (*s=='\\' && s[1]) s++;
+			i = atoi(s);
+			if (i>1900 && i<=1970)
+				*name = xstrdup("/dev/null");
+			else {
+				*s = 0;
+				*name = xstrdup(patchline+4);
+			}
+
+			// We defer actually opening the file because svn produces broken
+			// patches that don't signal they want to create a new file the
+			// way the patch man page says, so you have to read the first hunk
+			// and _guess_.
+
+		// Start a new hunk?  Usually @@ -oldline,oldlen +newline,newlen @@
+		// but a missing ,value means the value is 1.
+		} else if (state == 1 && !strncmp("@@ -", patchline, 4)) {
+			int i;
+			char *s = patchline+4;
+
+			// Read oldline[,oldlen] +newline[,newlen]
+
+			TT.oldlen = TT.newlen = 1;
+			TT.oldline = strtol(s, &s, 10);
+			if (*s == ',') TT.oldlen=strtol(s+1, &s, 10);
+			TT.newline = strtol(s+2, &s, 10);
+			if (*s == ',') TT.newlen = strtol(s+1, &s, 10);
+
+			TT.context = 0;
+			state = 2;
+
+			// If this is the first hunk, open the file.
+			if (TT.filein == -1) {
+				int oldsum, newsum, del = 0;
+				char *name;
+
+ 				oldsum = TT.oldline + TT.oldlen;
+				newsum = TT.newline + TT.newlen;
+
+				name = reverse ? oldname : newname;
+
+				// We're deleting oldname if new file is /dev/null (before -p)
+				// or if new hunk is empty (zero context) after patching
+				if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum))
+				{
+					name = reverse ? newname : oldname;
+					del++;
+				}
+
+				// handle -p path truncation.
+				for (i = 0, s = name; *s;) {
+					if ((toys.optflags & FLAG_PATHLEN) && TT.prefix == i) break;
+					if (*s++ != '/') continue;
+					while (*s == '/') s++;
+					name = s;
+					i++;
+				}
+
+				if (del) {
+					printf("removing %s\n", name);
+					xunlink(name);
+					state = 0;
+				// If we've got a file to open, do so.
+				} else if (!(toys.optflags & FLAG_PATHLEN) || i <= TT.prefix) {
+					// If the old file was null, we're creating a new one.
+					if (!strcmp(oldname, "/dev/null") || !oldsum) {
+						printf("creating %s\n", name);
+						s = strrchr(name, '/');
+						if (s) {
+							*s = 0;
+							xmkpath(name, -1);
+							*s = '/';
+						}
+						TT.filein = xcreate(name, O_CREAT|O_EXCL|O_RDWR, 0666);
+					} else {
+						printf("patching %s\n", name);
+						TT.filein = xopen(name, O_RDWR);
+					}
+					TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname);
+					TT.linenum = 0;
+					TT.hunknum = 0;
+				}
+			}
+
+			TT.hunknum++;
+
+			continue;
+		}
+
+		// If we didn't continue above, discard this line.
+		free(patchline);
+	}
+
+	finish_oldfile();
+
+	if (CFG_TOYBOX_FREE) {
+		close(TT.filepatch);
+		free(oldname);
+		free(newname);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/pwd.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,30 @@
+/* vi: set sw=4 ts=4:
+ *
+ * pwd.c - Print working directory.
+ *
+ * Copyright 2006 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/echo.html
+ *
+ * TODO: add -L -P
+
+USE_PWD(NEWTOY(pwd, NULL, TOYFLAG_BIN))
+
+config PWD
+	bool "pwd"
+	default y
+	help
+	  usage: pwd
+
+	  The print working directory command prints the current directory.
+*/
+
+#include "toys.h"
+
+void pwd_main(void)
+{
+	char *pwd = xgetcwd();
+
+	xprintf("%s\n", pwd);
+	if (CFG_TOYBOX_FREE) free(pwd);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/rmdir.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,43 @@
+/* vi: set sw=4 ts=4:
+ *
+ * rmdir.c - remove directory/path
+ *
+ * Copyright 2008 Rob Landley <rob@landley.net>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/rmdir.html
+
+USE_RMDIR(NEWTOY(rmdir, "<1p", TOYFLAG_BIN))
+
+config RMDIR
+	bool "rmdir"
+	default y
+	help
+	  usage: rmdir [-p] [dirname...]
+	  Remove one or more directories.
+
+	  -p	Remove path.
+*/
+
+#include "toys.h"
+
+static void do_rmdir(char *name)
+{
+	for (;;) {
+		char *temp;
+
+		if (rmdir(name)) {
+			perror_msg("%s",name);
+			return;
+		}
+		if (!toys.optflags) return;
+		if (!(temp=strrchr(name,'/'))) return;
+		*temp=0;
+	}
+}
+
+void rmdir_main(void)
+{
+	char **s;
+
+	for (s=toys.optargs; *s; s++) do_rmdir(*s);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/sed.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,63 @@
+/* vi: set sw=4 ts=4:
+ *
+ * sed.c - Stream editor.
+ *
+ * Copyright 2008 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/sed.c
+
+USE_SED(NEWTOY(sed, "irne*", TOYFLAG_BIN))
+
+config SED
+	bool "sed"
+	default n
+	help
+	  usage: sed [-irn] {command | [-e command]...} [FILE...]
+
+	  Stream EDitor, transforms text by appling commands to each line
+	  of input.
+*/
+
+#include "toys.h"
+#include "lib/xregcomp.h"
+
+DEFINE_GLOBALS(
+	struct arg_list *commands;
+)
+
+#define TT this.sed
+
+struct sed_command {
+	// Doubly linked list of commands.
+	struct sed_command *next, *prev;
+
+	// Regexes for s/match/data/ and /match_begin/,/match_end/command
+	regex_t *match, *match_begin, *match_end;
+
+	// For numeric ranges ala 10,20command
+	int first_line, last_line;
+
+	// Which match to replace, 0 for all.
+	int which;
+
+	// s and w commands can write to a file.  Slight optimization: we use 0
+	// instead of -1 to mean no file here, because even when there's no stdin
+	// our input file would take fd 0.
+	int outfd;
+
+	// Data string for (saicytb)
+	char *data;
+
+	// Which command letter is this?
+	char command;
+};
+
+void sed_main(void)
+{
+	struct arg_list *test;
+
+	for (test = TT.commands; test; test = test->next)
+		dprintf(2,"command=%s\n",test->arg);
+
+	printf("Hello world\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/sleep.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,51 @@
+/* vi: set sw=4 ts=4:
+ *
+ * sleep.c - Wait for a number of seconds.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/sleep.html
+
+USE_SLEEP(NEWTOY(sleep, "<1", TOYFLAG_BIN))
+
+config SLEEP
+	bool "sleep"
+	default y
+	help
+	  usage: sleep SECONDS
+
+	  Wait before exiting.
+
+config SLEEP_FLOAT
+	bool
+	default y
+	depends on SLEEP && TOYBOX_FLOAT
+	help
+	  The delay can be a decimal fraction. An optional suffix can be "m"
+	  (minutes), "h" (hours), "d" (days), or "s" (seconds, the default).
+*/
+
+#include "toys.h"
+
+void sleep_main(void)
+{
+
+	if (!CFG_TOYBOX_FLOAT) toys.exitval = sleep(atol(*toys.optargs));
+	else {
+		char *arg;
+		double d = strtod(*toys.optargs, &arg);
+		struct timespec tv;
+
+		// Parse suffix
+		if (*arg) {
+			int ismhd[]={1,60,3600,86400};
+			char *smhd = "smhd", *c = strchr(smhd, *arg);
+			if (!c) error_exit("Unknown suffix '%c'", *arg);
+			d *= ismhd[c-smhd];
+		}
+
+		tv.tv_nsec=1000000000*(d-(tv.tv_sec = (unsigned long)d));
+		toys.exitval = !!nanosleep(&tv, NULL);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/sort.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,421 @@
+/* vi: set sw=4 ts=4:
+ *
+ * sort.c - put input lines into order
+ *
+ * Copyright 2004, 2008 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html
+
+USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")USE_SORT_BIG("S:T:m" "o:k*t:xbMcszdfi") "run", TOYFLAG_USR|TOYFLAG_BIN))
+
+config SORT
+    bool "sort"
+    default y
+    help
+      usage: sort [-run] [FILE...]
+
+      Sort all lines of text from input files (or stdin) to stdout.
+
+      -r    reverse
+      -u    unique lines only
+      -n    numeric order (instead of alphabetical)
+
+config SORT_BIG
+    bool "SuSv3 options (Support -ktcsbdfiozM)"
+    default y
+    depends on SORT
+    help
+      usage: sort [-bcdfiMsz] [-k#[,#[x]] [-t X]] [-o FILE]
+
+      -b    ignore leading blanks (or trailing blanks in second part of key)
+      -c    check whether input is sorted
+      -d    dictionary order (use alphanumeric and whitespace chars only)
+      -f    force uppercase (case insensitive sort)
+      -i    ignore nonprinting characters
+      -M    month sort (jan, feb, etc).
+      -x    Hexadecimal numerical sort
+      -s    skip fallback sort (only sort with keys)
+      -z    zero (null) terminated input
+      -k    sort by "key" (see below)
+      -t    use a key separator other than whitespace
+      -o    output to FILE instead of stdout
+
+      Sorting by key looks at a subset of the words on each line.  -k2
+      uses the second word to the end of the line, -k2,2 looks at only
+      the second word, -k2,4 looks from the start of the second to the end
+      of the fourth word.  Specifying multiple keys uses the later keys as
+      tie breakers, in order.  A type specifier appended to a sort key
+          (such as -2,2n) applies only to sorting that key.
+
+config SORT_FLOAT
+    bool "Floating point (-g)"
+    default y
+    depends on SORT_BIG
+    help
+      usage: sort [-g]
+
+      This version of sort requires floating point.
+
+      -g    general numeric sort (double precision with nan and inf)
+
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+    char *key_separator;
+    struct arg_list *raw_keys;
+    char *outfile;
+    char *ignore1, ignore2;   // GNU compatability NOPs for -S and -T.
+
+    void *key_list;
+    int linecount;
+    char **lines;
+)
+
+#define TT this.sort
+
+// The sort types are n, g, and M.
+// u, c, s, and z apply to top level only, not to keys.
+// b at top level implies bb.
+// The remaining options can be applied to search keys.
+
+#define FLAG_n  (1<<0)  // Sort type: numeric
+#define FLAG_u  (1<<1)  // Unique
+#define FLAG_r  (1<<2)  // Reverse output order
+
+#define FLAG_i  (1<<3)  // Ignore !isprint()
+#define FLAG_f  (1<<4)  // Force uppercase
+#define FLAG_d  (1<<5)  // Ignore !(isalnum()|isspace())
+#define FLAG_z  (1<<6)  // Input is null terminated, not \n
+#define FLAG_s  (1<<7)  // Stable sort, no ascii fallback at end
+#define FLAG_c  (1<<8)  // Check only.  No output, exit(!ordered)
+#define FLAG_M  (1<<9)  // Sort type: date
+#define FLAG_b  (1<<10) // Ignore leading blanks
+#define FLAG_x  (1<<11) // Hex sort
+#define FLAG_g  (1<<18) // Sort type: strtod()
+
+// Left off dealing with FLAG_b/FLAG_bb logic...
+
+#define FLAG_bb (1<<31)  // Ignore trailing blanks
+
+struct sort_key
+{
+    struct sort_key *next_key;  // linked list
+    unsigned range[4];          // start word, start char, end word, end char
+    int flags;
+};
+
+// Copy of the part of this string corresponding to a key/flags.
+
+static char *get_key_data(char *str, struct sort_key *key, int flags)
+{
+    int start=0, end, len, i, j;
+
+    // Special case whole string, so we don't have to make a copy
+
+    if(key->range[0]==1 && !key->range[1] && !key->range[2] && !key->range[3]
+        && !(flags&(FLAG_b&FLAG_d&FLAG_f&FLAG_i&FLAG_bb))) return str;
+
+    // Find start of key on first pass, end on second pass
+
+    len = strlen(str);
+    for (j=0; j<2; j++) {
+        if (!key->range[2*j]) end=len;
+
+        // Loop through fields
+        else {
+            end=0;
+            for (i=1; i < key->range[2*j]+j; i++) {
+
+                // Skip leading blanks
+                if (str[end] && !TT.key_separator)
+                    while (isspace(str[end])) end++;
+
+                // Skip body of key
+                for (; str[end]; end++) {
+                    if (TT.key_separator) {
+                        if (str[end]==*TT.key_separator) break;
+                    } else if (isspace(str[end])) break;
+                }
+            }
+        }
+        if (!j) start=end;
+    }
+
+    // Key with explicit separator starts after the separator
+    if (TT.key_separator && str[start]==*TT.key_separator) start++;
+
+    // Strip leading and trailing whitespace if necessary
+    if (flags&FLAG_b) while (isspace(str[start])) start++;
+    if (flags&FLAG_bb) while (end>start && isspace(str[end-1])) end--;
+
+    // Handle offsets on start and end
+    if (key->range[3]) {
+        end += key->range[3]-1;
+        if (end>len) end=len;
+    }
+    if (key->range[1]) {
+        start += key->range[1]-1;
+        if (start>len) start=len;
+    }
+
+    // Make the copy
+    if (end<start) end=start;
+    str = xstrndup(str+start, end-start);
+
+    // Handle -d
+    if (flags&FLAG_d) {
+        for (start = end = 0; str[end]; end++)
+            if (isspace(str[end]) || isalnum(str[end])) str[start++] = str[end];
+        str[start] = 0;
+    }
+
+    // Handle -i
+    if (flags&FLAG_i) {
+        for (start = end = 0; str[end]; end++)
+            if (isprint(str[end])) str[start++] = str[end];
+        str[start] = 0;
+    }
+
+    // Handle -f
+    if (flags*FLAG_f) for(i=0; str[i]; i++) str[i] = toupper(str[i]);
+
+    return str;
+}
+
+// append a sort_key to key_list.
+
+static struct sort_key *add_key(void)
+{
+    void **stupid_compiler = &TT.key_list;
+    struct sort_key **pkey = (struct sort_key **)stupid_compiler;
+
+    while (*pkey) pkey = &((*pkey)->next_key);
+    return *pkey = xzalloc(sizeof(struct sort_key));
+}
+
+// Perform actual comparison
+static int compare_values(int flags, char *x, char *y)
+{
+    int ff = flags & (FLAG_n|FLAG_g|FLAG_M|FLAG_x);
+
+    // Ascii sort
+    if (!ff) return strcmp(x, y);
+
+    if (CFG_SORT_FLOAT && ff == FLAG_g) {
+        char *xx,*yy;
+        double dx = strtod(x,&xx), dy = strtod(y,&yy);
+        int xinf, yinf;
+
+        // not numbers < NaN < -infinity < numbers < +infinity
+
+        if (x==xx) return y==yy ? 0 : -1;
+        if (y==yy) return 1;
+
+        // Check for isnan
+        if (dx!=dx) return (dy!=dy) ? 0 : -1;
+        if (dy!=dy) return 1;
+
+        // Check for infinity.  (Could underflow, but avoids needing libm.)
+        xinf = (1.0/dx == 0.0);
+        yinf = (1.0/dy == 0.0);
+        if (xinf) {
+            if(dx<0) return (yinf && dy<0) ? 0 : -1;
+            return (yinf && dy>0) ? 0 : 1;
+        }
+        if (yinf) return dy<0 ? 1 : -1;
+
+        return dx>dy ? 1 : (dx<dy ? -1 : 0);
+    } else if (CFG_SORT_BIG && ff == FLAG_M) {
+        struct tm thyme;
+        int dx;
+        char *xx,*yy;
+
+        xx = strptime(x,"%b",&thyme);
+        dx = thyme.tm_mon;
+        yy = strptime(y,"%b",&thyme);
+        if (!xx) return !yy ? 0 : -1;
+        else if (!yy) return 1;
+        else return dx==thyme.tm_mon ? 0 : dx-thyme.tm_mon;
+
+    } else if (CFG_SORT_BIG && ff == FLAG_x) {
+        return strtol(x, NULL, 16)-strtol(y, NULL, 16);
+    // This has to be ff == FLAG_n
+    } else {
+        // Full floating point version of -n
+        if (CFG_SORT_FLOAT) {
+            double dx = atof(x), dy = atof(y);
+
+            return dx>dy ? 1 : (dx<dy ? -1 : 0);
+        // Integer version of -n for tiny systems
+        } else return atoi(x)-atoi(y);
+    }
+}
+
+
+// Callback from qsort(): Iterate through key_list and perform comparisons.
+static int compare_keys(const void *xarg, const void *yarg)
+{
+    int flags = toys.optflags, retval = 0;
+    char *x, *y, *xx = *(char **)xarg, *yy = *(char **)yarg;
+    struct sort_key *key;
+
+    if (CFG_SORT_BIG) {
+        for (key=(struct sort_key *)TT.key_list; !retval && key;
+             key = key->next_key)
+        {
+            flags = key->flags ? key->flags : toys.optflags;
+
+            // Chop out and modify key chunks, handling -dfib
+
+            x = get_key_data(xx, key, flags);
+            y = get_key_data(yy, key, flags);
+
+            retval = compare_values(flags, x, y);
+
+            // Free the copies get_key_data() made.
+
+            if (x != xx) free(x);
+            if (y != yy) free(y);
+
+            if (retval) break;
+        }
+    } else retval = compare_values(flags, xx, yy);
+
+    // Perform fallback sort if necessary
+    if (!retval && !(CFG_SORT_BIG && (toys.optflags&FLAG_s))) {
+        retval = strcmp(xx, yy);
+        flags = toys.optflags;
+    }
+
+    return retval * ((flags&FLAG_r) ? -1 : 1);
+}
+
+// Callback from loopfiles to handle input files.
+static void sort_read(int fd, char *name)
+{
+    // Read each line from file, appending to a big array.
+
+    for (;;) {
+        char * line = (CFG_SORT_BIG && (toys.optflags&FLAG_z))
+                       ? get_rawline(fd, NULL, 0) : get_line(fd);
+
+        if (!line) break;
+
+        // handle -c here so we don't allocate more memory than necessary.
+        if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) {
+            int j = (toys.optflags&FLAG_u) ? -1 : 0;
+
+            if (TT.lines && compare_keys((void *)&TT.lines, &line)>j)
+                error_exit("%s: Check line %d\n", name, TT.linecount);
+            free(TT.lines);
+            TT.lines = (char **)line;
+        } else {
+            if (!(TT.linecount&63))
+                TT.lines = xrealloc(TT.lines, sizeof(char *)*(TT.linecount+64));
+            TT.lines[TT.linecount] = line;
+        }
+        TT.linecount++;
+    }
+}
+
+void sort_main(void)
+{
+    int idx, fd = 1;
+
+    // Open output file if necessary.
+    if (CFG_SORT_BIG && TT.outfile)
+        fd = xcreate(TT.outfile, O_CREAT|O_TRUNC|O_WRONLY, 0666);
+
+    // Parse -k sort keys.
+    if (CFG_SORT_BIG && TT.raw_keys) {
+        struct arg_list *arg;
+ 
+        for (arg = TT.raw_keys; arg; arg = arg->next) {
+            struct sort_key *key = add_key();
+            char *temp;
+            int flag;
+
+            idx = 0;
+            temp = arg->arg;
+            while (*temp) {
+                // Start of range
+                key->range[2*idx] = (unsigned)strtol(temp, &temp, 10);
+                if (*temp=='.')
+                    key->range[(2*idx)+1] = (unsigned)strtol(temp+1, &temp, 10);
+
+                // Handle flags appended to a key type.
+                for (;*temp;temp++) {
+                    char *temp2, *optlist;
+
+                    // Note that a second comma becomes an "Unknown key" error.
+
+                    if (*temp==',' && !idx++) {
+                        temp++;
+                        break;
+                    }
+
+                    // Which flag is this?
+
+                    optlist = toys.which->options;
+                    temp2 = strchr(optlist, *temp);
+                    flag = (1<<(optlist-temp2+strlen(optlist)-1));
+
+                    // Was it a flag that can apply to a key?
+
+                    if (!temp2 || flag>FLAG_b
+                        || (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z)))
+                    {
+                        error_exit("Unknown key option.");
+                    }
+                    // b after , means strip _trailing_ space, not leading.
+                    if (idx && flag==FLAG_b) flag = FLAG_bb;
+                    key->flags |= flag;
+                }
+            }
+        }
+    }
+
+    // global b flag strips both leading and trailing spaces
+    if (toys.optflags&FLAG_b) toys.optflags |= FLAG_bb;
+
+    // If no keys, perform alphabetic sort over the whole line.
+    if (CFG_SORT_BIG && !TT.key_list) add_key()->range[0] = 1;
+
+    // Open input files and read data, populating TT.lines[TT.linecount]
+    loopfiles(toys.optargs, sort_read);
+
+    // The compare (-c) logic was handled in sort_read(),
+    // so if we got here, we're done.
+    if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) goto exit_now;
+
+    // Perform the actual sort
+    qsort(TT.lines, TT.linecount, sizeof(char *), compare_keys);
+
+    // handle unique (-u)
+    if (toys.optflags&FLAG_u) {
+        int jdx;
+
+        for (jdx=0, idx=1; idx<TT.linecount; idx++) {
+            if (!compare_keys(&TT.lines[jdx], &TT.lines[idx]))
+                free(TT.lines[idx]);
+            else TT.lines[++jdx] = TT.lines[idx];
+        }
+        if (TT.linecount) TT.linecount = jdx+1;
+    }
+
+    // Output result
+    for (idx = 0; idx<TT.linecount; idx++) {
+        char *s = TT.lines[idx];
+        xwrite(fd, s, strlen(s));
+        if (CFG_TOYBOX_FREE) free(s);
+        xwrite(fd, "\n", 1);
+    }
+
+exit_now:
+    if (CFG_TOYBOX_FREE) {
+      if (fd != 1) close(fd);
+      free(TT.lines);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/tail.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,232 @@
+/* vi: set sw=4 ts=4:
+ *
+ * tail.c - copy last lines from input to stdout.
+ *
+ * Copyright 2012 Timothy Elliott <tle@holymonkey.com>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/tail.html
+
+USE_TAIL(NEWTOY(tail, "fc-n-", TOYFLAG_BIN))
+
+config TAIL
+	bool "tail"
+	default y
+	help
+	  usage: tail [-n|c number] [-f] [file...]
+
+	  Copy last lines from files to stdout. If no files listed, copy from
+	  stdin. Filename "-" is a synonym for stdin.
+
+	  -n	output the last X lines (default 10), +X counts from start.
+	  -c    output the last X bytes, +X counts from start
+	  -f   	follow file, waiting for more data to be appended
+
+config TAIL_SEEK
+	bool "tail seek support"
+	default y
+	depends on TAIL
+	help
+		This version uses lseek, which is faster on large files.
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	long lines;
+	long bytes;
+
+	int file_no;
+)
+
+#define TT this.tail
+
+#define FLAG_n 1
+#define FLAG_c 2
+#define FLAG_f 4
+
+struct line_list {
+	struct line_list *next, *prev;
+	char *data;
+	int len;
+};
+
+static struct line_list *get_chunk(int fd, int len)
+{
+	struct line_list *line = xmalloc(sizeof(struct line_list)+len);
+
+	line->data = ((char *)line) + sizeof(struct line_list);
+	line->len = readall(fd, line->data, len);
+
+	if (line->len < 1) {
+		free(line);
+		return 0;
+	}
+
+	return line;
+}
+
+static void dump_chunk(void *ptr)
+{
+	struct line_list *list = ptr;
+	xwrite(1, list->data, list->len);
+	free(list);
+}
+
+// Reading through very large files is slow.  Using lseek can speed things
+// up a lot, but isn't applicable to all input (cat | tail).
+// Note: bytes and lines are negative here.
+static int try_lseek(int fd, long bytes, long lines)
+{
+	struct line_list *list = 0, *temp;
+	int flag = 0, chunk = sizeof(toybuf);
+	ssize_t pos = lseek(fd, 0, SEEK_END);
+
+	// If lseek() doesn't work on this stream, return now.
+	if (pos<0) return 0;
+
+	// Seek to the right spot, output data from there.
+	if (bytes) {
+		if (lseek(fd, bytes, SEEK_END)<0) lseek(fd, 0, SEEK_SET);
+		xsendfile(fd, 1);
+		return 1;
+	}
+
+	// Read from end to find enough lines, then output them.
+
+	bytes = pos;
+	while (lines && pos) {
+		int offset;
+
+		// Read in next chunk from end of file
+		if (chunk>pos) chunk = pos;
+		pos -= chunk;
+		if (pos != lseek(fd, pos, SEEK_SET)) {
+			perror_msg("seek failed");
+			break;
+		}
+		if (!(temp = get_chunk(fd, chunk))) break;
+		if (list) list->next = temp;
+		list = temp;
+
+		// Count newlines in this chunk.
+		offset = list->len;
+		while (offset--) {
+			// If the last line ends with a newline, that one doesn't count.
+			if (!flag) {
+				flag++;
+
+				continue;
+			}
+
+			// Start outputting data right after newline
+			if (list->data[offset] == '\n' && !++lines) {
+				offset++;
+				list->data += offset;
+				list->len -= offset;
+
+				break;
+			}
+		}
+	}
+
+	// Output stored data
+	llist_traverse(list, dump_chunk);
+
+	// In case of -f
+	lseek(fd, bytes, SEEK_SET);
+	return 1;
+}
+
+// Called for each file listed on command line, and/or stdin
+static void do_tail(int fd, char *name)
+{
+	long bytes = TT.bytes, lines = TT.lines;
+
+	if (toys.optc > 1) {
+		if (TT.file_no++) xputc('\n');
+		xprintf("==> %s <==\n", name);
+	}
+
+	// Are we measuring from the end of the file?
+
+	if (bytes<0 || lines<0) {
+		struct line_list *list = 0, *new;
+
+		// The slow codepath is always needed, and can handle all input,
+		// so make lseek support optional.
+		if (CFG_TAIL_SEEK && try_lseek(fd, bytes, lines));
+
+		// Read data until we run out, keep a trailing buffer
+		else for (;;) {
+			int len, count;
+			char *try;
+
+			if (!(new = get_chunk(fd, sizeof(toybuf)))) break;
+			// append in order
+			dlist_add_nomalloc((struct double_list **)&list,
+							   (struct double_list *)new);
+
+			// Measure new chunk, discarding extra data from buffer
+			len = new->len;
+			try = new->data;
+			for (count=0; count<len; count++) {
+				if ((toys.optflags & FLAG_c) && bytes) {
+					bytes++;
+					continue;
+				}
+
+				if (lines) {
+					if(try[count] != '\n' && count != len-1) continue;
+					if (lines<0) {
+						if (!++lines) ++lines;
+						continue;
+					}
+				}
+
+				// Time to discard data; given that bytes and lines were
+				// nonzero coming in, we can't discard too much if we're
+				// measuring right.
+				do {
+					char c = *(list->data++);
+					if (!(--list->len)) {
+						struct line_list *next = list->next;
+						list->prev->next = next;
+						list->next->prev = list->prev;
+						free(list);
+						list = next;
+					}
+					if (c == '\n') break;
+				} while (lines);
+			}
+		}
+
+		// Output/free the buffer.
+		llist_traverse(list, dump_chunk);
+
+	// Measuring from the beginning of the file.
+	} else for (;;) {
+		int len, offset = 0;
+
+		// Error while reading does not exit.  Error writing does.
+		len = read(fd, toybuf, sizeof(toybuf));
+		if (len<1) break;
+		while (bytes > 1 || lines > 1) {
+			bytes--;
+			if (toybuf[offset++] == '\n') lines--;
+			if (offset >= len) break;
+		}
+		if (offset<len) xwrite(1, toybuf+offset, len-offset);
+	}
+
+	// -f support: cache name/descriptor
+}
+
+void tail_main(void)
+{
+	// if nothing specified, default -n to -10
+	if (!(toys.optflags&(FLAG_n|FLAG_c))) TT.lines = -10;
+
+	loopfiles(toys.optargs, do_tail);
+
+	// do -f stuff
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/tee.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,75 @@
+/* vi: set sw=4 ts=4:
+ *
+ * tee.c - cat to multiple outputs.
+ *
+ * Copyright 2008 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/tee.html
+
+USE_TEE(NEWTOY(tee, "ia", TOYFLAG_BIN))
+
+config TEE
+    bool "tee"
+    default y
+    help
+      usage: tee [-ai] [file...]
+
+      Copy stdin to each listed file, and also to stdout.
+      Filename "-" is a synonym for stdout.
+
+      -a	append to files.
+      -i	ignore SIGINT.
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+    void *outputs;
+)
+
+#define TT this.tee
+
+struct fd_list {
+    struct fd_list *next;
+    int fd;
+};
+
+// Open each output file, saving filehandles to a linked list.
+
+static void do_tee_open(int fd, char *name)
+{
+    struct fd_list *temp;
+
+    temp = xmalloc(sizeof(struct fd_list));
+    temp->next = TT.outputs;
+    temp->fd = fd;
+    TT.outputs = temp;
+}
+
+void tee_main(void)
+{
+    if (toys.optflags&2) signal(SIGINT, SIG_IGN);
+
+    // Open output files
+    loopfiles_rw(toys.optargs,
+		O_RDWR|O_CREAT|((toys.optflags&1)?O_APPEND:O_TRUNC), 0666, 0,
+		do_tee_open);
+
+    for (;;) {
+        struct fd_list *fdl;
+        int len;
+
+        // Read data from stdin
+        len = xread(0, toybuf, sizeof(toybuf));
+        if (len<1) break;
+
+        // Write data to each output file, plus stdout.
+        fdl = TT.outputs;
+        for (;;) {
+            if(len != writeall(fdl ? fdl->fd : 1, toybuf, len)) toys.exitval=1;
+            if (!fdl) break;
+            fdl = fdl->next;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/true.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,23 @@
+/* vi: set sw=4 ts=4:
+ *
+ * true.c - Return zero.
+ *
+ * Copyright 2007 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/true.html
+
+USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN))
+
+config TRUE
+	bool "true"
+	default y
+	help
+	  Return zero.
+*/
+
+#include "toys.h"
+
+void true_main(void)
+{
+	return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/tty.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4:
+ *
+ * tty.c - Show stdin's terminal name
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/tty.html
+
+USE_TTY(NEWTOY(tty, "s", TOYFLAG_USR|TOYFLAG_BIN))
+
+config TTY
+	bool "tty"
+	default y
+	help
+	  Show filename of terminal connected to stdin.
+
+	  Prints "not a tty" and exits with nonzero status if no terminal
+	  is connected to stdin.
+
+	  -s	silent mode
+*/
+
+#include "toys.h"
+
+void tty_main(void)
+{
+	char *tty = ttyname(0);
+
+	if (!toys.optflags) puts(tty ? tty : "not a tty");
+
+	toys.exitval = !tty;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/uname.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,74 @@
+/* vi: set sw=4 ts=4:
+ *
+ * uname.c - return system name
+ *
+ * Copyright 2008 Rob Landley <rob@landley.net>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/uname.html
+
+USE_UNAME(NEWTOY(uname, "amvrns", TOYFLAG_BIN))
+
+config UNAME
+	bool "uname"
+	default y
+	help
+	  usage: uname [-asnrvmpio]
+
+	  Print system information.
+
+	  -s	System name
+	  -n	Network (domain) name
+	  -r	Release number
+	  -v	Version (build date)
+	  -m	Machine (hardware) name
+	  -a	All of the above
+*/
+
+#include "toys.h"
+
+// If a 32 bit x86 build environment working in a chroot under an x86-64
+// kernel returns x86_64 for -m it confuses ./configure.  Special case it.
+
+#if defined(__i686__)
+#define GROSS "i686"
+#elif defined(__i586__)
+#define GROSS "i586"
+#elif defined(__i486__)
+#define GROSS "i486"
+#elif defined(__i386__)
+#define GROSS "i386"
+#endif
+
+#define FLAG_a (1<<5)
+
+void uname_main(void)
+{
+	int i, flags = toys.optflags, needspace=0;
+
+	uname((void *)toybuf);
+
+	if (!flags) flags=1;
+	for (i=0; i<5; i++) {
+		char *c = toybuf+(65*i);
+
+		if (flags & ((1<<i)|FLAG_a)) {
+			int len = strlen(c);
+
+			// This problem originates in autoconf, so of course the solution
+			// is horribly ugly.
+#ifdef GROSS
+			if (i==4 && !strcmp(c,"x86_64")) printf(GROSS);
+	        else
+#endif
+
+			if (needspace++) {
+				// We can't decrement on the first entry, because
+				// needspace would be 0
+				*(--c)=' ';
+				len++;
+			}
+			xwrite(1, c, len);
+		}
+	}
+	putchar('\n');
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/uniq.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,131 @@
+/* vi: set sw=4 ts=4:
+ *
+ * uniq.c - report or filter out repeated lines in a file
+ *
+ * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
+ *
+ * See http://www.opengroup.org/onlinepubs/009695399/utilities/uniq.html
+
+USE_UNIQ(NEWTOY(uniq, "f#s#w#zicdu", TOYFLAG_BIN))
+
+config UNIQ
+	bool "uniq"
+	default y
+	help
+	  usage: uniq [-cduiz] [-w maxchars] [-f fields] [-s char] [input_file [output_file]]
+
+	  Report or filter out repeated lines in a file
+
+	  -c	show counts before each line
+	  -d	show only lines that are repeated
+	  -u	show only lines that are unique
+	  -i	ignore case when comparing lines
+	  -z	lines end with \0 not \n
+	  -w	compare maximum X chars per line
+	  -f	ignore first X fields
+	  -s	ignore first X chars
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	long maxchars;
+	long nchars;
+	long nfields;
+	long repeats;
+)
+
+#define TT this.uniq
+
+#define FLAG_z 16
+#define FLAG_i 8
+#define FLAG_c 4
+#define FLAG_d 2
+#define FLAG_u 1
+
+static char *skip(char *str)
+{
+	long nchars = TT.nchars, nfields;
+
+	// Skip fields first
+	for (nfields = TT.nfields; nfields; str++) {
+		while (*str && isspace(*str)) str++;
+		while (*str && !isspace(*str)) str++;
+		nfields--;
+	}
+	// Skip chars
+	while (*str && nchars--) str++;
+
+	return str;
+}
+
+static void print_line(FILE *f, char *line)
+{
+	if (toys.optflags & (TT.repeats ? FLAG_u : FLAG_d)) return;
+	if (toys.optflags & FLAG_c) fprintf(f, "%7lu ", TT.repeats + 1);
+	fputs(line, f);
+	if (toys.optflags & FLAG_z) fputc(0, f);
+}
+
+void uniq_main(void)
+{
+	FILE *infile = stdin, *outfile = stdout;
+	char *thisline = NULL, *prevline = NULL, *tmpline, eol = '\n';
+	size_t thissize, prevsize = 0, tmpsize;
+
+	if (toys.optc >= 1) infile = xfopen(toys.optargs[0], "r");
+	if (toys.optc >= 2) outfile = xfopen(toys.optargs[1], "w");
+
+	if (toys.optflags & FLAG_z) eol = 0;
+
+	// If first line can't be read
+	if (getdelim(&prevline, &prevsize, eol, infile) < 0)
+		return;
+
+	while (getdelim(&thisline, &thissize, eol, infile) > 0) {
+		int diff;
+		char *t1, *t2;
+
+		// If requested get the chosen fields + character offsets.
+		if (TT.nfields || TT.nchars) {
+			t1 = skip(thisline);
+			t2 = skip(prevline);
+		} else {
+			t1 = thisline;
+			t2 = prevline;
+		}
+
+		if (TT.maxchars == 0) {
+			diff = !(toys.optflags & FLAG_i)
+			        ? strcmp(t1, t2)
+			        : strcasecmp(t1, t2);
+		} else {
+			diff = !(toys.optflags & FLAG_i)
+			        ? strncmp(t1, t2, TT.maxchars)
+			        : strncasecmp(t1, t2, TT.maxchars);
+		}
+
+		if (diff == 0) { // same
+			TT.repeats++;
+		} else {
+			print_line(outfile, prevline);
+
+			TT.repeats = 0;
+
+			tmpline = prevline;
+			prevline = thisline;
+			thisline = tmpline;
+
+			tmpsize = prevsize;
+			prevsize = thissize;
+			thissize = tmpsize;
+		}
+	}
+
+	print_line(outfile, prevline);
+
+	if (CFG_TOYBOX_FREE) {
+		free(prevline);
+		free(thisline);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/unlink.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,26 @@
+/* vi: set sw=4 ts=4:
+ *
+ * unlink.c - delete one file
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/unlink.html
+
+USE_UNLINK(NEWTOY(unlink, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
+
+config UNLINK
+	bool "unlink"
+	default y
+	help
+	  usage: unlink FILE
+
+	  Deletes one file.
+*/
+
+#include "toys.h"
+
+void unlink_main(void)
+{
+	if (unlink(*toys.optargs))
+		perror_exit("Couldn't unlink `%s'", *toys.optargs);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/wc.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,60 @@
+/* vi: set sw=4 ts=4:
+ *
+ * wc.c - Word count
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/wc.html
+
+USE_WC(NEWTOY(wc, "cwl", TOYFLAG_USR|TOYFLAG_BIN))
+
+config WC
+	bool "wc"
+	default y
+	help
+	  usage: wc -lwc [FILE...]
+
+	  Count lines, words, and characters in input.
+
+	  -l	show lines
+	  -w	show words
+	  -c	show characters
+
+	  By default outputs lines, words, characters, and filename for each
+	  argument (or from stdin if none).
+*/
+
+#include "toys.h"
+
+static void do_wc(int fd, char *name)
+{
+	int i, len;
+	unsigned long word=0, lengths[]={0,0,0};
+
+	for (;;) {
+		len = read(fd, toybuf, sizeof(toybuf));
+		if (len<0) {
+			perror_msg("%s",name);
+			toys.exitval = EXIT_FAILURE;
+		}
+		if (len<1) break;
+		for (i=0; i<len; i++) {
+			if (toybuf[i]==10) lengths[0]++;
+			if (isspace(toybuf[i])) word=0;
+			else {
+				if (!word) lengths[1]++;
+				word=1;
+			}
+			lengths[2]++;
+		}
+	}
+	for (i=0; i<3; i++)
+		if (!toys.optflags || (toys.optflags&(1<<i)))
+			printf("%ld ", lengths[i]);
+	printf("%s\n", (!toys.optflags && strcmp(name,"-")) ? name : "");
+}
+
+void wc_main(void)
+{
+	loopfiles(toys.optargs, do_wc);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/who.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,46 @@
+/* vi: set sw=4 ts=4:
+ *
+ * who.c - display who is on the system
+ *
+ * Copyright 2012 ProFUSION Embedded Systems
+ *
+ * by Luis Felipe Strano Moraes <lfelipe@profusion.mobi>
+ *
+ * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/who.html
+
+USE_WHO(NEWTOY(who, NULL, TOYFLAG_BIN))
+
+config WHO
+	bool "who"
+	default n
+	help
+	  usage: who
+
+	  Print logged user information on system
+
+*/
+
+#include "toys.h"
+
+void who_main(void)
+{
+    struct utmpx *entry;
+
+    setutxent();
+
+    while ((entry = getutxent())) {
+        if (entry->ut_type == USER_PROCESS) {
+            time_t time;
+            int time_size;
+            char * times;
+
+            time = entry->ut_tv.tv_sec;
+            times = ctime(&time);
+            time_size = strlen(times) - 2;
+            printf("%s\t%s\t%*.*s\t(%s)\n", entry->ut_user, entry->ut_line, time_size, time_size, ctime(&time), entry->ut_host);
+
+        }
+    }
+
+    endutxent();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/posix/xargs.c	Sat Aug 25 14:25:22 2012 -0500
@@ -0,0 +1,188 @@
+/* vi: set sw=4 ts=4:
+ *
+ * xargs.c - Run command with arguments taken from stdin.
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/xargs.html
+
+USE_XARGS(NEWTOY(xargs, "^I:E:L#ptxrn#<1s#0", TOYFLAG_USR|TOYFLAG_BIN))
+
+config XARGS
+	bool "xargs"
+	default y
+	help
+	  usage: xargs [-ptxr0] [-s NUM] [-n NUM] [-L NUM] [-E STR] COMMAND...
+
+	  Run command line one or more times, appending arguments from stdin.
+
+	  If command exits with 255, don't launch another even if arguments remain.
+
+	  -s	Size in bytes per command line
+	  -n	Max number of arguments per command
+	  -0	Each argument is NULL terminated, no whitespace or quote processing
+	  #-p	Prompt for y/n from tty before running each command
+	  #-t	Trace, print command line to stderr
+	  #-x	Exit if can't fit everything in one command
+	  #-r	Don't run command with empty input
+	  #-L	Max number of lines of input per command
+	  -E	stop at line matching string
+*/
+
+#include "toys.h"
+
+DEFINE_GLOBALS(
+	long max_bytes;
+	long max_entries;
+	long L;
+	char *eofstr;
+	char *I;
+
+	long entries, bytes;
+	char delim;
+)
+
+#define TT this.xargs
+
+// If out==NULL count TT.bytes and TT.entries, stopping at max.
+// Otherwise, fill out out[] 
+
+// Returning NULL means need more data.
+// Returning char * means hit data limits, start of data left over
+// Returning 1 means hit data limits, but consumed all data
+// Returning 2 means hit -E eofstr
+
+static char *handle_entries(char *data, char **entry)
+{
+	if (TT.delim) { 
+		char *s = data;
+
+		// Chop up whitespace delimited string into args
+		while (*s) {
+			char *save;
+
+			while (isspace(*s)) {
+				if (entry) *s = 0;
+				s++;
+			}
+
+			if (TT.max_entries && TT.entries >= TT.max_entries)
+				return *s ? s : (char *)1;
+
+			if (!*s) break;
+			save = s;
+
+			for (;;) {
+				if (++TT.bytes >= TT.max_bytes && TT.max_bytes) return save;
+				if (!*s || isspace(*s)) break;
+				s++;
+			}
+			if (TT.eofstr) {
+				int len = s-save;
+				if (len == strlen(TT.eofstr) && !strncmp(save, TT.eofstr, len))
+					return (char *)2;
+			}
+			if (entry) entry[TT.entries] = save;
+			++TT.entries;
+		}
+
+	// -0 support
+	} else {
+		TT.bytes += strlen(data)+1;
+		if (TT.max_bytes && TT.bytes >= TT.max_bytes) return data;
+		if (TT.max_entries && TT.entries >= TT.max_entries)
+			return (char *)1;
+		if (entry) entry[TT.entries] = data;
+		TT.entries++;
+	}
+
+	return NULL;
+}
+
+void xargs_main(void)
+{
+	struct double_list *dlist = NULL;
+	int entries, bytes, done = 0, status;
+	char *data = NULL;
+
+	if (!(toys.optflags&1)) TT.delim = '\n';
+
+	// If no optargs, call echo.
+	if (!toys.optc) {
+		free(toys.optargs);
+		*(toys.optargs = xzalloc(2*sizeof(char *)))="echo";
+		toys.optc = 1;
+	}
+
+	for (entries = 0, bytes = -1; entries < toys.optc; entries++, bytes++)
+		bytes += strlen(toys.optargs[entries]);
+
+	// Loop through exec chunks.
+	while (data || !done) {
+		char **out;
+
+		TT.entries = 0;
+		TT.bytes = bytes;
+
+		// Loop reading input
+		for (;;) {
+
+			// Read line
+			if (!data) {
+				ssize_t l = 0;
+				l = getdelim(&data, (size_t *)&l, TT.delim, stdin);
+
+				if (l<0) {
+					data = 0;
+					done++;
+					break;
+				}
+			}
+			dlist_add(&dlist, data);
+
+			// Count data used
+			data = handle_entries(data, NULL);
+			if (!data) continue;
+			if (data == (char *)2) done++;
+			if ((long)data <= 2) data = 0;
+			else data = xstrdup(data);
+
+			break;
+		}
+
+		// Accumulate cally thing
+
+		if (data && !TT.entries) error_exit("argument too long");
+		out = xzalloc((entries+TT.entries+1)*sizeof(char *));
+
+		if (dlist) {
+			struct double_list *dtemp;
+
+			// Fill out command line to exec
+			memcpy(out, toys.optargs, entries*sizeof(char *));
+			TT.entries = 0;
+			TT.bytes = bytes;
+			dlist->prev->next = 0;
+			for (dtemp = dlist; dtemp; dtemp = dtemp->next)
+				handle_entries(dtemp->data, out+entries);
+		}
+		pid_t pid=fork();
+		if (!pid) {
+			xclose(0);
+			open("/dev/null", O_RDONLY);
+			xexec(out);
+		}
+		waitpid(pid, &status, 0);
+		status = WEXITSTATUS(status);
+
+		// Abritrary number of execs, can't just leak memory each time...
+		while (dlist) {
+			struct double_list *dtemp = dlist->next;
+
+			free(dlist->data);
+			free(dlist);
+			dlist = dtemp;
+		}
+		free(out);
+	}
+}
--- a/toys/printenv.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * printenv.c - Print environment variables.
- *
- * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
- *
-
-USE_PRINTENV(NEWTOY(printenv, "0(null)", TOYFLAG_USR|TOYFLAG_BIN))
-
-config PRINTENV
-	bool "printenv"
-	default y
-	help
-	  usage: printenv [-0] [env_var...]
-
-	  Print environment variables.
-
-	  -0	Use \0 as delimiter instead of \n
-*/
-
-#include "toys.h"
-
-extern char **environ;
-
-void printenv_main(void)
-{
-	char **env, **var = toys.optargs;
-	char delim = '\n';
-
-	if (toys.optflags) delim = 0;
-
-	do {
-		int catch = 0, len = *var ? strlen(*var) : 0;
-
-		for (env = environ; *env; env++) {
-			char *out = *env;
-			if (*var) {
-				if (!strncmp(out, *var, len) && out[len] == '=')
-					out += len +1;
-				else continue;
-			}
-			xprintf("%s%c", out, delim);
-			catch++;
-		}
-		if (*var && !catch) toys.exitval = 1;
-	} while (*var && *(++var));
-}
--- a/toys/pwd.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * pwd.c - Print working directory.
- *
- * Copyright 2006 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/echo.html
- *
- * TODO: add -L -P
-
-USE_PWD(NEWTOY(pwd, NULL, TOYFLAG_BIN))
-
-config PWD
-	bool "pwd"
-	default y
-	help
-	  usage: pwd
-
-	  The print working directory command prints the current directory.
-*/
-
-#include "toys.h"
-
-void pwd_main(void)
-{
-	char *pwd = xgetcwd();
-
-	xprintf("%s\n", pwd);
-	if (CFG_TOYBOX_FREE) free(pwd);
-}
--- a/toys/readlink.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * readlink.c - Return string representation of a symbolic link.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3.
-
-USE_READLINK(NEWTOY(readlink, "<1f", TOYFLAG_BIN))
-
-config READLINK
-	bool "readlink"
-	default n
-	help
-	  usage: readlink
-
-	  Show what a symbolic link points to.
-
-config READLINK_F
-	bool "readlink -f"
-	default n
-	depends on READLINK
-	help
-	  usage: readlink [-f]
-
-	  -f	Show full cannonical path, with no symlinks in it.  Returns
-		nonzero if nothing could currently exist at this location.
-*/
-
-#include "toys.h"
-
-void readlink_main(void)
-{
-	char *s;
-
-	// Calculating full cannonical path?
-
-	if (CFG_READLINK_F && toys.optflags) s = xrealpath(*toys.optargs);
-	else s = xreadlink(*toys.optargs);
-
-	if (s) {
-		xputs(s);
-		if (CFG_TOYBOX_FREE) free(s);
-	} else toys.exitval = 1;
-}
--- a/toys/realpath.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * realpath.c - Return the canonical version of a pathname
- *
- * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
- *
- * Not in SUSv4.
-
-USE_REALPATH(NEWTOY(realpath, "<1", TOYFLAG_USR|TOYFLAG_BIN))
-
-config REALPATH
-	bool "realpath"
-	default y
-	help
-	  usage: realpath FILE...
-
-	  Display the canonical absolute pathname
-*/
-
-#include "toys.h"
-
-void realpath_main(void)
-{
-    char **s = toys.optargs;
-    for (s = toys.optargs; *s; s++) {
-        if (!realpath(*s, toybuf)) {
-            perror_msg("cannot access '%s'", *s);
-            toys.exitval = 1;
-        } else xputs(toybuf);
-    }
-}
--- a/toys/rmdir.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * rmdir.c - remove directory/path
- *
- * Copyright 2008 Rob Landley <rob@landley.net>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/rmdir.html
-
-USE_RMDIR(NEWTOY(rmdir, "<1p", TOYFLAG_BIN))
-
-config RMDIR
-	bool "rmdir"
-	default y
-	help
-	  usage: rmdir [-p] [dirname...]
-	  Remove one or more directories.
-
-	  -p	Remove path.
-*/
-
-#include "toys.h"
-
-static void do_rmdir(char *name)
-{
-	for (;;) {
-		char *temp;
-
-		if (rmdir(name)) {
-			perror_msg("%s",name);
-			return;
-		}
-		if (!toys.optflags) return;
-		if (!(temp=strrchr(name,'/'))) return;
-		*temp=0;
-	}
-}
-
-void rmdir_main(void)
-{
-	char **s;
-
-	for (s=toys.optargs; *s; s++) do_rmdir(*s);
-}
--- a/toys/rmmod.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * rmmod.c - Remove a module from the Linux kernel.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
-
-USE_RMMOD(NEWTOY(rmmod, "<1wf", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
-
-config RMMOD
-	bool "rmmod"
-	default y
-	help
-	  usage: rmmod [-wf] [MODULE]
-
-	  Unload the module named MODULE from the Linux kernel.
-	  -f   Force unload of a module
-	  -w   Wait until the module is no longer used.
-
-*/
-
-#include "toys.h"
-
-#include <sys/syscall.h>
-#define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
-
-void rmmod_main(void)
-{
-	unsigned int flags = O_NONBLOCK|O_EXCL;
-	char * mod_name;
-	int len;
-
-	// Basename
-	mod_name = strrchr(toys.optargs[0],'/');
-	if (mod_name)
-		mod_name++;
-	else
-		mod_name = toys.optargs[0];
-
-	// Remove .ko if present
-	len = strlen(mod_name);
-	if (len > 3 && !strcmp(&mod_name[len-3], ".ko" ))
-		mod_name[len-3] = 0;
-
-	if (toys.optflags & 1) flags |= O_TRUNC;
-	if (toys.optflags & 2) flags &= ~O_NONBLOCK;
-
-	if (delete_module(mod_name, flags))
-		perror_exit("failed to unload %s", mod_name);
-}
--- a/toys/sed.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * sed.c - Stream editor.
- *
- * Copyright 2008 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/sed.c
-
-USE_SED(NEWTOY(sed, "irne*", TOYFLAG_BIN))
-
-config SED
-	bool "sed"
-	default n
-	help
-	  usage: sed [-irn] {command | [-e command]...} [FILE...]
-
-	  Stream EDitor, transforms text by appling commands to each line
-	  of input.
-*/
-
-#include "toys.h"
-#include "lib/xregcomp.h"
-
-DEFINE_GLOBALS(
-	struct arg_list *commands;
-)
-
-#define TT this.sed
-
-struct sed_command {
-	// Doubly linked list of commands.
-	struct sed_command *next, *prev;
-
-	// Regexes for s/match/data/ and /match_begin/,/match_end/command
-	regex_t *match, *match_begin, *match_end;
-
-	// For numeric ranges ala 10,20command
-	int first_line, last_line;
-
-	// Which match to replace, 0 for all.
-	int which;
-
-	// s and w commands can write to a file.  Slight optimization: we use 0
-	// instead of -1 to mean no file here, because even when there's no stdin
-	// our input file would take fd 0.
-	int outfd;
-
-	// Data string for (saicytb)
-	char *data;
-
-	// Which command letter is this?
-	char command;
-};
-
-void sed_main(void)
-{
-	struct arg_list *test;
-
-	for (test = TT.commands; test; test = test->next)
-		dprintf(2,"command=%s\n",test->arg);
-
-	printf("Hello world\n");
-}
--- a/toys/seq.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * seq.c - Count from first to last, by increment.
- *
- * Copyright 2006 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3.  (Don't ask me why not.)
-
-USE_SEQ(NEWTOY(seq, "<1>3?", TOYFLAG_USR|TOYFLAG_BIN))
-
-config SEQ
-	bool "seq"
-	depends on TOYBOX_FLOAT
-	default y
-	help
-	  usage: seq [first] [increment] last
-
-	  Count from first to last, by increment.  Omitted arguments default
-	  to 1.  Two arguments are used as first and last.  Arguments can be
-	  negative or floating point.
-*/
-
-#include "toys.h"
-
-void seq_main(void)
-{
-	double first, increment, last, dd;
-
-	// Parse command line arguments, with appropriate defaults.
-	// Note that any non-numeric arguments are treated as zero.
-	first = increment = 1;
-	switch (toys.optc) {
-		case 3:
-			increment = atof(toys.optargs[1]);
-		case 2:
-			first = atof(*toys.optargs);
-		default:
-			last = atof(toys.optargs[toys.optc-1]);
-	}
-
-	// Yes, we're looping on a double.  Yes rounding errors can accumulate if
-	// you use a non-integer increment.  Deal with it.
-	for (dd=first; (increment>0 && dd<=last) || (increment <0 && dd>=last);
-		dd+=increment)
-	{
-		printf("%g\n", dd);
-	}
-}
--- a/toys/setsid.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * setsid.c - Run program in a new session ID.
- *
- * Copyright 2006 Rob Landley <rob@landley.net>
- *
- * Not in SUSv4.
-
-USE_SETSID(NEWTOY(setsid, "^<1t", TOYFLAG_USR|TOYFLAG_BIN))
-
-config SETSID
-	bool "setsid"
-	default y
-	help
-	  usage: setsid [-t] command [args...]
-
-	  Run process in a new session.
-
-	  -t	Grab tty (become foreground process, receiving keyboard signals)
-*/
-
-#include "toys.h"
-
-void setsid_main(void)
-{
-	while (setsid()<0)
-		if (vfork()) _exit(0);
-	if (toys.optflags) {
-		setpgid(0,0);
-		tcsetpgrp(0, getpid());
-	}
-	xexec(toys.optargs);
-}
--- a/toys/sha1sum.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * sha1sum.c - Calculate sha1 cryptographic hash for input.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * Based on the public domain SHA-1 in C by Steve Reid <steve@edmweb.com>
- * from http://www.mirrors.wiretapped.net/security/cryptography/hashes/sha1/
- *
- * Not in SUSv3.
-
-USE_SHA1SUM(NEWTOY(sha1sum, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-
-config SHA1SUM
-	bool "sha1sum"
-	default y
-	help
-	  usage: sha1sum [file...]
-
-	  Calculate sha1 hash of files (or stdin).
-*/
-
-#include <toys.h>
-
-struct sha1 {
-	uint32_t state[5];
-	uint32_t oldstate[5];
-	uint64_t count;
-	union {
-		unsigned char c[64];
-		uint32_t i[16];
-	} buffer;
-};
-
-static void sha1_init(struct sha1 *this);
-static void sha1_transform(struct sha1 *this);
-static void sha1_update(struct sha1 *this, char *data, unsigned int len);
-static void sha1_final(struct sha1 *this, char digest[20]);
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-// blk0() and blk() perform the initial expand.
-// The idea of expanding during the round function comes from SSLeay
-#if 1
-#define blk0(i) (block[i] = (rol(block[i],24)&0xFF00FF00) \
-	|(rol(block[i],8)&0x00FF00FF))
-#else	// big endian?
-#define blk0(i) block[i]
-#endif
-#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
-	^block[(i+2)&15]^block[i&15],1))
-
-static const uint32_t rconsts[]={0x5A827999,0x6ED9EBA1,0x8F1BBCDC,0xCA62C1D6};
-
-// Hash a single 512-bit block. This is the core of the algorithm.
-
-static void sha1_transform(struct sha1 *this)
-{
-	int i, j, k, count;
-	uint32_t *block = this->buffer.i;
-	uint32_t *rot[5], *temp;
-
-	// Copy context->state[] to working vars
-	for (i=0; i<5; i++) {
-		this->oldstate[i] = this->state[i];
-		rot[i] = this->state + i;
-	}
-	// 4 rounds of 20 operations each.
-	for (i=count=0; i<4; i++) {
-		for (j=0; j<20; j++) {
-			uint32_t work;
-
-			work = *rot[2] ^ *rot[3];
-			if (!i) work = (work & *rot[1]) ^ *rot[3];
-			else {
-				if (i==2)
-					work = ((*rot[1]|*rot[2])&*rot[3])|(*rot[1]&*rot[2]);
-				else work ^= *rot[1];
-			}
-			if (!i && j<16) work += blk0(count);
-			else work += blk(count);
-			*rot[4] += work + rol(*rot[0],5) + rconsts[i];
-			*rot[1] = rol(*rot[1],30);
-
-			// Rotate by one for next time.
-			temp = rot[4];
-			for (k=4; k; k--) rot[k] = rot[k-1];
-			*rot = temp;
-			count++;
-		}
-	}
-	// Add the previous values of state[]
-	for (i=0; i<5; i++) this->state[i] += this->oldstate[i];
-}
-
-
-// Initialize a struct sha1.
-
-static void sha1_init(struct sha1 *this)
-{
-	/* SHA1 initialization constants */
-	this->state[0] = 0x67452301;
-	this->state[1] = 0xEFCDAB89;
-	this->state[2] = 0x98BADCFE;
-	this->state[3] = 0x10325476;
-	this->state[4] = 0xC3D2E1F0;
-	this->count = 0;
-}
-
-// Fill the 64-byte working buffer and call sha1_transform() when full.
-
-void sha1_update(struct sha1 *this, char *data, unsigned int len)
-{
-	unsigned int i, j;
-
-	j = this->count & 63;
-	this->count += len;
-
-	// Enough data to process a frame?
-	if ((j + len) > 63) {
-		i = 64-j;
-		memcpy(this->buffer.c + j, data, i);
-		sha1_transform(this);
-		for ( ; i + 63 < len; i += 64) {
-			memcpy(this->buffer.c, data + i, 64);
-			sha1_transform(this);
-		}
-		j = 0;
-	} else i = 0;
-	// Grab remaining chunk
-	memcpy(this->buffer.c + j, data + i, len - i);
-}
-
-// Add padding and return the message digest.
-
-void sha1_final(struct sha1 *this, char digest[20])
-{
-	uint64_t count = this->count << 3;
-	unsigned int i;
-	char buf;
-
-	// End the message by appending a "1" bit to the data, ending with the
-	// message size (in bits, big endian), and adding enough zero bits in
-	// between to pad to the end of the next 64-byte frame.
-	//
-	// Since our input up to now has been in whole bytes, we can deal with
-	// bytes here too.
-
-	buf = 0x80;
-	do {
-		sha1_update(this, &buf, 1);
-		buf = 0;
-	} while ((this->count & 63) != 56);
-	for (i = 0; i < 8; i++)
-	  this->buffer.c[56+i] = count >> (8*(7-i));
-	sha1_transform(this);
-
-	for (i = 0; i < 20; i++)
-		digest[i] = this->state[i>>2] >> ((3-(i & 3)) * 8);
-	// Wipe variables.  Cryptogropher paranoia.
-	memset(this, 0, sizeof(struct sha1));
-}
-
-// Callback for loopfiles()
-
-static void do_sha1(int fd, char *name)
-{
-	struct sha1 this;
-	int len;
-
-	sha1_init(&this);
-	for (;;) {
-		len = read(fd, toybuf, sizeof(toybuf));
-		if (len<1) break;
-		sha1_update(&this, toybuf, len);
-	}
-	sha1_final(&this, toybuf);
-	for (len = 0; len < 20; len++) printf("%02x", toybuf[len]);
-	printf("  %s\n", name);
-}
-
-void sha1sum_main(void)
-{
-	loopfiles(toys.optargs, do_sha1);
-}
--- a/toys/sleep.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * sleep.c - Wait for a number of seconds.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/sleep.html
-
-USE_SLEEP(NEWTOY(sleep, "<1", TOYFLAG_BIN))
-
-config SLEEP
-	bool "sleep"
-	default y
-	help
-	  usage: sleep SECONDS
-
-	  Wait before exiting.
-
-config SLEEP_FLOAT
-	bool
-	default y
-	depends on SLEEP && TOYBOX_FLOAT
-	help
-	  The delay can be a decimal fraction. An optional suffix can be "m"
-	  (minutes), "h" (hours), "d" (days), or "s" (seconds, the default).
-*/
-
-#include "toys.h"
-
-void sleep_main(void)
-{
-
-	if (!CFG_TOYBOX_FLOAT) toys.exitval = sleep(atol(*toys.optargs));
-	else {
-		char *arg;
-		double d = strtod(*toys.optargs, &arg);
-		struct timespec tv;
-
-		// Parse suffix
-		if (*arg) {
-			int ismhd[]={1,60,3600,86400};
-			char *smhd = "smhd", *c = strchr(smhd, *arg);
-			if (!c) error_exit("Unknown suffix '%c'", *arg);
-			d *= ismhd[c-smhd];
-		}
-
-		tv.tv_nsec=1000000000*(d-(tv.tv_sec = (unsigned long)d));
-		toys.exitval = !!nanosleep(&tv, NULL);
-	}
-}
--- a/toys/sort.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,421 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * sort.c - put input lines into order
- *
- * Copyright 2004, 2008 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html
-
-USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")USE_SORT_BIG("S:T:m" "o:k*t:xbMcszdfi") "run", TOYFLAG_USR|TOYFLAG_BIN))
-
-config SORT
-    bool "sort"
-    default y
-    help
-      usage: sort [-run] [FILE...]
-
-      Sort all lines of text from input files (or stdin) to stdout.
-
-      -r    reverse
-      -u    unique lines only
-      -n    numeric order (instead of alphabetical)
-
-config SORT_BIG
-    bool "SuSv3 options (Support -ktcsbdfiozM)"
-    default y
-    depends on SORT
-    help
-      usage: sort [-bcdfiMsz] [-k#[,#[x]] [-t X]] [-o FILE]
-
-      -b    ignore leading blanks (or trailing blanks in second part of key)
-      -c    check whether input is sorted
-      -d    dictionary order (use alphanumeric and whitespace chars only)
-      -f    force uppercase (case insensitive sort)
-      -i    ignore nonprinting characters
-      -M    month sort (jan, feb, etc).
-      -x    Hexadecimal numerical sort
-      -s    skip fallback sort (only sort with keys)
-      -z    zero (null) terminated input
-      -k    sort by "key" (see below)
-      -t    use a key separator other than whitespace
-      -o    output to FILE instead of stdout
-
-      Sorting by key looks at a subset of the words on each line.  -k2
-      uses the second word to the end of the line, -k2,2 looks at only
-      the second word, -k2,4 looks from the start of the second to the end
-      of the fourth word.  Specifying multiple keys uses the later keys as
-      tie breakers, in order.  A type specifier appended to a sort key
-          (such as -2,2n) applies only to sorting that key.
-
-config SORT_FLOAT
-    bool "Floating point (-g)"
-    default y
-    depends on SORT_BIG
-    help
-      usage: sort [-g]
-
-      This version of sort requires floating point.
-
-      -g    general numeric sort (double precision with nan and inf)
-
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-    char *key_separator;
-    struct arg_list *raw_keys;
-    char *outfile;
-    char *ignore1, ignore2;   // GNU compatability NOPs for -S and -T.
-
-    void *key_list;
-    int linecount;
-    char **lines;
-)
-
-#define TT this.sort
-
-// The sort types are n, g, and M.
-// u, c, s, and z apply to top level only, not to keys.
-// b at top level implies bb.
-// The remaining options can be applied to search keys.
-
-#define FLAG_n  (1<<0)  // Sort type: numeric
-#define FLAG_u  (1<<1)  // Unique
-#define FLAG_r  (1<<2)  // Reverse output order
-
-#define FLAG_i  (1<<3)  // Ignore !isprint()
-#define FLAG_f  (1<<4)  // Force uppercase
-#define FLAG_d  (1<<5)  // Ignore !(isalnum()|isspace())
-#define FLAG_z  (1<<6)  // Input is null terminated, not \n
-#define FLAG_s  (1<<7)  // Stable sort, no ascii fallback at end
-#define FLAG_c  (1<<8)  // Check only.  No output, exit(!ordered)
-#define FLAG_M  (1<<9)  // Sort type: date
-#define FLAG_b  (1<<10) // Ignore leading blanks
-#define FLAG_x  (1<<11) // Hex sort
-#define FLAG_g  (1<<18) // Sort type: strtod()
-
-// Left off dealing with FLAG_b/FLAG_bb logic...
-
-#define FLAG_bb (1<<31)  // Ignore trailing blanks
-
-struct sort_key
-{
-    struct sort_key *next_key;  // linked list
-    unsigned range[4];          // start word, start char, end word, end char
-    int flags;
-};
-
-// Copy of the part of this string corresponding to a key/flags.
-
-static char *get_key_data(char *str, struct sort_key *key, int flags)
-{
-    int start=0, end, len, i, j;
-
-    // Special case whole string, so we don't have to make a copy
-
-    if(key->range[0]==1 && !key->range[1] && !key->range[2] && !key->range[3]
-        && !(flags&(FLAG_b&FLAG_d&FLAG_f&FLAG_i&FLAG_bb))) return str;
-
-    // Find start of key on first pass, end on second pass
-
-    len = strlen(str);
-    for (j=0; j<2; j++) {
-        if (!key->range[2*j]) end=len;
-
-        // Loop through fields
-        else {
-            end=0;
-            for (i=1; i < key->range[2*j]+j; i++) {
-
-                // Skip leading blanks
-                if (str[end] && !TT.key_separator)
-                    while (isspace(str[end])) end++;
-
-                // Skip body of key
-                for (; str[end]; end++) {
-                    if (TT.key_separator) {
-                        if (str[end]==*TT.key_separator) break;
-                    } else if (isspace(str[end])) break;
-                }
-            }
-        }
-        if (!j) start=end;
-    }
-
-    // Key with explicit separator starts after the separator
-    if (TT.key_separator && str[start]==*TT.key_separator) start++;
-
-    // Strip leading and trailing whitespace if necessary
-    if (flags&FLAG_b) while (isspace(str[start])) start++;
-    if (flags&FLAG_bb) while (end>start && isspace(str[end-1])) end--;
-
-    // Handle offsets on start and end
-    if (key->range[3]) {
-        end += key->range[3]-1;
-        if (end>len) end=len;
-    }
-    if (key->range[1]) {
-        start += key->range[1]-1;
-        if (start>len) start=len;
-    }
-
-    // Make the copy
-    if (end<start) end=start;
-    str = xstrndup(str+start, end-start);
-
-    // Handle -d
-    if (flags&FLAG_d) {
-        for (start = end = 0; str[end]; end++)
-            if (isspace(str[end]) || isalnum(str[end])) str[start++] = str[end];
-        str[start] = 0;
-    }
-
-    // Handle -i
-    if (flags&FLAG_i) {
-        for (start = end = 0; str[end]; end++)
-            if (isprint(str[end])) str[start++] = str[end];
-        str[start] = 0;
-    }
-
-    // Handle -f
-    if (flags*FLAG_f) for(i=0; str[i]; i++) str[i] = toupper(str[i]);
-
-    return str;
-}
-
-// append a sort_key to key_list.
-
-static struct sort_key *add_key(void)
-{
-    void **stupid_compiler = &TT.key_list;
-    struct sort_key **pkey = (struct sort_key **)stupid_compiler;
-
-    while (*pkey) pkey = &((*pkey)->next_key);
-    return *pkey = xzalloc(sizeof(struct sort_key));
-}
-
-// Perform actual comparison
-static int compare_values(int flags, char *x, char *y)
-{
-    int ff = flags & (FLAG_n|FLAG_g|FLAG_M|FLAG_x);
-
-    // Ascii sort
-    if (!ff) return strcmp(x, y);
-
-    if (CFG_SORT_FLOAT && ff == FLAG_g) {
-        char *xx,*yy;
-        double dx = strtod(x,&xx), dy = strtod(y,&yy);
-        int xinf, yinf;
-
-        // not numbers < NaN < -infinity < numbers < +infinity
-
-        if (x==xx) return y==yy ? 0 : -1;
-        if (y==yy) return 1;
-
-        // Check for isnan
-        if (dx!=dx) return (dy!=dy) ? 0 : -1;
-        if (dy!=dy) return 1;
-
-        // Check for infinity.  (Could underflow, but avoids needing libm.)
-        xinf = (1.0/dx == 0.0);
-        yinf = (1.0/dy == 0.0);
-        if (xinf) {
-            if(dx<0) return (yinf && dy<0) ? 0 : -1;
-            return (yinf && dy>0) ? 0 : 1;
-        }
-        if (yinf) return dy<0 ? 1 : -1;
-
-        return dx>dy ? 1 : (dx<dy ? -1 : 0);
-    } else if (CFG_SORT_BIG && ff == FLAG_M) {
-        struct tm thyme;
-        int dx;
-        char *xx,*yy;
-
-        xx = strptime(x,"%b",&thyme);
-        dx = thyme.tm_mon;
-        yy = strptime(y,"%b",&thyme);
-        if (!xx) return !yy ? 0 : -1;
-        else if (!yy) return 1;
-        else return dx==thyme.tm_mon ? 0 : dx-thyme.tm_mon;
-
-    } else if (CFG_SORT_BIG && ff == FLAG_x) {
-        return strtol(x, NULL, 16)-strtol(y, NULL, 16);
-    // This has to be ff == FLAG_n
-    } else {
-        // Full floating point version of -n
-        if (CFG_SORT_FLOAT) {
-            double dx = atof(x), dy = atof(y);
-
-            return dx>dy ? 1 : (dx<dy ? -1 : 0);
-        // Integer version of -n for tiny systems
-        } else return atoi(x)-atoi(y);
-    }
-}
-
-
-// Callback from qsort(): Iterate through key_list and perform comparisons.
-static int compare_keys(const void *xarg, const void *yarg)
-{
-    int flags = toys.optflags, retval = 0;
-    char *x, *y, *xx = *(char **)xarg, *yy = *(char **)yarg;
-    struct sort_key *key;
-
-    if (CFG_SORT_BIG) {
-        for (key=(struct sort_key *)TT.key_list; !retval && key;
-             key = key->next_key)
-        {
-            flags = key->flags ? key->flags : toys.optflags;
-
-            // Chop out and modify key chunks, handling -dfib
-
-            x = get_key_data(xx, key, flags);
-            y = get_key_data(yy, key, flags);
-
-            retval = compare_values(flags, x, y);
-
-            // Free the copies get_key_data() made.
-
-            if (x != xx) free(x);
-            if (y != yy) free(y);
-
-            if (retval) break;
-        }
-    } else retval = compare_values(flags, xx, yy);
-
-    // Perform fallback sort if necessary
-    if (!retval && !(CFG_SORT_BIG && (toys.optflags&FLAG_s))) {
-        retval = strcmp(xx, yy);
-        flags = toys.optflags;
-    }
-
-    return retval * ((flags&FLAG_r) ? -1 : 1);
-}
-
-// Callback from loopfiles to handle input files.
-static void sort_read(int fd, char *name)
-{
-    // Read each line from file, appending to a big array.
-
-    for (;;) {
-        char * line = (CFG_SORT_BIG && (toys.optflags&FLAG_z))
-                       ? get_rawline(fd, NULL, 0) : get_line(fd);
-
-        if (!line) break;
-
-        // handle -c here so we don't allocate more memory than necessary.
-        if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) {
-            int j = (toys.optflags&FLAG_u) ? -1 : 0;
-
-            if (TT.lines && compare_keys((void *)&TT.lines, &line)>j)
-                error_exit("%s: Check line %d\n", name, TT.linecount);
-            free(TT.lines);
-            TT.lines = (char **)line;
-        } else {
-            if (!(TT.linecount&63))
-                TT.lines = xrealloc(TT.lines, sizeof(char *)*(TT.linecount+64));
-            TT.lines[TT.linecount] = line;
-        }
-        TT.linecount++;
-    }
-}
-
-void sort_main(void)
-{
-    int idx, fd = 1;
-
-    // Open output file if necessary.
-    if (CFG_SORT_BIG && TT.outfile)
-        fd = xcreate(TT.outfile, O_CREAT|O_TRUNC|O_WRONLY, 0666);
-
-    // Parse -k sort keys.
-    if (CFG_SORT_BIG && TT.raw_keys) {
-        struct arg_list *arg;
- 
-        for (arg = TT.raw_keys; arg; arg = arg->next) {
-            struct sort_key *key = add_key();
-            char *temp;
-            int flag;
-
-            idx = 0;
-            temp = arg->arg;
-            while (*temp) {
-                // Start of range
-                key->range[2*idx] = (unsigned)strtol(temp, &temp, 10);
-                if (*temp=='.')
-                    key->range[(2*idx)+1] = (unsigned)strtol(temp+1, &temp, 10);
-
-                // Handle flags appended to a key type.
-                for (;*temp;temp++) {
-                    char *temp2, *optlist;
-
-                    // Note that a second comma becomes an "Unknown key" error.
-
-                    if (*temp==',' && !idx++) {
-                        temp++;
-                        break;
-                    }
-
-                    // Which flag is this?
-
-                    optlist = toys.which->options;
-                    temp2 = strchr(optlist, *temp);
-                    flag = (1<<(optlist-temp2+strlen(optlist)-1));
-
-                    // Was it a flag that can apply to a key?
-
-                    if (!temp2 || flag>FLAG_b
-                        || (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z)))
-                    {
-                        error_exit("Unknown key option.");
-                    }
-                    // b after , means strip _trailing_ space, not leading.
-                    if (idx && flag==FLAG_b) flag = FLAG_bb;
-                    key->flags |= flag;
-                }
-            }
-        }
-    }
-
-    // global b flag strips both leading and trailing spaces
-    if (toys.optflags&FLAG_b) toys.optflags |= FLAG_bb;
-
-    // If no keys, perform alphabetic sort over the whole line.
-    if (CFG_SORT_BIG && !TT.key_list) add_key()->range[0] = 1;
-
-    // Open input files and read data, populating TT.lines[TT.linecount]
-    loopfiles(toys.optargs, sort_read);
-
-    // The compare (-c) logic was handled in sort_read(),
-    // so if we got here, we're done.
-    if (CFG_SORT_BIG && (toys.optflags&FLAG_c)) goto exit_now;
-
-    // Perform the actual sort
-    qsort(TT.lines, TT.linecount, sizeof(char *), compare_keys);
-
-    // handle unique (-u)
-    if (toys.optflags&FLAG_u) {
-        int jdx;
-
-        for (jdx=0, idx=1; idx<TT.linecount; idx++) {
-            if (!compare_keys(&TT.lines[jdx], &TT.lines[idx]))
-                free(TT.lines[idx]);
-            else TT.lines[++jdx] = TT.lines[idx];
-        }
-        if (TT.linecount) TT.linecount = jdx+1;
-    }
-
-    // Output result
-    for (idx = 0; idx<TT.linecount; idx++) {
-        char *s = TT.lines[idx];
-        xwrite(fd, s, strlen(s));
-        if (CFG_TOYBOX_FREE) free(s);
-        xwrite(fd, "\n", 1);
-    }
-
-exit_now:
-    if (CFG_TOYBOX_FREE) {
-      if (fd != 1) close(fd);
-      free(TT.lines);
-    }
-}
--- a/toys/swapoff.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * swapoff.c - Disable region for swapping
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
-
-USE_SWAPOFF(NEWTOY(swapoff, "<1>1", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
-
-config SWAPOFF
-	bool "swapoff"
-	default y
-	help
-	  usage: swapoff swapregion
-
-	  Disable swapping on a given swapregion.
-*/
-
-#include "toys.h"
-
-void swapoff_main(void)
-{
-	if (swapoff(toys.optargs[0]))
-		perror_exit("failed to remove swaparea");
-}
--- a/toys/swapon.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * swapon.c - Enable region for swapping
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
-
-USE_SWAPON(NEWTOY(swapon, "<1>1p#<0>32767", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
-
-config SWAPON
-	bool "swapon"
-	default y
-	help
-	  usage: swapon [-p priority] filename
-
-	  Enable swapping on a given device/file.
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	long priority;
-)
-
-#define TT this.swapon
-
-void swapon_main(void)
-{
-	int flags = 0;
-
-	if (toys.optflags & 1)
-		flags = SWAP_FLAG_PREFER | (TT.priority << SWAP_FLAG_PRIO_SHIFT);
-
-	if (swapon(*toys.optargs, flags))
-		perror_exit("Couldn't swapon '%s'", *toys.optargs);
-}
--- a/toys/sync.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * sync.c - Write all pending data to disk.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3.
-
-USE_SYNC(NEWTOY(sync, NULL, TOYFLAG_BIN))
-
-config SYNC
-	bool "sync"
-	default y
-	help
-	  usage: sync
-
-	  Write pending cached data to disk (synchronize), blocking until done.
-*/
-
-#include "toys.h"
-
-void sync_main(void)
-{
-	sync();
-}
--- a/toys/tac.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * tac.c - output lines in reverse order
- *
- * Copyright 2012 Rob Landley <rob@landley.net>
- *
- * Not in SUSv4.
-
-USE_TAC(NEWTOY(tac, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-
-config TAC
-	bool "tac"
-	default y
-	help
-	  usage: tac [FILE...]
-
-	  Output lines in reverse order.
-*/
-
-#include "toys.h"
-
-void do_tac(int fd, char *name)
-{
-	struct arg_list *list = NULL;
-	char *c;
-
-	// Read in lines
-	for (;;) {
-		struct arg_list *temp;
-		int len;
-
-		if (!(c = get_line(fd))) break;
-
-		len = strlen(c);
-		if (len && c[len-1]=='\n') c[len-1] = 0;
-		temp = xmalloc(sizeof(struct arg_list));
-		temp->next = list;
-		temp->arg = c;
-		list = temp;
-	}
-
-	// Play them back.
-	while (list) {
-		struct arg_list *temp = list->next;
-		xputs(list->arg);
-		free(list->arg);
-		free(list);
-		list = temp;
-	}
-}
-
-void tac_main(void)
-{
-	loopfiles(toys.optargs, do_tac);
-}
--- a/toys/tail.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * tail.c - copy last lines from input to stdout.
- *
- * Copyright 2012 Timothy Elliott <tle@holymonkey.com>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/tail.html
-
-USE_TAIL(NEWTOY(tail, "fc-n-", TOYFLAG_BIN))
-
-config TAIL
-	bool "tail"
-	default y
-	help
-	  usage: tail [-n|c number] [-f] [file...]
-
-	  Copy last lines from files to stdout. If no files listed, copy from
-	  stdin. Filename "-" is a synonym for stdin.
-
-	  -n	output the last X lines (default 10), +X counts from start.
-	  -c    output the last X bytes, +X counts from start
-	  -f   	follow file, waiting for more data to be appended
-
-config TAIL_SEEK
-	bool "tail seek support"
-	default y
-	depends on TAIL
-	help
-		This version uses lseek, which is faster on large files.
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	long lines;
-	long bytes;
-
-	int file_no;
-)
-
-#define TT this.tail
-
-#define FLAG_n 1
-#define FLAG_c 2
-#define FLAG_f 4
-
-struct line_list {
-	struct line_list *next, *prev;
-	char *data;
-	int len;
-};
-
-static struct line_list *get_chunk(int fd, int len)
-{
-	struct line_list *line = xmalloc(sizeof(struct line_list)+len);
-
-	line->data = ((char *)line) + sizeof(struct line_list);
-	line->len = readall(fd, line->data, len);
-
-	if (line->len < 1) {
-		free(line);
-		return 0;
-	}
-
-	return line;
-}
-
-static void dump_chunk(void *ptr)
-{
-	struct line_list *list = ptr;
-	xwrite(1, list->data, list->len);
-	free(list);
-}
-
-// Reading through very large files is slow.  Using lseek can speed things
-// up a lot, but isn't applicable to all input (cat | tail).
-// Note: bytes and lines are negative here.
-static int try_lseek(int fd, long bytes, long lines)
-{
-	struct line_list *list = 0, *temp;
-	int flag = 0, chunk = sizeof(toybuf);
-	ssize_t pos = lseek(fd, 0, SEEK_END);
-
-	// If lseek() doesn't work on this stream, return now.
-	if (pos<0) return 0;
-
-	// Seek to the right spot, output data from there.
-	if (bytes) {
-		if (lseek(fd, bytes, SEEK_END)<0) lseek(fd, 0, SEEK_SET);
-		xsendfile(fd, 1);
-		return 1;
-	}
-
-	// Read from end to find enough lines, then output them.
-
-	bytes = pos;
-	while (lines && pos) {
-		int offset;
-
-		// Read in next chunk from end of file
-		if (chunk>pos) chunk = pos;
-		pos -= chunk;
-		if (pos != lseek(fd, pos, SEEK_SET)) {
-			perror_msg("seek failed");
-			break;
-		}
-		if (!(temp = get_chunk(fd, chunk))) break;
-		if (list) list->next = temp;
-		list = temp;
-
-		// Count newlines in this chunk.
-		offset = list->len;
-		while (offset--) {
-			// If the last line ends with a newline, that one doesn't count.
-			if (!flag) {
-				flag++;
-
-				continue;
-			}
-
-			// Start outputting data right after newline
-			if (list->data[offset] == '\n' && !++lines) {
-				offset++;
-				list->data += offset;
-				list->len -= offset;
-
-				break;
-			}
-		}
-	}
-
-	// Output stored data
-	llist_traverse(list, dump_chunk);
-
-	// In case of -f
-	lseek(fd, bytes, SEEK_SET);
-	return 1;
-}
-
-// Called for each file listed on command line, and/or stdin
-static void do_tail(int fd, char *name)
-{
-	long bytes = TT.bytes, lines = TT.lines;
-
-	if (toys.optc > 1) {
-		if (TT.file_no++) xputc('\n');
-		xprintf("==> %s <==\n", name);
-	}
-
-	// Are we measuring from the end of the file?
-
-	if (bytes<0 || lines<0) {
-		struct line_list *list = 0, *new;
-
-		// The slow codepath is always needed, and can handle all input,
-		// so make lseek support optional.
-		if (CFG_TAIL_SEEK && try_lseek(fd, bytes, lines));
-
-		// Read data until we run out, keep a trailing buffer
-		else for (;;) {
-			int len, count;
-			char *try;
-
-			if (!(new = get_chunk(fd, sizeof(toybuf)))) break;
-			// append in order
-			dlist_add_nomalloc((struct double_list **)&list,
-							   (struct double_list *)new);
-
-			// Measure new chunk, discarding extra data from buffer
-			len = new->len;
-			try = new->data;
-			for (count=0; count<len; count++) {
-				if ((toys.optflags & FLAG_c) && bytes) {
-					bytes++;
-					continue;
-				}
-
-				if (lines) {
-					if(try[count] != '\n' && count != len-1) continue;
-					if (lines<0) {
-						if (!++lines) ++lines;
-						continue;
-					}
-				}
-
-				// Time to discard data; given that bytes and lines were
-				// nonzero coming in, we can't discard too much if we're
-				// measuring right.
-				do {
-					char c = *(list->data++);
-					if (!(--list->len)) {
-						struct line_list *next = list->next;
-						list->prev->next = next;
-						list->next->prev = list->prev;
-						free(list);
-						list = next;
-					}
-					if (c == '\n') break;
-				} while (lines);
-			}
-		}
-
-		// Output/free the buffer.
-		llist_traverse(list, dump_chunk);
-
-	// Measuring from the beginning of the file.
-	} else for (;;) {
-		int len, offset = 0;
-
-		// Error while reading does not exit.  Error writing does.
-		len = read(fd, toybuf, sizeof(toybuf));
-		if (len<1) break;
-		while (bytes > 1 || lines > 1) {
-			bytes--;
-			if (toybuf[offset++] == '\n') lines--;
-			if (offset >= len) break;
-		}
-		if (offset<len) xwrite(1, toybuf+offset, len-offset);
-	}
-
-	// -f support: cache name/descriptor
-}
-
-void tail_main(void)
-{
-	// if nothing specified, default -n to -10
-	if (!(toys.optflags&(FLAG_n|FLAG_c))) TT.lines = -10;
-
-	loopfiles(toys.optargs, do_tail);
-
-	// do -f stuff
-}
--- a/toys/taskset.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * taskset.c - Retrieve or set the CPU affinity of a process.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * No standard.
-
-USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_BIN|TOYFLAG_STAYROOT))
-
-config TASKSET
-	bool "taskset"
-	default y
-	help
-	  usage: taskset [-ap] [mask] [PID | cmd [args...]]
-
-	  Launch a new task which may only run on certain processors, or change
-	  the processor affinity of an exisitng PID.
-
-	  Mask is a hex string where each bit represents a processor the process
-	  is allowed to run on. PID without a mask displays existing affinity.
-
-	  -p	Set/get the affinity of given PID instead of a new command.
-	  -a	Set/get the affinity of all threads of the PID.
-*/
-
-#include "toys.h"
-
-#define FLAG_a 0x1
-#define FLAG_p 0x2
-
-// Prototype for syscall wrappers sched.h refuses to give us
-int sched_setaffinity(pid_t pid, size_t size, void *cpuset);
-int sched_getaffinity(pid_t pid, size_t size, void *cpuset);
-
-// mask is an array of long, which makes the layout a bit weird on big
-// endian systems but as long as it's consistent...
-
-static void do_taskset(pid_t pid, int quiet)
-{
-	unsigned long *mask = (unsigned long *)toybuf;
-	char *s = *toys.optargs, *failed = "failed to %s %d's affinity";
-	int i, j, k;
-
-	for (i=0; ; i++) {
-		if (!quiet) {
-			int j = sizeof(toybuf), flag = 0;
-
-			if (sched_getaffinity(pid, sizeof(toybuf), (void *)mask))
-				perror_exit(failed, "get", pid);
-
-			printf("pid %d's %s affinity mask: ", pid, i ? "new" : "current");
-
-			while (j--) {
-				int x = 255 & (mask[j/sizeof(long)] >> (8*(j&(sizeof(long)-1))));
-
-				if (flag) printf("%02x", x);
-				else if (x) {
-					flag++;
-					printf("%x", x);
-				}
-			}
-			putchar('\n');
-		}
-
-		if (i || toys.optc < 2) return;
-
-		memset(toybuf, 0, sizeof(toybuf));
-		k = strlen(s = *toys.optargs);
-		s += k;
-		for (j = 0; j<k; j++) {
-			unsigned long digit = *(--s) - '0';
-
-			if (digit > 9) digit = 10 + tolower(*s)-'a';
-			if (digit > 15) error_exit("bad mask '%s'", *toys.optargs);
-			mask[j/(2*sizeof(long))] |= digit << 4*(j&((2*sizeof(long))-1));
-		}
-
-		if (sched_setaffinity(pid, sizeof(toybuf), (void *)mask))
-			perror_exit(failed, "set", pid);
-	}
-}
-
-static int task_callback(struct dirtree *new)
-{
-	if (!new->parent) return DIRTREE_RECURSE;
-	if (isdigit(*new->name)) do_taskset(atoi(new->name), 0);
-
-	return 0;
-}
-
-void taskset_main(void)
-{
-	if (!(toys.optflags & FLAG_p)) {
-		if (toys.optc < 2) error_exit("Needs 2 args");
-		do_taskset(getpid(), 1);
-		xexec(toys.optargs+1);
-	} else {
-		char *c;
-		pid_t pid = strtol(toys.optargs[toys.optc-1], &c, 10);
-
-		if (*c) error_exit("Not int %s", toys.optargs[1]);
-
-		if (toys.optflags & FLAG_a) {
-			char buf[33];
-			sprintf(buf, "/proc/%ld/task/", (long)pid);
-			dirtree_read(buf, task_callback);
-		} else do_taskset(pid, 0);
-	}
-}
--- a/toys/tee.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * tee.c - cat to multiple outputs.
- *
- * Copyright 2008 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/tee.html
-
-USE_TEE(NEWTOY(tee, "ia", TOYFLAG_BIN))
-
-config TEE
-    bool "tee"
-    default y
-    help
-      usage: tee [-ai] [file...]
-
-      Copy stdin to each listed file, and also to stdout.
-      Filename "-" is a synonym for stdout.
-
-      -a	append to files.
-      -i	ignore SIGINT.
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-    void *outputs;
-)
-
-#define TT this.tee
-
-struct fd_list {
-    struct fd_list *next;
-    int fd;
-};
-
-// Open each output file, saving filehandles to a linked list.
-
-static void do_tee_open(int fd, char *name)
-{
-    struct fd_list *temp;
-
-    temp = xmalloc(sizeof(struct fd_list));
-    temp->next = TT.outputs;
-    temp->fd = fd;
-    TT.outputs = temp;
-}
-
-void tee_main(void)
-{
-    if (toys.optflags&2) signal(SIGINT, SIG_IGN);
-
-    // Open output files
-    loopfiles_rw(toys.optargs,
-		O_RDWR|O_CREAT|((toys.optflags&1)?O_APPEND:O_TRUNC), 0666, 0,
-		do_tee_open);
-
-    for (;;) {
-        struct fd_list *fdl;
-        int len;
-
-        // Read data from stdin
-        len = xread(0, toybuf, sizeof(toybuf));
-        if (len<1) break;
-
-        // Write data to each output file, plus stdout.
-        fdl = TT.outputs;
-        for (;;) {
-            if(len != writeall(fdl ? fdl->fd : 1, toybuf, len)) toys.exitval=1;
-            if (!fdl) break;
-            fdl = fdl->next;
-        }
-    }
-
-}
--- a/toys/toysh.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,382 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * toysh - toybox shell
- *
- * Copyright 2006 Rob Landley <rob@landley.net>
- *
- * The spec for this is at:
- * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
- * and http://www.opengroup.org/onlinepubs/009695399/utilities/sh.html
- *
- * There are also specs for:
- * http://www.opengroup.org/onlinepubs/009695399/utilities/cd.html
- * http://www.opengroup.org/onlinepubs/009695399/utilities/exit.html
- *
- * Things like the bash man page are good to read too.
- *
- * TODO: // Handle embedded NUL bytes in the command line.
-
-USE_TOYSH(NEWTOY(cd, NULL, TOYFLAG_NOFORK))
-USE_TOYSH(NEWTOY(exit, NULL, TOYFLAG_NOFORK))
-USE_TOYSH(OLDTOY(sh, toysh, "c:i", TOYFLAG_BIN))
-USE_TOYSH(NEWTOY(toysh, "c:i", TOYFLAG_BIN))
-
-config TOYSH
-	bool "sh (toysh)"
-	default n
-	help
-	  usage: sh [-c command] [script]
-
-	  The toybox command shell.  Runs a shell script, or else reads input
-	  interactively and responds to it.
-
-	  -c	command line to execute
-
-config TOYSH_TTY
-	bool "Interactive shell (terminal control)"
-	default n
-	depends on TOYSH
-	help
-	  Add terminal control to toysh.  This is necessary for interactive use,
-	  so the shell isn't killed by CTRL-C.
-
-config TOYSH_PROFILE
-	bool "Profile support"
-	default n
-	depends on TOYSH_TTY
-	help
-	  Read /etc/profile and ~/.profile when running interactively.
-
-	  Also enables the built-in command "source".
-
-config TOYSH_JOBCTL
-	bool "Job Control (fg, bg, jobs)"
-	default n
-	depends on TOYSH_TTY
-	help
-	  Add job control to toysh.  This lets toysh handle CTRL-Z, and enables
-	  the built-in commands "fg", "bg", and "jobs".
-
-	  With pipe support, enable use of "&" to run background processes.
-
-config TOYSH_FLOWCTL
-	bool "Flow control (if, while, for, functions)"
-	default n
-	depends on TOYSH
-	help
-	  Add flow control to toysh.  This enables the if/then/else/fi,
-	  while/do/done, and for/do/done constructs.
-
-	  With pipe support, this enables the ability to define functions
-	  using the "function name" or "name()" syntax, plus curly brackets
-	  "{ }" to group commands.
-
-config TOYSH_QUOTES
-	bool "Smarter argument parsing (quotes)"
-	default n
-	depends on TOYSH
-	help
-	  Add support for parsing "" and '' style quotes to the toysh command
-	  parser, with lets arguments have spaces in them.
-
-config TOYSH_WILDCARDS
-	bool "Wildcards ( ?*{,} )"
-	default n
-	depends on TOYSH_QUOTES
-	help
-	  Expand wildcards in argument names, ala "ls -l *.t?z" and
-	  "rm subdir/{one,two,three}.txt".
-
-config TOYSH_PROCARGS
-	bool "Executable arguments ( `` and $() )"
-	default n
-	depends on TOYSH_QUOTES
-	help
-	  Add support for executing arguments contianing $() and ``, using
-	  the output of the command as the new argument value(s).
-
-	  (Bash calls this "command substitution".)
-
-config TOYSH_ENVVARS
-	bool "Environment variable support"
-	default n
-	depends on TOYSH_QUOTES
-	help
-	  Substitute environment variable values for $VARNAME or ${VARNAME},
-	  and enable the built-in command "export".
-
-config TOYSH_LOCALS
-	bool "Local variables"
-	default n
-	depends on TOYSH_ENVVARS
-	help
-	  Support for local variables, fancy prompts ($PS1), the "set" command,
-	  and $?.
-
-config TOYSH_ARRAYS
-	bool "Array variables"
-	default n
-	depends on TOYSH_LOCALS
-	help
-	  Support for ${blah[blah]} style array variables.
-
-config TOYSH_PIPES
-	bool "Pipes and redirects ( | > >> < << & && | || () ; )"
-	default n
-	depends on TOYSH
-	help
-	  Support multiple commands on the same command line.  This includes
-	  | pipes, > >> < redirects, << here documents, || && conditional
-	  execution, () subshells, ; sequential execution, and (with job
-	  control) & background processes.
-
-config TOYSH_BUILTINS
-	bool "Builtin commands"
-	default n
-	depends on TOYSH
-	help
-	  Adds the commands exec, fg, bg, help, jobs, pwd, export, source, set,
-	  unset, read, alias.
-
-config EXIT
-	bool
-	default n
-	depends on TOYSH
-	help
-	  usage: exit [status]
-
-	  Exit shell.  If no return value supplied on command line, use value
-	  of most recent command, or 0 if none.
-
-config CD
-	bool
-	default n
-	depends on TOYSH
-	help
-	  usage: cd [path]
-
-	  Change current directory.  With no arguments, go to $HOME.
-
-config CD_P
-	bool # "-P support for cd"
-	default n
-	depends on TOYSH
-	help
-	  usage: cd [-PL]
-
-	  -P    Physical path: resolve symlinks in path.
-	  -L    Cancel previous -P and restore default behavior.
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	char *command;
-)
-
-#define TT this.toysh
-
-// A single executable, its arguments, and other information we know about it.
-#define TOYSH_FLAG_EXIT    1
-#define TOYSH_FLAG_SUSPEND 2
-#define TOYSH_FLAG_PIPE    4
-#define TOYSH_FLAG_AND     8
-#define TOYSH_FLAG_OR      16
-#define TOYSH_FLAG_AMP     32
-#define TOYSH_FLAG_SEMI    64
-#define TOYSH_FLAG_PAREN   128
-
-// What we know about a single process.
-struct command {
-	struct command *next;
-	int flags;              // exit, suspend, && ||
-	int pid;                // pid (or exit code)
-	int argc;
-	char *argv[0];
-};
-
-// A collection of processes piped into/waiting on each other.
-struct pipeline {
-	struct pipeline *next;
-	int job_id;
-	struct command *cmd;
-	char *cmdline;         // Unparsed line for display purposes
-	int cmdlinelen;        // How long is cmdline?
-};
-
-// Parse one word from the command line, appending one or more argv[] entries
-// to struct command.  Handles environment variable substitution and
-// substrings.  Returns pointer to next used byte, or NULL if it
-// hit an ending token.
-static char *parse_word(char *start, struct command **cmd)
-{
-	char *end;
-
-	// Detect end of line (and truncate line at comment)
-	if (CFG_TOYSH_PIPES && strchr("><&|(;", *start)) return 0;
-
-	// Grab next word.  (Add dequote and envvar logic here)
-	end = start;
-	while (*end && !isspace(*end)) end++;
-	(*cmd)->argv[(*cmd)->argc++] = xstrndup(start, end-start);
-
-	// Allocate more space if there's no room for NULL terminator.
-
-	if (!((*cmd)->argc & 7))
-		*cmd=xrealloc(*cmd,
-				sizeof(struct command) + ((*cmd)->argc+8)*sizeof(char *));
-	(*cmd)->argv[(*cmd)->argc] = 0;
-	return end;
-}
-
-// Parse a line of text into a pipeline.
-// Returns a pointer to the next line.
-
-static char *parse_pipeline(char *cmdline, struct pipeline *line)
-{
-	struct command **cmd = &(line->cmd);
-	char *start = line->cmdline = cmdline;
-
-	if (!cmdline) return 0;
-
-	if (CFG_TOYSH_JOBCTL) line->cmdline = cmdline;
-
-	// Parse command into argv[]
-	for (;;) {
-		char *end;
-
-		// Skip leading whitespace and detect end of line.
-		while (isspace(*start)) start++;
-		if (!*start || *start=='#') {
-			if (CFG_TOYSH_JOBCTL) line->cmdlinelen = start-cmdline;
-			return 0;
-		}
-
-		// Allocate next command structure if necessary
-		if (!*cmd) *cmd = xzalloc(sizeof(struct command)+8*sizeof(char *));
-
-		// Parse next argument and add the results to argv[]
-		end = parse_word(start, cmd);
-
-		// If we hit the end of this command, how did it end?
-		if (!end) {
-			if (CFG_TOYSH_PIPES && *start) {
-				if (*start==';') {
-					start++;
-					break;
-				}
-				// handle | & < > >> << || &&
-			}
-			break;
-		}
-		start = end;
-	}
-
-	if (CFG_TOYSH_JOBCTL) line->cmdlinelen = start-cmdline;
-
-	return start;
-}
-
-// Execute the commands in a pipeline
-static void run_pipeline(struct pipeline *line)
-{
-	struct toy_list *tl;
-	struct command *cmd = line->cmd;
-	if (!cmd || !cmd->argc) return;
-
-	tl = toy_find(cmd->argv[0]);
-	// Is this command a builtin that should run in this process?
-	if (tl && (tl->flags & TOYFLAG_NOFORK)) {
-		struct toy_context temp;
-
-		// This fakes lots of what toybox_main() does.
-		memcpy(&temp, &toys, sizeof(struct toy_context));
-		memset(&toys, 0, sizeof(struct toy_context));
-		toy_init(tl, cmd->argv);
-		tl->toy_main();
-		cmd->pid = toys.exitval;
-		free(toys.optargs);
-		if (toys.old_umask) umask(toys.old_umask);
-		memcpy(&toys, &temp, sizeof(struct toy_context));
-	} else {
-		int status;
-
-		cmd->pid = vfork();
-		if (!cmd->pid) xexec(cmd->argv);
-		else waitpid(cmd->pid, &status, 0);
-
-		if (CFG_TOYSH_FLOWCTL || CFG_TOYSH_PIPES) {
-			if (WIFEXITED(status)) cmd->pid = WEXITSTATUS(status);
-			if (WIFSIGNALED(status)) cmd->pid = WTERMSIG(status);
-		}
-	}
-
-	return;
-}
-
-// Free the contents of a command structure
-static void free_cmd(void *data)
-{
-	struct command *cmd=(struct command *)data;
-
-	while(cmd->argc) free(cmd->argv[--cmd->argc]);
-}
-
-
-// Parse a command line and do what it says to do.
-static void handle(char *command)
-{
-	struct pipeline line;
-	char *start = command;
-
-	// Loop through commands in this line
-
-	for (;;) {
-
-		// Parse a group of connected commands
-
-		memset(&line,0,sizeof(struct pipeline));
-		start = parse_pipeline(start, &line);
-		if (!line.cmd) break;
-
-		// Run those commands
-
-		run_pipeline(&line);
-		llist_traverse(line.cmd, free_cmd);
-	}
-}
-
-void cd_main(void)
-{
-	char *dest = *toys.optargs ? *toys.optargs : getenv("HOME");
-	xchdir(dest);
-}
-
-void exit_main(void)
-{
-	exit(*toys.optargs ? atoi(*toys.optargs) : 0);
-}
-
-void toysh_main(void)
-{
-	FILE *f;
-
-	// Set up signal handlers and grab control of this tty.
-	if (CFG_TOYSH_TTY) {
-		if (isatty(0)) toys.optflags |= 1;
-	}
-	f = *toys.optargs ? xfopen(*toys.optargs, "r") : NULL;
-	if (TT.command) handle(TT.command);
-	else {
-		size_t cmdlen = 0;
-		for (;;) {
-			char *command = 0;
-			if (!f) xputc('$');
-			if (1 > getline(&command, &cmdlen, f ? f : stdin)) break;
-			handle(command);
-			free(command);
-		}
-	}
-
-	toys.exitval = 1;
-}
--- a/toys/true.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * true.c - Return zero.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/true.html
-
-USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN))
-
-config TRUE
-	bool "true"
-	default y
-	help
-	  Return zero.
-*/
-
-#include "toys.h"
-
-void true_main(void)
-{
-	return;
-}
--- a/toys/truncate.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * truncate.c - set file length, extending sparsely if necessary
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
- *
- * Not in SUSv4
-
-USE_TRUNCATE(NEWTOY(truncate, "<1s#|c", TOYFLAG_BIN))
-
-config TRUNCATE
-	bool "truncate"
-	default y
-	help
-	  usage: truncate [-c] -s file...
-	  Set length of file(s), extending sparsely if necessary.
-
-	  -c	Don't create file if it doesn't exist.
-	  -s	New size
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	long size;
-)
-
-#define TT this.truncate
-
-static void do_truncate(int fd, char *name)
-{
-	if (fd<0) return;
-	if (ftruncate(fd, TT.size)) {
-		perror_msg("failed to set '%s' to '%ld'", name, TT.size);
-		toys.exitval = EXIT_FAILURE;
-	}
-}
-
-void truncate_main(void)
-{
-	int cr = !(toys.optflags&1);
-
-	// Create files with mask rwrwrw.
-	// Nonexistent files are only an error if we're supposed to create them.
-	loopfiles_rw(toys.optargs, O_WRONLY|(cr ? O_CREAT : 0), 0666, cr,
-		do_truncate);
-}
--- a/toys/tty.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * tty.c - Show stdin's terminal name
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/tty.html
-
-USE_TTY(NEWTOY(tty, "s", TOYFLAG_USR|TOYFLAG_BIN))
-
-config TTY
-	bool "tty"
-	default y
-	help
-	  Show filename of terminal connected to stdin.
-
-	  Prints "not a tty" and exits with nonzero status if no terminal
-	  is connected to stdin.
-
-	  -s	silent mode
-*/
-
-#include "toys.h"
-
-void tty_main(void)
-{
-	char *tty = ttyname(0);
-
-	if (!toys.optflags) puts(tty ? tty : "not a tty");
-
-	toys.exitval = !tty;
-}
--- a/toys/uname.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * uname.c - return system name
- *
- * Copyright 2008 Rob Landley <rob@landley.net>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/uname.html
-
-USE_UNAME(NEWTOY(uname, "amvrns", TOYFLAG_BIN))
-
-config UNAME
-	bool "uname"
-	default y
-	help
-	  usage: uname [-asnrvmpio]
-
-	  Print system information.
-
-	  -s	System name
-	  -n	Network (domain) name
-	  -r	Release number
-	  -v	Version (build date)
-	  -m	Machine (hardware) name
-	  -a	All of the above
-*/
-
-#include "toys.h"
-
-// If a 32 bit x86 build environment working in a chroot under an x86-64
-// kernel returns x86_64 for -m it confuses ./configure.  Special case it.
-
-#if defined(__i686__)
-#define GROSS "i686"
-#elif defined(__i586__)
-#define GROSS "i586"
-#elif defined(__i486__)
-#define GROSS "i486"
-#elif defined(__i386__)
-#define GROSS "i386"
-#endif
-
-#define FLAG_a (1<<5)
-
-void uname_main(void)
-{
-	int i, flags = toys.optflags, needspace=0;
-
-	uname((void *)toybuf);
-
-	if (!flags) flags=1;
-	for (i=0; i<5; i++) {
-		char *c = toybuf+(65*i);
-
-		if (flags & ((1<<i)|FLAG_a)) {
-			int len = strlen(c);
-
-			// This problem originates in autoconf, so of course the solution
-			// is horribly ugly.
-#ifdef GROSS
-			if (i==4 && !strcmp(c,"x86_64")) printf(GROSS);
-	        else
-#endif
-
-			if (needspace++) {
-				// We can't decrement on the first entry, because
-				// needspace would be 0
-				*(--c)=' ';
-				len++;
-			}
-			xwrite(1, c, len);
-		}
-	}
-	putchar('\n');
-}
--- a/toys/uniq.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * uniq.c - report or filter out repeated lines in a file
- *
- * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
- *
- * See http://www.opengroup.org/onlinepubs/009695399/utilities/uniq.html
-
-USE_UNIQ(NEWTOY(uniq, "f#s#w#zicdu", TOYFLAG_BIN))
-
-config UNIQ
-	bool "uniq"
-	default y
-	help
-	  usage: uniq [-cduiz] [-w maxchars] [-f fields] [-s char] [input_file [output_file]]
-
-	  Report or filter out repeated lines in a file
-
-	  -c	show counts before each line
-	  -d	show only lines that are repeated
-	  -u	show only lines that are unique
-	  -i	ignore case when comparing lines
-	  -z	lines end with \0 not \n
-	  -w	compare maximum X chars per line
-	  -f	ignore first X fields
-	  -s	ignore first X chars
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	long maxchars;
-	long nchars;
-	long nfields;
-	long repeats;
-)
-
-#define TT this.uniq
-
-#define FLAG_z 16
-#define FLAG_i 8
-#define FLAG_c 4
-#define FLAG_d 2
-#define FLAG_u 1
-
-static char *skip(char *str)
-{
-	long nchars = TT.nchars, nfields;
-
-	// Skip fields first
-	for (nfields = TT.nfields; nfields; str++) {
-		while (*str && isspace(*str)) str++;
-		while (*str && !isspace(*str)) str++;
-		nfields--;
-	}
-	// Skip chars
-	while (*str && nchars--) str++;
-
-	return str;
-}
-
-static void print_line(FILE *f, char *line)
-{
-	if (toys.optflags & (TT.repeats ? FLAG_u : FLAG_d)) return;
-	if (toys.optflags & FLAG_c) fprintf(f, "%7lu ", TT.repeats + 1);
-	fputs(line, f);
-	if (toys.optflags & FLAG_z) fputc(0, f);
-}
-
-void uniq_main(void)
-{
-	FILE *infile = stdin, *outfile = stdout;
-	char *thisline = NULL, *prevline = NULL, *tmpline, eol = '\n';
-	size_t thissize, prevsize = 0, tmpsize;
-
-	if (toys.optc >= 1) infile = xfopen(toys.optargs[0], "r");
-	if (toys.optc >= 2) outfile = xfopen(toys.optargs[1], "w");
-
-	if (toys.optflags & FLAG_z) eol = 0;
-
-	// If first line can't be read
-	if (getdelim(&prevline, &prevsize, eol, infile) < 0)
-		return;
-
-	while (getdelim(&thisline, &thissize, eol, infile) > 0) {
-		int diff;
-		char *t1, *t2;
-
-		// If requested get the chosen fields + character offsets.
-		if (TT.nfields || TT.nchars) {
-			t1 = skip(thisline);
-			t2 = skip(prevline);
-		} else {
-			t1 = thisline;
-			t2 = prevline;
-		}
-
-		if (TT.maxchars == 0) {
-			diff = !(toys.optflags & FLAG_i)
-			        ? strcmp(t1, t2)
-			        : strcasecmp(t1, t2);
-		} else {
-			diff = !(toys.optflags & FLAG_i)
-			        ? strncmp(t1, t2, TT.maxchars)
-			        : strncasecmp(t1, t2, TT.maxchars);
-		}
-
-		if (diff == 0) { // same
-			TT.repeats++;
-		} else {
-			print_line(outfile, prevline);
-
-			TT.repeats = 0;
-
-			tmpline = prevline;
-			prevline = thisline;
-			thisline = tmpline;
-
-			tmpsize = prevsize;
-			prevsize = thissize;
-			thissize = tmpsize;
-		}
-	}
-
-	print_line(outfile, prevline);
-
-	if (CFG_TOYBOX_FREE) {
-		free(prevline);
-		free(thisline);
-	}
-}
--- a/toys/unlink.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * unlink.c - delete one file
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/unlink.html
-
-USE_UNLINK(NEWTOY(unlink, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
-
-config UNLINK
-	bool "unlink"
-	default y
-	help
-	  usage: unlink FILE
-
-	  Deletes one file.
-*/
-
-#include "toys.h"
-
-void unlink_main(void)
-{
-	if (unlink(*toys.optargs))
-		perror_exit("Couldn't unlink `%s'", *toys.optargs);
-}
--- a/toys/unshare.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * unshare.c - run command in new context
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
- *
- * Not in SUSv4.
-
-USE_UNSHARE(NEWTOY(unshare, "<1^nium", TOYFLAG_USR|TOYFLAG_BIN))
-
-config UNSHARE
-	bool "unshare"
-	default y
-	depends on TOYBOX_CONTAINER
-	help
-	  usage: unshare [-muin] COMMAND...
-
-	  Create new namespace(s) for this process and its children, so some
-	  attribute is not shared with the parent process.  This is part of
-	  Linux Containers.  Each process can have its own:
-
-	  -m	Mount/unmount tree
-	  -u	Host and domain names
-	  -i	SysV IPC (message queues, semaphores, shared memory)
-	  -n	Network address, sockets, routing, iptables
-*/
-
-#include "toys.h"
-#include <linux/sched.h>
-extern int unshare (int __flags);
-
-void unshare_main(void)
-{
-	unsigned flags[]={CLONE_NEWNS, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWNET,0};
-	unsigned f=0;
-	int i;
-
-	for (i=0; flags[i]; i++)
-		if (toys.optflags & (1<<i))
-			f |= flags[i];
-
-	if(unshare(f)) perror_exit("failed");
-
-	xexec(toys.optargs);
-}
--- a/toys/uptime.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * uptime.c - Tell how long the system has been running.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
-
-USE_UPTIME(NEWTOY(uptime, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-
-config UPTIME
-	bool "uptime"
-	default y
-	help
-	  usage: uptime
-
-	  Tell how long the system has been running and the system load
-	  averages for the past 1, 5 and 15 minutes.
-*/
-
-#include "toys.h"
-
-void uptime_main(void)
-{
-	struct sysinfo info;
-	time_t tmptime;
-	struct tm * now;
-	unsigned int days, hours, minutes;
-
-	// Obtain the data we need.
-	sysinfo(&info);
-	time(&tmptime);
-	now = localtime(&tmptime);
-
-	// Time
-	xprintf(" %02d:%02d:%02d up ", now->tm_hour, now->tm_min, now->tm_sec);
-	// Uptime
-	info.uptime /= 60;
-	minutes = info.uptime%60;
-	info.uptime /= 60;
-	hours = info.uptime%24;
-	days = info.uptime/24;
-	if (days) xprintf("%d day%s, ", days, (days!=1)?"s":"");
-	if (hours)
-		xprintf("%2d:%02d, ", hours, minutes);
-	else
-		printf("%d min, ", minutes);
-
-	printf(" load average: %.02f %.02f %.02f\n", info.loads[0]/65536.0,
-		info.loads[1]/65536.0, info.loads[2]/65536.0);
-
-}
--- a/toys/usleep.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * usleep.c - Wait for a number of microseconds.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * No standard.
-
-USE_USLEEP(NEWTOY(usleep, "<1", TOYFLAG_BIN))
-
-config USLEEP
-	bool "usleep"
-	default y
-	help
-	  usage: usleep MICROSECONDS
-
-	  Pause for MICROSECONDS microseconds.
-
-*/
-
-#include "toys.h"
-
-void usleep_main(void)
-{
-    struct timespec tv;
-    long delay = atol(*toys.optargs);
-    
-    tv.tv_sec = delay/1000000;
-    tv.tv_nsec = (delay%1000000) * 1000;
-    toys.exitval = !!nanosleep(&tv, NULL);
-
-}
--- a/toys/vmstat.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * vmstat.c - Report virtual memory statistics.
- *
- * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
- *
- * Not in SUSv4.
-
-USE_VMSTAT(NEWTOY(vmstat, ">2n", TOYFLAG_BIN))
-
-config VMSTAT
-	bool "vmstat"
-	default y
-	help
-	  usage: vmstat [-n] [delay [count]]
-	  -n Display the header only once
-	  delay The delay between updates in seconds, when not specified
-	        the average since boot is displayed.
-	  count Number of updates to display, the default is inifinite.
-*/
-
-#include "toys.h"
-
-void read_proc_stat(unsigned int * proc_running, unsigned int * proc_blocked,
-		uint64_t * sys_irq, uint64_t * sys_ctxt,
-		uint64_t * cpu_user, uint64_t * cpu_sys, uint64_t * cpu_idle, uint64_t * cpu_wait)
-{
-	char * off;
-	uint64_t c_user, c_nice, c_sys, c_irq, c_sirq;
-	int fd = xopen("/proc/stat", O_RDONLY);
-	size_t s = xread(fd, toybuf, sizeof(toybuf)-1);
-	toybuf[s] = 0;
-	if ( s == sizeof(toybuf)-1)
-		error_exit("/proc/stat is too large");
-
-	off = strstr(toybuf, "cpu ");
-	// Ignoring steal and guest fields for now.
-	if (off) sscanf(off, "cpu  %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 \
-		" %"PRIu64" %"PRIu64" %"PRIu64, &c_user, &c_nice, &c_sys, cpu_idle,
-		cpu_wait, &c_irq, &c_sirq);
-	*cpu_user = c_user + c_nice;
-	*cpu_sys = c_sys + c_irq + c_sirq;
-	off = strstr(toybuf, "intr");
-	if (off) sscanf(off, "intr %"PRIu64, sys_irq);
-
-	off = strstr(toybuf, "ctxt");
-	if (off) sscanf(off, "ctxt %"PRIu64, sys_ctxt);
-
-	off = strstr(toybuf, "procs_running");
-	if (off) sscanf(off, "procs_running %u", proc_running);
-	(*proc_running)--; // look, i'm invisible.
-
-	off = strstr(toybuf, "procs_blocked");
-	if (off) sscanf(off, "procs_blocked %u", proc_blocked);
-
-	close(fd);
-}
-
-void read_proc_meminfo(unsigned long * mem_swapped, unsigned long * mem_free,
-			unsigned long * mem_buff, unsigned long * mem_cache)
-{
-	char * off;
-	unsigned long swap_total, swap_free;
-	int fd = xopen("/proc/meminfo", O_RDONLY);
-	size_t s = xread(fd, toybuf, sizeof(toybuf)-1);
-	toybuf[s] = 0;
-	if ( s == sizeof(toybuf)-1)
-		error_exit("/proc/meminfo is too large");
-
-	off = strstr(toybuf, "MemFree");
-	if (off) sscanf(off, "MemFree: %lu kB", mem_free);
-
-	off = strstr(toybuf, "Buffers");
-	if (off) sscanf(off, "Buffers: %lu kB", mem_buff);
-
-	off = strstr(toybuf, "Cached");
-	if (off) sscanf(off, "Cached: %lu kB", mem_cache);
-
-	off = strstr(toybuf, "SwapFree");
-	if (off) sscanf(off, "SwapFree: %lu kB", &swap_free); 
-
-	off = strstr(toybuf, "SwapTotal");
-	if (off) sscanf(off, "SwapTotal: %lu kB", &swap_total);
-	*mem_swapped = swap_total - swap_free;
-
-	close(fd);
-}
-
-void read_proc_vmstat(unsigned long * io_pages_in, unsigned long * io_pages_out,
-			unsigned long * swap_bytes_in, unsigned long * swap_bytes_out)
-{
-	char * off;
-	unsigned long s_pages_in, s_pages_out;
-	unsigned long pagesize_kb = sysconf(_SC_PAGESIZE) / 1024L;
-	int fd = xopen("/proc/vmstat", O_RDONLY);
-	size_t s = xread(fd, toybuf, sizeof(toybuf)-1);
-	toybuf[s] = 0;
-	if ( s == sizeof(toybuf)-1)
-		error_exit("/proc/vmstat is too large");
-
-	off = strstr(toybuf, "pgpgin");
-	if (off) sscanf(off, "pgpgin %lu", io_pages_in);
-
-	off = strstr(toybuf, "pgpgout");
-	if (off) sscanf(off, "pgpgout %lu", io_pages_out);
-
-	off = strstr(toybuf, "pswpin");
-	if (off) sscanf(off, "pswpin %lu", &s_pages_in);
-	*swap_bytes_in = s_pages_in * pagesize_kb;
-
-	off = strstr(toybuf, "pswpout");
-	if (off) sscanf(off, "pswpout %lu", &s_pages_out);
-	*swap_bytes_out = s_pages_out * pagesize_kb;
-
-	close(fd);
-}
-
-void vmstat_main(void)
-{
-	const char fmt[] = "%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n";
-	unsigned int loop_num = 0, loop_max_num = 0, loop_delay = 0;
-	unsigned int running = 0, blocked = 0;
-	unsigned long mem_swap = 0, mem_free = 0, mem_buff = 0, mem_cache = 0;
-	unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2];
-	uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2];
-	int first_run = 1;
-	int no_header = toys.optflags & 0x1;
-	unsigned num_rows = 22;
-
-	if (toys.optc >= 1)
-		loop_delay = atoi(toys.optargs[0]);
-	if (toys.optc >= 2)
-		loop_max_num = atoi(toys.optargs[1]);
-
-	if (loop_max_num < 0 || loop_delay < 0)
-		error_exit("Invalid arguments");
-
-	while(1) {
-		uint64_t total_jif;
-		int idx = loop_num%2;
-
-		if(first_run || (!(loop_num % num_rows) && !no_header)) {
-			unsigned rows = 0, cols = 0;
-			terminal_size(&cols, &rows);
-			num_rows = (rows > 3)? rows - 3 : 22;
-			printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n");
-			printf(" r  b   swpd   free   buff  cache   si   so	bi	bo   in   cs us sy id wa\n");
-		}
-
-		read_proc_stat(&running, &blocked, &sys_irq[idx], &sys_ctxt[idx], &cpu_user[idx],
-					   &cpu_sys[idx], &cpu_idle[idx], &cpu_wait[idx]);
-		read_proc_meminfo(&mem_swap, &mem_free, &mem_buff, &mem_cache);
-		read_proc_vmstat(&io_pages_in[idx], &io_pages_out[idx], &swap_bytes_in[idx], &swap_bytes_out[idx]);
-
-		if (first_run) {
-			struct sysinfo inf;
-			sysinfo(&inf);
-			first_run = 0;
-			total_jif = cpu_user[idx] + cpu_idle[idx] + cpu_wait[idx];
-			printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache,
-				   (unsigned) (swap_bytes_in[idx]/inf.uptime),
-				   (unsigned) (swap_bytes_out[idx]/inf.uptime),
-				   (unsigned) (io_pages_in[idx]/inf.uptime),
-				   (unsigned) (io_pages_out[idx]/inf.uptime),
-				   (unsigned) (sys_irq[idx]/inf.uptime),
-				   (unsigned) (sys_ctxt[idx]/inf.uptime),
-				   (unsigned) (100*cpu_user[idx]/total_jif),
-				   (unsigned) (100*cpu_sys[idx]/total_jif),
-				   (unsigned) (100*cpu_idle[idx]/total_jif),
-				   (unsigned) (100*cpu_wait[idx]/total_jif));
-		}else{
-			total_jif = cpu_user[idx] - cpu_user[!idx] + cpu_idle[idx] - cpu_idle[!idx] + cpu_wait[idx] - cpu_wait[!idx];
-			printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache,
-				   (unsigned) ((swap_bytes_in[idx] - swap_bytes_in[!idx])/loop_delay),
-				   (unsigned) ((swap_bytes_out[idx] - swap_bytes_out[!idx])/loop_delay),
-				   (unsigned) ((io_pages_in[idx] - io_pages_in[!idx])/loop_delay),
-				   (unsigned) ((io_pages_out[idx] - io_pages_out[!idx])/loop_delay),
-				   (unsigned) ((sys_irq[idx] - sys_irq[!idx])/loop_delay),
-				   (unsigned) ((sys_ctxt[idx] - sys_ctxt[!idx])/loop_delay),
-				   (unsigned) (100*(cpu_user[idx] - cpu_user[!idx])/total_jif),
-				   (unsigned) (100*(cpu_sys[idx]  - cpu_sys[!idx]) /total_jif),
-				   (unsigned) (100*(cpu_idle[idx] - cpu_idle[!idx])/total_jif),
-				   (unsigned) (100*(cpu_wait[idx] - cpu_wait[!idx])/total_jif));
-		}
-
-		loop_num++;
-		if (loop_delay == 0 || (loop_max_num != 0 && loop_num >= loop_max_num))
-			break;
-		sleep(loop_delay);
-	}
-}
--- a/toys/w.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * w.c - shows logged in users
- *
- * Copyright 2012 Gaurang Shastri <gmshastri@gmail.com>
- *
- * Not in SUSv4.
-
-USE_W(NEWTOY(w, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-
-config W
-	bool "w"
-	default y
-	help
-	  usage: w 
-
-	  Show who is logged on and since how long they logged in.
-*/
-
-#include "toys.h"
-
-void w_main(void)
-{
-    struct utmpx *x;
-
-    xprintf("USER     TTY             LOGIN@              FROM");
-    setutxent();
-    while ((x=getutxent()) != NULL)
-        if (x->ut_type==7) {
-            time_t tt = x->ut_tv.tv_sec;
-
-            xprintf("\n%-9.8s%-9.8s %-4.24s (%-1.12s)", x->ut_user, x->ut_line,
-                ctime(&tt), x->ut_host);
-        }
-    xputc('\n');
-}
--- a/toys/wc.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * wc.c - Word count
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/wc.html
-
-USE_WC(NEWTOY(wc, "cwl", TOYFLAG_USR|TOYFLAG_BIN))
-
-config WC
-	bool "wc"
-	default y
-	help
-	  usage: wc -lwc [FILE...]
-
-	  Count lines, words, and characters in input.
-
-	  -l	show lines
-	  -w	show words
-	  -c	show characters
-
-	  By default outputs lines, words, characters, and filename for each
-	  argument (or from stdin if none).
-*/
-
-#include "toys.h"
-
-static void do_wc(int fd, char *name)
-{
-	int i, len;
-	unsigned long word=0, lengths[]={0,0,0};
-
-	for (;;) {
-		len = read(fd, toybuf, sizeof(toybuf));
-		if (len<0) {
-			perror_msg("%s",name);
-			toys.exitval = EXIT_FAILURE;
-		}
-		if (len<1) break;
-		for (i=0; i<len; i++) {
-			if (toybuf[i]==10) lengths[0]++;
-			if (isspace(toybuf[i])) word=0;
-			else {
-				if (!word) lengths[1]++;
-				word=1;
-			}
-			lengths[2]++;
-		}
-	}
-	for (i=0; i<3; i++)
-		if (!toys.optflags || (toys.optflags&(1<<i)))
-			printf("%ld ", lengths[i]);
-	printf("%s\n", (!toys.optflags && strcmp(name,"-")) ? name : "");
-}
-
-void wc_main(void)
-{
-	loopfiles(toys.optargs, do_wc);
-}
--- a/toys/which.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * which.c - Find executable files in $PATH.
- *
- * Copyright 2006 Rob landley <rob@landley.net>
- *
- * Not in SUSv3.
-
-USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
-
-config WHICH
-	bool "which"
-	default y
-	help
-	  usage: which [-a] filename ...
-
-	  Search $PATH for executable files matching filename(s).
-
-	  -a	Show all matches
-*/
-#include "toys.h"
-
-// Find an exectuable file either at a path with a slash in it (absolute or
-// relative to current directory), or in $PATH.  Returns absolute path to file,
-// or NULL if not found.
-
-static int which_in_path(char *filename)
-{
-	struct string_list *list;
-
-	// If they gave us a path, don't worry about $PATH or -a
-
-	if (strchr(filename, '/')) {
-		// Confirm it has the executable bit set, and it's not a directory.
-		if (!access(filename, X_OK)) {
-			struct stat st;
-
-			if (!stat(filename, &st) && S_ISREG(st.st_mode)) {
-				puts(filename);
-				return 0;
-			}
-			return 1;
-		}
-	}
-
-	// Search $PATH for matches.
-	list = find_in_path(getenv("PATH"), filename);
-	if (!list) return 1;
-
-	// Print out matches
-	while (list) {
-		if (!access(list->str, X_OK)) {
-			puts(list->str);
-			// If we should stop at one match, do so
-			if (!toys.optflags) {
-				llist_traverse(list, free);
-				break;
-			}
-		}
-		free(llist_pop(&list));
-	}
-
-	return 0;
-}
-
-void which_main(void)
-{
-	int i;
-	for (i=0; toys.optargs[i]; i++)
-		toys.exitval |= which_in_path(toys.optargs[i]);
-}
--- a/toys/who.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * who.c - display who is on the system
- *
- * Copyright 2012 ProFUSION Embedded Systems
- *
- * by Luis Felipe Strano Moraes <lfelipe@profusion.mobi>
- *
- * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/who.html
-
-USE_WHO(NEWTOY(who, NULL, TOYFLAG_BIN))
-
-config WHO
-	bool "who"
-	default n
-	help
-	  usage: who
-
-	  Print logged user information on system
-
-*/
-
-#include "toys.h"
-
-void who_main(void)
-{
-    struct utmpx *entry;
-
-    setutxent();
-
-    while ((entry = getutxent())) {
-        if (entry->ut_type == USER_PROCESS) {
-            time_t time;
-            int time_size;
-            char * times;
-
-            time = entry->ut_tv.tv_sec;
-            times = ctime(&time);
-            time_size = strlen(times) - 2;
-            printf("%s\t%s\t%*.*s\t(%s)\n", entry->ut_user, entry->ut_line, time_size, time_size, ctime(&time), entry->ut_host);
-
-        }
-    }
-
-    endutxent();
-}
--- a/toys/whoami.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * whoami.c - Print effective user name
- *
- * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
- *
-
-USE_WHOAMI(NEWTOY(whoami, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-
-config WHOAMI
-	bool "whoami"
-	default y
-	help
-	  usage: whoami
-
-	  Print effective user name.
-*/
-
-#include "toys.h"
-
-void whoami_main(void)
-{
-	struct passwd *pw = getpwuid(geteuid());
-
-	if (!pw) {
-		perror("getpwuid");
-		toys.exitval = 1;
-		return;
-	}
-
-	xputs(pw->pw_name);
-}
--- a/toys/xargs.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * xargs.c - Run command with arguments taken from stdin.
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
- *
- * See http://opengroup.org/onlinepubs/9699919799/utilities/xargs.html
-
-USE_XARGS(NEWTOY(xargs, "^I:E:L#ptxrn#<1s#0", TOYFLAG_USR|TOYFLAG_BIN))
-
-config XARGS
-	bool "xargs"
-	default y
-	help
-	  usage: xargs [-ptxr0] [-s NUM] [-n NUM] [-L NUM] [-E STR] COMMAND...
-
-	  Run command line one or more times, appending arguments from stdin.
-
-	  If command exits with 255, don't launch another even if arguments remain.
-
-	  -s	Size in bytes per command line
-	  -n	Max number of arguments per command
-	  -0	Each argument is NULL terminated, no whitespace or quote processing
-	  #-p	Prompt for y/n from tty before running each command
-	  #-t	Trace, print command line to stderr
-	  #-x	Exit if can't fit everything in one command
-	  #-r	Don't run command with empty input
-	  #-L	Max number of lines of input per command
-	  -E	stop at line matching string
-*/
-
-#include "toys.h"
-
-DEFINE_GLOBALS(
-	long max_bytes;
-	long max_entries;
-	long L;
-	char *eofstr;
-	char *I;
-
-	long entries, bytes;
-	char delim;
-)
-
-#define TT this.xargs
-
-// If out==NULL count TT.bytes and TT.entries, stopping at max.
-// Otherwise, fill out out[] 
-
-// Returning NULL means need more data.
-// Returning char * means hit data limits, start of data left over
-// Returning 1 means hit data limits, but consumed all data
-// Returning 2 means hit -E eofstr
-
-static char *handle_entries(char *data, char **entry)
-{
-	if (TT.delim) { 
-		char *s = data;
-
-		// Chop up whitespace delimited string into args
-		while (*s) {
-			char *save;
-
-			while (isspace(*s)) {
-				if (entry) *s = 0;
-				s++;
-			}
-
-			if (TT.max_entries && TT.entries >= TT.max_entries)
-				return *s ? s : (char *)1;
-
-			if (!*s) break;
-			save = s;
-
-			for (;;) {
-				if (++TT.bytes >= TT.max_bytes && TT.max_bytes) return save;
-				if (!*s || isspace(*s)) break;
-				s++;
-			}
-			if (TT.eofstr) {
-				int len = s-save;
-				if (len == strlen(TT.eofstr) && !strncmp(save, TT.eofstr, len))
-					return (char *)2;
-			}
-			if (entry) entry[TT.entries] = save;
-			++TT.entries;
-		}
-
-	// -0 support
-	} else {
-		TT.bytes += strlen(data)+1;
-		if (TT.max_bytes && TT.bytes >= TT.max_bytes) return data;
-		if (TT.max_entries && TT.entries >= TT.max_entries)
-			return (char *)1;
-		if (entry) entry[TT.entries] = data;
-		TT.entries++;
-	}
-
-	return NULL;
-}
-
-void xargs_main(void)
-{
-	struct double_list *dlist = NULL;
-	int entries, bytes, done = 0, status;
-	char *data = NULL;
-
-	if (!(toys.optflags&1)) TT.delim = '\n';
-
-	// If no optargs, call echo.
-	if (!toys.optc) {
-		free(toys.optargs);
-		*(toys.optargs = xzalloc(2*sizeof(char *)))="echo";
-		toys.optc = 1;
-	}
-
-	for (entries = 0, bytes = -1; entries < toys.optc; entries++, bytes++)
-		bytes += strlen(toys.optargs[entries]);
-
-	// Loop through exec chunks.
-	while (data || !done) {
-		char **out;
-
-		TT.entries = 0;
-		TT.bytes = bytes;
-
-		// Loop reading input
-		for (;;) {
-
-			// Read line
-			if (!data) {
-				ssize_t l = 0;
-				l = getdelim(&data, (size_t *)&l, TT.delim, stdin);
-
-				if (l<0) {
-					data = 0;
-					done++;
-					break;
-				}
-			}
-			dlist_add(&dlist, data);
-
-			// Count data used
-			data = handle_entries(data, NULL);
-			if (!data) continue;
-			if (data == (char *)2) done++;
-			if ((long)data <= 2) data = 0;
-			else data = xstrdup(data);
-
-			break;
-		}
-
-		// Accumulate cally thing
-
-		if (data && !TT.entries) error_exit("argument too long");
-		out = xzalloc((entries+TT.entries+1)*sizeof(char *));
-
-		if (dlist) {
-			struct double_list *dtemp;
-
-			// Fill out command line to exec
-			memcpy(out, toys.optargs, entries*sizeof(char *));
-			TT.entries = 0;
-			TT.bytes = bytes;
-			dlist->prev->next = 0;
-			for (dtemp = dlist; dtemp; dtemp = dtemp->next)
-				handle_entries(dtemp->data, out+entries);
-		}
-		pid_t pid=fork();
-		if (!pid) {
-			xclose(0);
-			open("/dev/null", O_RDONLY);
-			xexec(out);
-		}
-		waitpid(pid, &status, 0);
-		status = WEXITSTATUS(status);
-
-		// Abritrary number of execs, can't just leak memory each time...
-		while (dlist) {
-			struct double_list *dtemp = dlist->next;
-
-			free(dlist->data);
-			free(dlist);
-			dlist = dtemp;
-		}
-		free(out);
-	}
-}
--- a/toys/yes.c	Sat Aug 25 14:24:24 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/* vi: set sw=4 ts=4:
- *
- * yes.c - Repeatedly output a string.
- *
- * Copyright 2007 Rob Landley <rob@landley.net>
- *
- * Not in SUSv3.
-
-USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-
-config YES
-	bool "yes"
-	default y
-	help
-	  usage: yes [args...]
-
-	  Repeatedly output line until killed.  If no args, output 'y'.
-*/
-
-#include "toys.h"
-
-void yes_main(void)
-{
-	for (;;) {
-		int i;
-		for (i=0; toys.optargs[i]; i++) {
-			if (i) xputc(' ');
-			xprintf("%s", toys.optargs[i]);
-		}
-		if (!i) xputc('y');
-		xputc('\n');
-	}
-}