More stuff works.
 -Erik
diff --git a/Makefile b/Makefile
index bef25a3..62c4ac6 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@
 # For debugging only
 #CFLAGS=-Wall -g -D_GNU_SOURCE
 LIBRARIES=-lc
-OBJECTS=$(shell ./busybox.obj) utility.o
+OBJECTS=$(shell ./busybox.sh) utility.o
 
 CFLAGS+= -DBB_VER='"$(VERSION)"'
 CFLAGS+= -DBB_BT='"$(BUILDTIME)"'
@@ -36,3 +36,5 @@
 	- rm -f busybox
 
 force:
+
+$(OBJECTS):  busybox.def.h Makefile
diff --git a/applets/busybox.c b/applets/busybox.c
index b7b2b60..08ba88d 100644
--- a/applets/busybox.c
+++ b/applets/busybox.c
@@ -16,14 +16,12 @@
 #ifdef BB_CAT			//bin
     {"cat", cat_more_main},
 #endif
-#ifdef BB_CHGRP			//bin
-    {"chgrp", chgrp_main},
-#endif
 #ifdef BB_CHMOD			//bin
     {"chmod", chmod_main},
 #endif
 #ifdef BB_CHOWN			//bin
     {"chown", chown_main},
+    {"chgrp", chown_main},
 #endif
 #ifdef BB_CHROOT		//sbin
     {"chroot", chroot_main},
diff --git a/busybox.c b/busybox.c
index b7b2b60..08ba88d 100644
--- a/busybox.c
+++ b/busybox.c
@@ -16,14 +16,12 @@
 #ifdef BB_CAT			//bin
     {"cat", cat_more_main},
 #endif
-#ifdef BB_CHGRP			//bin
-    {"chgrp", chgrp_main},
-#endif
 #ifdef BB_CHMOD			//bin
     {"chmod", chmod_main},
 #endif
 #ifdef BB_CHOWN			//bin
     {"chown", chown_main},
+    {"chgrp", chown_main},
 #endif
 #ifdef BB_CHROOT		//sbin
     {"chroot", chroot_main},
diff --git a/busybox.def.h b/busybox.def.h
index ad6480a..7d49ed0 100644
--- a/busybox.def.h
+++ b/busybox.def.h
@@ -6,11 +6,10 @@
 //#define BB_BLOCK_DEVICE
 #define BB_BUSYBOX
 #define BB_CAT
-#define BB_CHGRP
 //#define BB_CHMOD
-//#define BB_CHOWN
-//#define BB_CHROOT
-//#define BB_CLEAR
+#define BB_CHOWN
+#define BB_CHROOT
+#define BB_CLEAR
 //#define BB_CP
 //#define BB_DATE
 //#define BB_DD
@@ -19,7 +18,7 @@
 //#define BB_DMESG
 //#define BB_DUTMP
 //#define BB_DYADIC
-//#define BB_FALSE
+#define BB_FALSE
 //#define BB_FDFLUSH
 //#define BB_FIND
 //#define BB_FINDMOUNT
@@ -56,7 +55,7 @@
 //#define BB_SYNC
 //#define BB_TAR
 //#define BB_TOUCH
-//#define BB_TRUE
+#define BB_TRUE
 //#define BB_UMOUNT
 //#define BB_UPDATE
 //#define BB_UTILITY
diff --git a/cat.c b/cat.c
index 12faf55..0f2460e 100644
--- a/cat.c
+++ b/cat.c
@@ -31,7 +31,7 @@
 
     if (argc < 2) {
 	fprintf(stderr, "Usage: %s %s", *argv, cat_usage);
-	return 1;
+	return(FALSE);
     }
     argc--;
     argv++;
@@ -39,8 +39,8 @@
     while (argc-- > 0) {
 	file = fopen(*argv, "r");
 	if (file == NULL) {
-	    name_and_error(*argv);
-	    return 1;
+	    perror(*argv);
+	    return(FALSE);
 	}
 	while ((c = getc(file)) != EOF)
 	    putc(c, stdout);
@@ -50,5 +50,5 @@
 	argc--;
 	argv++;
     }
-    return 0;
+    return(TRUE);
 }
diff --git a/chgrp.c b/chgrp.c
deleted file mode 100644
index 038c665..0000000
--- a/chgrp.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Mini chgrp implementation for busybox
- *
- * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "internal.h"
-#include <grp.h>
-#include <stdio.h>
-
-const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n"
-    "Change the group membership of each FILE to GROUP.\n"
-    "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
-
-int chgrp_main(int argc, char **argv)
-{
-    const char *cp;
-    int gid;
-    struct group *grp;
-    struct stat statBuf;
-
-    if (argc < 2) {
-	fprintf(stderr, "Usage: %s %s", *argv, chgrp_usage);
-	return 1;
-    }
-    argc--;
-    argv++;
-
-    cp = argv[1];
-    if (isDecimal(*cp)) {
-	gid = 0;
-	while (isDecimal(*cp))
-	    gid = gid * 10 + (*cp++ - '0');
-	if (*cp) {
-	    fprintf(stderr, "Bad gid value\n");
-	    return -1;
-	}
-    } else {
-	grp = getgrnam(cp);
-	if (grp == NULL) {
-	    fprintf(stderr, "Unknown group name\n");
-	    return -1;
-	}
-	gid = grp->gr_gid;
-    }
-    argc--;
-    argv++;
-    while (argc-- > 1) {
-	argv++;
-	if ((stat(*argv, &statBuf) < 0) ||
-	    (chown(*argv, statBuf.st_uid, gid) < 0)) {
-	    perror(*argv);
-	}
-    }
-    return 1;
-}
-
-
-
-
-
-
-
-
-
-#if 0
-int
-recursive(const char *fileName, BOOL followLinks, const char *pattern,
-	  int (*fileAction) (const char *fileName,
-			     const struct stat * statbuf),
-	  int (*dirAction) (const char *fileName,
-			    const struct stat * statbuf))
-
-#endif
diff --git a/chown.c b/chown.c
index a611f92..fc0c242 100644
--- a/chown.c
+++ b/chown.c
@@ -1,63 +1,125 @@
-#include "internal.h"
-#include <pwd.h>
-#include <grp.h>
-#include <string.h>
+/*
+ * Mini chown/chgrp implementation for busybox
+ *
+ * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
 #include <stdio.h>
+#include <grp.h>
+#include <pwd.h>
+#include "internal.h"
 
-const char	chown_usage[] = "chown [-R] user-name file [file ...]\n"
-"\n\tThe group list is kept in the file /etc/groups.\n\n"
-"\t-R:\tRecursively change the mode of all files and directories\n"
-"\t\tunder the argument directory.";
 
-int
-parse_user_name(const char * s, struct FileInfo * i)
+static int uid=-1;
+static int gid=0;
+static int chownApp;
+static char* invocationName=NULL;
+
+
+const char chgrp_usage[] = "[OPTION]... GROUP FILE...\n"
+    "Change the group membership of each FILE to GROUP.\n"
+    "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
+const char chown_usage[] = "[OPTION]...  OWNER[.[GROUP] FILE...\n"
+    "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n"
+    "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
+
+
+
+static int fileAction(const char *fileName)
 {
-	struct	passwd * 	p;
-	char *				dot = strchr(s, '.');
-
-	if (! dot )
-		dot = strchr(s, ':');
-
-	if ( dot )
-		*dot = '\0';
-
-	if ( (p = getpwnam(s)) == 0 ) {
-		fprintf(stderr, "%s: no such user.\n", s);
-		return 1;
-	}
-	i->userID = p->pw_uid;
-
-	if ( dot ) {
-		struct group *	g = getgrnam(++dot);
-		if ( g == 0 ) {
-			fprintf(stderr, "%s: no such group.\n", dot);
-			return 1;
-		}
-		i->groupID = g->gr_gid;
-		i->changeGroupID = 1;
-	}
-	return 0;
+    struct stat statBuf;
+    if ((stat(fileName, &statBuf) < 0) || 
+	    (chown(fileName, 
+		   ((chownApp==TRUE)? uid: statBuf.st_uid), 
+		   gid) < 0)) { 
+	perror(fileName);
+	return( TRUE);
+    }
+    return( FALSE);
 }
 
-extern int
-chown_main(struct FileInfo * i, int argc, char * * argv)
+int chown_main(int argc, char **argv)
 {
-	int					status;
+    struct group *grp;
+    struct passwd *pwd;
+    int recursiveFlag=FALSE;
+    char *groupName;
 
-	while ( argc >= 3 && strcmp("-R", argv[1]) == 0 ) {
-		i->recursive = 1;
-		argc--;
-		argv++;
+
+    chownApp = (strcmp(*argv, "chown")==0)? TRUE : FALSE;
+
+    if (argc < 2) {
+	fprintf(stderr, "Usage: %s %s", *argv, 
+		(chownApp==TRUE)? chown_usage : chgrp_usage);
+	return( FALSE);
+    }
+    invocationName=*argv;
+    argc--;
+    argv++;
+
+    /* Parse options */
+    while (**argv == '-') {
+	while (*++(*argv)) switch (**argv) {
+	    case 'R':
+		recursiveFlag = TRUE;
+		break;
+	    default:
+		fprintf(stderr, "Unknown option: %c\n", **argv);
+		return( FALSE);
 	}
-
-	if ( (status = parse_user_name(argv[1], i)) != 0 )
-		return status;
-
-	argv++;
 	argc--;
+	argv++;
+    }
+    
+    /* Find the selected group */
+    groupName = strchr(*argv, '.');
+    if ( chownApp==TRUE && groupName )
+	*groupName++ = '\0';
+    else
+	groupName = *argv;
+    grp = getgrnam(groupName);
+    if (grp == NULL) {
+	fprintf(stderr, "%s: Unknown group name: %s\n", invocationName, groupName);
+	return( FALSE);
+    }
+    gid = grp->gr_gid;
 
-	i->changeUserID = 1;
-	i->complainInPostProcess = 1;
+    /* Find the selected user (if appropriate)  */
+    if (chownApp==TRUE) {
+	pwd = getpwnam(*argv);
+	if (pwd == NULL) {
+	    fprintf(stderr, "%s: Unknown user name: %s\n", invocationName, *argv);
+	    return( FALSE);
+	}
+	uid = pwd->pw_uid;
+    }
 
-	return monadic_main(i, argc, argv);
+    /* Ok, ready to do the deed now */
+    if (argc <= 1) {
+	fprintf(stderr, "%s: too few arguments", invocationName);
+	return( FALSE);
+    }
+    while (argc-- > 1) {
+	argv++;
+	if (recursiveFlag==TRUE) 
+	    recursiveAction( *argv, TRUE, fileAction, fileAction);
+	else
+	    fileAction( *argv);
+    }
+    return(TRUE);
 }
diff --git a/chroot.c b/chroot.c
index ca0bfcf..d395494 100644
--- a/chroot.c
+++ b/chroot.c
@@ -1,32 +1,65 @@
+/*
+ * Mini chroot implementation for busybox
+ *
+ * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
 #include "internal.h"
 #include <stdio.h>
 #include <unistd.h>
 
 
-const char chroot_usage[] = "chroot directory [command]\n"
-  "Run a command with special root directory.\n";
+static const char chroot_usage[] = "NEWROOT [COMMAND...]\n"
+"Run COMMAND with root directory set to NEWROOT.\n";
 
-extern int
-chroot_main (struct FileInfo *i, int argc, char **argv)
+
+
+int chroot_main(int argc, char **argv)
 {
-  char *prog;
+    if (argc < 2) {
+	fprintf(stderr, "Usage: %s %s", *argv, chroot_usage);
+	return( FALSE);
+    }
+    argc--;
+    argv++;
 
-  if (chroot (argv[1]))
-    {
-      name_and_error ("cannot chroot to that directory");
-      return 1;
+    fprintf(stderr, "new root: %s\n", *argv);
+    
+    if (chroot (*argv) || (chdir ("/"))) {
+	perror("cannot chroot");
+	return( FALSE);
     }
-  if (argc > 2)
-    {
-      execvp (argv[2], argv + 2);
+
+    argc--;
+    argv++;
+    if (argc >= 1) {
+	fprintf(stderr, "command: %s\n", *argv);
+	execvp (*argv, argv);
     }
-  else
-    {
-      prog = getenv ("SHELL");
-      if (!prog)
-	prog = "/bin/sh";
-      execlp (prog, prog, NULL);
+    else {
+	char *prog;
+	prog = getenv ("SHELL");
+	if (!prog)
+	    prog = "/bin/sh";
+	fprintf(stderr, "no command. running: %s\n", prog);
+	execlp (prog, prog, NULL);
     }
-  name_and_error ("cannot exec");
-  return 1;
+    perror("cannot exec");
+    return(FALSE);
 }
+
diff --git a/clear.c b/clear.c
index 21a890c..c0c94d0 100644
--- a/clear.c
+++ b/clear.c
@@ -1,12 +1,30 @@
+/*
+ * Mini clear implementation for busybox
+ *
+ * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
 #include "internal.h"
 #include <stdio.h>
 
-const char	clear_usage[] = "clear\n"
-"\n"
-"\tClears the screen.\n";
 
 extern int
-clear_main(struct FileInfo * i, int argc, char * * argv)
+clear_main(int argc, char** argv)
 {
 	printf("\033[H\033[J");
 	return 0;
diff --git a/console-tools/clear.c b/console-tools/clear.c
index 21a890c..c0c94d0 100644
--- a/console-tools/clear.c
+++ b/console-tools/clear.c
@@ -1,12 +1,30 @@
+/*
+ * Mini clear implementation for busybox
+ *
+ * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
 #include "internal.h"
 #include <stdio.h>
 
-const char	clear_usage[] = "clear\n"
-"\n"
-"\tClears the screen.\n";
 
 extern int
-clear_main(struct FileInfo * i, int argc, char * * argv)
+clear_main(int argc, char** argv)
 {
 	printf("\033[H\033[J");
 	return 0;
diff --git a/coreutils/cat.c b/coreutils/cat.c
index 12faf55..0f2460e 100644
--- a/coreutils/cat.c
+++ b/coreutils/cat.c
@@ -31,7 +31,7 @@
 
     if (argc < 2) {
 	fprintf(stderr, "Usage: %s %s", *argv, cat_usage);
-	return 1;
+	return(FALSE);
     }
     argc--;
     argv++;
@@ -39,8 +39,8 @@
     while (argc-- > 0) {
 	file = fopen(*argv, "r");
 	if (file == NULL) {
-	    name_and_error(*argv);
-	    return 1;
+	    perror(*argv);
+	    return(FALSE);
 	}
 	while ((c = getc(file)) != EOF)
 	    putc(c, stdout);
@@ -50,5 +50,5 @@
 	argc--;
 	argv++;
     }
-    return 0;
+    return(TRUE);
 }
diff --git a/coreutils/chgrp.c b/coreutils/chgrp.c
deleted file mode 100644
index 038c665..0000000
--- a/coreutils/chgrp.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Mini chgrp implementation for busybox
- *
- * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "internal.h"
-#include <grp.h>
-#include <stdio.h>
-
-const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n"
-    "Change the group membership of each FILE to GROUP.\n"
-    "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
-
-int chgrp_main(int argc, char **argv)
-{
-    const char *cp;
-    int gid;
-    struct group *grp;
-    struct stat statBuf;
-
-    if (argc < 2) {
-	fprintf(stderr, "Usage: %s %s", *argv, chgrp_usage);
-	return 1;
-    }
-    argc--;
-    argv++;
-
-    cp = argv[1];
-    if (isDecimal(*cp)) {
-	gid = 0;
-	while (isDecimal(*cp))
-	    gid = gid * 10 + (*cp++ - '0');
-	if (*cp) {
-	    fprintf(stderr, "Bad gid value\n");
-	    return -1;
-	}
-    } else {
-	grp = getgrnam(cp);
-	if (grp == NULL) {
-	    fprintf(stderr, "Unknown group name\n");
-	    return -1;
-	}
-	gid = grp->gr_gid;
-    }
-    argc--;
-    argv++;
-    while (argc-- > 1) {
-	argv++;
-	if ((stat(*argv, &statBuf) < 0) ||
-	    (chown(*argv, statBuf.st_uid, gid) < 0)) {
-	    perror(*argv);
-	}
-    }
-    return 1;
-}
-
-
-
-
-
-
-
-
-
-#if 0
-int
-recursive(const char *fileName, BOOL followLinks, const char *pattern,
-	  int (*fileAction) (const char *fileName,
-			     const struct stat * statbuf),
-	  int (*dirAction) (const char *fileName,
-			    const struct stat * statbuf))
-
-#endif
diff --git a/coreutils/chown.c b/coreutils/chown.c
index a611f92..fc0c242 100644
--- a/coreutils/chown.c
+++ b/coreutils/chown.c
@@ -1,63 +1,125 @@
-#include "internal.h"
-#include <pwd.h>
-#include <grp.h>
-#include <string.h>
+/*
+ * Mini chown/chgrp implementation for busybox
+ *
+ * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
 #include <stdio.h>
+#include <grp.h>
+#include <pwd.h>
+#include "internal.h"
 
-const char	chown_usage[] = "chown [-R] user-name file [file ...]\n"
-"\n\tThe group list is kept in the file /etc/groups.\n\n"
-"\t-R:\tRecursively change the mode of all files and directories\n"
-"\t\tunder the argument directory.";
 
-int
-parse_user_name(const char * s, struct FileInfo * i)
+static int uid=-1;
+static int gid=0;
+static int chownApp;
+static char* invocationName=NULL;
+
+
+const char chgrp_usage[] = "[OPTION]... GROUP FILE...\n"
+    "Change the group membership of each FILE to GROUP.\n"
+    "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
+const char chown_usage[] = "[OPTION]...  OWNER[.[GROUP] FILE...\n"
+    "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n"
+    "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
+
+
+
+static int fileAction(const char *fileName)
 {
-	struct	passwd * 	p;
-	char *				dot = strchr(s, '.');
-
-	if (! dot )
-		dot = strchr(s, ':');
-
-	if ( dot )
-		*dot = '\0';
-
-	if ( (p = getpwnam(s)) == 0 ) {
-		fprintf(stderr, "%s: no such user.\n", s);
-		return 1;
-	}
-	i->userID = p->pw_uid;
-
-	if ( dot ) {
-		struct group *	g = getgrnam(++dot);
-		if ( g == 0 ) {
-			fprintf(stderr, "%s: no such group.\n", dot);
-			return 1;
-		}
-		i->groupID = g->gr_gid;
-		i->changeGroupID = 1;
-	}
-	return 0;
+    struct stat statBuf;
+    if ((stat(fileName, &statBuf) < 0) || 
+	    (chown(fileName, 
+		   ((chownApp==TRUE)? uid: statBuf.st_uid), 
+		   gid) < 0)) { 
+	perror(fileName);
+	return( TRUE);
+    }
+    return( FALSE);
 }
 
-extern int
-chown_main(struct FileInfo * i, int argc, char * * argv)
+int chown_main(int argc, char **argv)
 {
-	int					status;
+    struct group *grp;
+    struct passwd *pwd;
+    int recursiveFlag=FALSE;
+    char *groupName;
 
-	while ( argc >= 3 && strcmp("-R", argv[1]) == 0 ) {
-		i->recursive = 1;
-		argc--;
-		argv++;
+
+    chownApp = (strcmp(*argv, "chown")==0)? TRUE : FALSE;
+
+    if (argc < 2) {
+	fprintf(stderr, "Usage: %s %s", *argv, 
+		(chownApp==TRUE)? chown_usage : chgrp_usage);
+	return( FALSE);
+    }
+    invocationName=*argv;
+    argc--;
+    argv++;
+
+    /* Parse options */
+    while (**argv == '-') {
+	while (*++(*argv)) switch (**argv) {
+	    case 'R':
+		recursiveFlag = TRUE;
+		break;
+	    default:
+		fprintf(stderr, "Unknown option: %c\n", **argv);
+		return( FALSE);
 	}
-
-	if ( (status = parse_user_name(argv[1], i)) != 0 )
-		return status;
-
-	argv++;
 	argc--;
+	argv++;
+    }
+    
+    /* Find the selected group */
+    groupName = strchr(*argv, '.');
+    if ( chownApp==TRUE && groupName )
+	*groupName++ = '\0';
+    else
+	groupName = *argv;
+    grp = getgrnam(groupName);
+    if (grp == NULL) {
+	fprintf(stderr, "%s: Unknown group name: %s\n", invocationName, groupName);
+	return( FALSE);
+    }
+    gid = grp->gr_gid;
 
-	i->changeUserID = 1;
-	i->complainInPostProcess = 1;
+    /* Find the selected user (if appropriate)  */
+    if (chownApp==TRUE) {
+	pwd = getpwnam(*argv);
+	if (pwd == NULL) {
+	    fprintf(stderr, "%s: Unknown user name: %s\n", invocationName, *argv);
+	    return( FALSE);
+	}
+	uid = pwd->pw_uid;
+    }
 
-	return monadic_main(i, argc, argv);
+    /* Ok, ready to do the deed now */
+    if (argc <= 1) {
+	fprintf(stderr, "%s: too few arguments", invocationName);
+	return( FALSE);
+    }
+    while (argc-- > 1) {
+	argv++;
+	if (recursiveFlag==TRUE) 
+	    recursiveAction( *argv, TRUE, fileAction, fileAction);
+	else
+	    fileAction( *argv);
+    }
+    return(TRUE);
 }
diff --git a/coreutils/chroot.c b/coreutils/chroot.c
index ca0bfcf..d395494 100644
--- a/coreutils/chroot.c
+++ b/coreutils/chroot.c
@@ -1,32 +1,65 @@
+/*
+ * Mini chroot implementation for busybox
+ *
+ * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
 #include "internal.h"
 #include <stdio.h>
 #include <unistd.h>
 
 
-const char chroot_usage[] = "chroot directory [command]\n"
-  "Run a command with special root directory.\n";
+static const char chroot_usage[] = "NEWROOT [COMMAND...]\n"
+"Run COMMAND with root directory set to NEWROOT.\n";
 
-extern int
-chroot_main (struct FileInfo *i, int argc, char **argv)
+
+
+int chroot_main(int argc, char **argv)
 {
-  char *prog;
+    if (argc < 2) {
+	fprintf(stderr, "Usage: %s %s", *argv, chroot_usage);
+	return( FALSE);
+    }
+    argc--;
+    argv++;
 
-  if (chroot (argv[1]))
-    {
-      name_and_error ("cannot chroot to that directory");
-      return 1;
+    fprintf(stderr, "new root: %s\n", *argv);
+    
+    if (chroot (*argv) || (chdir ("/"))) {
+	perror("cannot chroot");
+	return( FALSE);
     }
-  if (argc > 2)
-    {
-      execvp (argv[2], argv + 2);
+
+    argc--;
+    argv++;
+    if (argc >= 1) {
+	fprintf(stderr, "command: %s\n", *argv);
+	execvp (*argv, argv);
     }
-  else
-    {
-      prog = getenv ("SHELL");
-      if (!prog)
-	prog = "/bin/sh";
-      execlp (prog, prog, NULL);
+    else {
+	char *prog;
+	prog = getenv ("SHELL");
+	if (!prog)
+	    prog = "/bin/sh";
+	fprintf(stderr, "no command. running: %s\n", prog);
+	execlp (prog, prog, NULL);
     }
-  name_and_error ("cannot exec");
-  return 1;
+    perror("cannot exec");
+    return(FALSE);
 }
+
diff --git a/internal.h b/internal.h
index e658d3b..75e5503 100644
--- a/internal.h
+++ b/internal.h
@@ -1,3 +1,26 @@
+/*
+ * Busybox main header file
+ *
+ * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Based in part on code from sash, Copyright (c) 1999 by David I. Bell 
+ * Permission has been granted to redistribute this code under the GPL.
+ *
+ */
 #ifndef	_INTERNAL_H_
 #define	_INTERNAL_H_
 
@@ -13,8 +36,8 @@
 typedef int     BOOL;
 #define STDIN	0
 #define STDOUT	1
-#define FALSE   ((BOOL) 0)
-#define TRUE    ((BOOL) 1)
+#define FALSE   ((BOOL) 1)
+#define TRUE    ((BOOL) 0)
 
 #define PATH_LEN        1024
 #define BUF_SIZE        8192
@@ -129,60 +152,36 @@
 
 extern int		parse_user_name(const char* string, struct FileInfo * i);
 
-extern const char	block_device_usage[];
-extern const char	chgrp_usage[];
-extern const char	chmod_usage[];
-extern const char	chown_usage[];
-extern const char	chroot_usage[];
-extern const char	clear_usage[];
-extern const char	cp_usage[];
-extern const char	date_usage[];
-extern const char	dd_usage[];
-extern const char	df_usage[];
-extern const char	dmesg_usage[];
-extern const char	dutmp_usage[];
-extern const char	false_usage[];
-extern const char	fdflush_usage[];
-extern const char	find_usage[];
-extern const char	grep_usage[];
-extern const char	halt_usage[];
-extern const char	init_usage[];
-extern const char	kill_usage[];
-extern const char	length_usage[];
-extern const char	ln_usage[];
-extern const char	loadkmap_usage[];
-extern const char	losetup_usage[];
-extern const char	ls_usage[];
-extern const char	math_usage[];
-extern const char	makedevs_usage[];
-extern const char	mkdir_usage[];
-extern const char	mknod_usage[];
-extern const char	mkswap_usage[];
-extern const char	mnc_usage[];
-extern const char	more_usage[];
-extern const char	mount_usage[];
-extern const char	mt_usage[];
-extern const char	mv_usage[];
-extern const char	printf_usage[];
-extern const char	pwd_usage[];
-extern const char	reboot_usage[];
-extern const char	rm_usage[];
-extern const char	rmdir_usage[];
-extern const char	scan_partitions_usage[];
-extern const char	sleep_usage[];
-extern const char	tar_usage[];
-extern const char	swapoff_usage[];
-extern const char	swapon_usage[];
-extern const char	sync_usage[];
-extern const char	touch_usage[];
-extern const char	tput_usage[];
-extern const char	true_usage[];
-extern const char	tryopen_usage[];
-extern const char	umount_usage[];
-extern const char	update_usage[];
-extern const char	zcat_usage[];
-extern const char	gzip_usage[];
 
+/*
+ * A chunk of data.
+ * Chunks contain data which is allocated as needed, but which is
+ * not freed until all of the data needs freeing, such as at
+ * the beginning of the next command.
+ */
+typedef struct chunk CHUNK;
+#define CHUNK_INIT_SIZE 4
+
+struct chunk {
+    CHUNK *next;
+    char data[CHUNK_INIT_SIZE];	/* actually of varying length */
+};
+
+const char *modeString(int mode);
+const char *timeString(time_t timeVal);
+BOOL isDirectory(const char *name);
+BOOL isDevice(const char *name);
+BOOL copyFile(const char *srcName, const char *destName, BOOL setModes);
+const char *buildName(const char *dirName, const char *fileName);
+BOOL makeString(int argc, const char **argv, char *buf, int bufLen);
+char *getChunk(int size);
+char *chunkstrdup(const char *str);
+void freeChunks(void);
+int fullWrite(int fd, const char *buf, int len);
+int fullRead(int fd, char *buf, int len);
+int recursiveAction(const char *fileName, BOOL followLinks,
+	  int (*fileAction) (const char *fileName),
+	  int (*dirAction) (const char *fileName));
 
 
 #endif
diff --git a/utility.c b/utility.c
index 6825971..a516355 100644
--- a/utility.c
+++ b/utility.c
@@ -22,7 +22,16 @@
  *
  */
 
-#include "utility.h"
+#include "internal.h"
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+//#include <sys/types.h>
+//#include <sys/stat.h>
+#include <dirent.h>
+#include <time.h>
+#include <utime.h>
 
 #if 0
 
@@ -54,13 +63,6 @@
 
 static	CHUNK *	chunkList;
 
-extern void
-name_and_error(const char * name)
-{
-	fprintf(stderr, "%s: %s\n", name, strerror(errno));
-}
-
-
 
 /*
  * Return the standard ls-like mode string from a file mode.
@@ -130,36 +132,6 @@
 
 
 /*
- * Get the time string to be used for a file.
- * This is down to the minute for new files, but only the date for old files.
- * The string is returned from a static buffer, and so is overwritten for
- * each call.
- */
-const char *
-timeString(time_t timeVal)
-{
-	time_t		now;
-	char *		str;
-	static	char	buf[26];
-
-	time(&now);
-
-	str = ctime(&timeVal);
-
-	strcpy(buf, &str[4]);
-	buf[12] = '\0';
-
-	if ((timeVal > now) || (timeVal < now - 365*24*60*60L))
-	{
-		strcpy(&buf[7], &str[20]);
-		buf[11] = '\0';
-	}
-
-	return buf;
-}
-
-
-/*
  * Return TRUE if a fileName is a directory.
  * Nonexistant files return FALSE.
  */
@@ -325,624 +297,6 @@
 
 
 /*
- * Expand the wildcards in a fileName wildcard pattern, if any.
- * Returns an argument list with matching fileNames in sorted order.
- * The expanded names are stored in memory chunks which can later all
- * be freed at once.  The returned list is only valid until the next
- * call or until the next command.  Returns zero if the name is not a
- * wildcard, or returns the count of matched files if the name is a
- * wildcard and there was at least one match, or returns -1 if either
- * no fileNames matched or there was an allocation error.
- */
-int
-expandWildCards(const char * fileNamePattern, const char *** retFileTable)
-{
-	const char *	last;
-	const char *	cp1;
-	const char *	cp2;
-	const char *	cp3;
-	char *		str;
-	DIR *		dirp;
-	struct dirent *	dp;
-	int		dirLen;
-	int		newFileTableSize;
-	char **		newFileTable;
-	char		dirName[PATH_LEN];
-
-	static int	fileCount;
-	static int	fileTableSize;
-	static char **	fileTable;
-
-	/*
-	 * Clear the return values until we know their final values.
-	 */
-	fileCount = 0;
-	*retFileTable = NULL;
-
-	/*
-	 * Scan the file name pattern for any wildcard characters.
-	 */
-	cp1 = strchr(fileNamePattern, '*');
-	cp2 = strchr(fileNamePattern, '?');
-	cp3 = strchr(fileNamePattern, '[');
-
-	/*
-	 * If there are no wildcard characters then return zero to
-	 * indicate that there was actually no wildcard pattern.
-	 */
-	if ((cp1 == NULL) && (cp2 == NULL) && (cp3 == NULL))
-		return 0;
-
-	/*
-	 * There are wildcards in the specified filename.
-	 * Get the last component of the file name.
-	 */
-	last = strrchr(fileNamePattern, '/');
-
-	if (last)
-		last++;
-	else
-		last = fileNamePattern;
-
-	/*
-	 * If any wildcards were found before the last filename component
-	 * then return an error.
-	 */
-	if ((cp1 && (cp1 < last)) || (cp2 && (cp2 < last)) ||
-		(cp3 && (cp3 < last)))
-	{
-		fprintf(stderr,
-		"Wildcards only implemented for last file name component\n");
-
-		return -1;
-	}
-
-	/*
-	 * Assume at first that we are scanning the current directory.
-	 */
-	dirName[0] = '.';
-	dirName[1] = '\0';
-
-	/*
-	 * If there was a directory given as part of the file name then
-	 * copy it and null terminate it.
-	 */
-	if (last != fileNamePattern)
-	{
-		memcpy(dirName, fileNamePattern, last - fileNamePattern);
-		dirName[last - fileNamePattern - 1] = '\0';
-
-		if (dirName[0] == '\0')
-		{
-			dirName[0] = '/';
-			dirName[1] = '\0';
-		}
-	}
-
-	/*
-	 * Open the directory containing the files to be checked.
-	 */
-	dirp = opendir(dirName);
-
-	if (dirp == NULL)
-	{
-		perror(dirName);
-
-		return -1;
-	}
-
-	/*
-	 * Prepare the directory name for use in making full path names.
-	 */
-	dirLen = strlen(dirName);
-
-	if (last == fileNamePattern)
-	{
-		dirLen = 0;
-		dirName[0] = '\0';
-	}
-	else if (dirName[dirLen - 1] != '/')
-	{
-		dirName[dirLen++] = '/';
-		dirName[dirLen] = '\0';
-	}
-
-	/*
-	 * Find all of the files in the directory and check them against
-	 * the wildcard pattern.
-	 */
-	while ((dp = readdir(dirp)) != NULL)
-	{
-		/*
-		 * Skip the current and parent directories.
-		 */
-		if ((strcmp(dp->d_name, ".") == 0) ||
-			(strcmp(dp->d_name, "..") == 0))
-		{
-			continue;
-		}
-
-		/*
-		 * If the file name doesn't match the pattern then skip it.
-		 */
-		if (!match(dp->d_name, last))
-			continue;
-
-		/*
-		 * This file name is selected.
-		 * See if we need to reallocate the file name table.
-		 */
-		if (fileCount >= fileTableSize)
-		{
-			/*
-			 * Increment the file table size and reallocate it.
-			 */
-			newFileTableSize = fileTableSize + EXPAND_ALLOC;
-
-			newFileTable = (char **) realloc((char *) fileTable,
-				(newFileTableSize * sizeof(char *)));
-
-			if (newFileTable == NULL)
-			{
-				fprintf(stderr, "Cannot allocate file list\n");
-				closedir(dirp);
-
-				return -1;
-			}
-
-			fileTable = newFileTable;
-			fileTableSize = newFileTableSize;
-		}
-
-		/*
-		 * Allocate space for storing the file name in a chunk.
-		 */
-		str = getChunk(dirLen + strlen(dp->d_name) + 1);
-
-		if (str == NULL)
-		{
-			fprintf(stderr, "No memory for file name\n");
-			closedir(dirp);
-
-			return -1;
-		}
-
-		/*
-		 * Save the file name in the chunk.
-		 */
-		if (dirLen)
-			memcpy(str, dirName, dirLen);
-
-		strcpy(str + dirLen, dp->d_name);
-
-		/*
-		 * Save the allocated file name into the file table.
-		 */
-		fileTable[fileCount++] = str;
-	}
-
-	/*
-	 * Close the directory and check for any matches.
-	 */
-	closedir(dirp);
-
-	if (fileCount == 0)
-	{
-		fprintf(stderr, "No matches\n");
-
-		return -1;
-	}
-
-	/*
-	 * Sort the list of file names.
-	 */
-	qsort((void *) fileTable, fileCount, sizeof(char *), nameSort);
-
-	/*
-	 * Return the file list and count.
-	 */
-	*retFileTable = (const char **) fileTable;
-
-	return fileCount;
-}
-
-
-/*
- * Sort routine for list of fileNames.
- */
-int
-nameSort(const void * p1, const void * p2)
-{
-	const char **	s1;
-	const char **	s2;
-
-	s1 = (const char **) p1;
-	s2 = (const char **) p2;
-
-	return strcmp(*s1, *s2);
-}
-
-
-
-/*
- * Routine to see if a text string is matched by a wildcard pattern.
- * Returns TRUE if the text is matched, or FALSE if it is not matched
- * or if the pattern is invalid.
- *  *		matches zero or more characters
- *  ?		matches a single character
- *  [abc]	matches 'a', 'b' or 'c'
- *  \c		quotes character c
- *  Adapted from code written by Ingo Wilken.
- */
-BOOL
-match(const char * text, const char * pattern)
-{
-	const char *	retryPat;
-	const char *	retryText;
-	int		ch;
-	BOOL		found;
-
-	retryPat = NULL;
-	retryText = NULL;
-
-	while (*text || *pattern)
-	{
-		ch = *pattern++;
-
-		switch (ch)
-		{
-			case '*':  
-				retryPat = pattern;
-				retryText = text;
-				break;
-
-			case '[':  
-				found = FALSE;
-
-				while ((ch = *pattern++) != ']')
-				{
-					if (ch == '\\')
-						ch = *pattern++;
-
-					if (ch == '\0')
-						return FALSE;
-
-					if (*text == ch)
-						found = TRUE;
-				}
-
-				if (!found)
-				{
-					pattern = retryPat;
-					text = ++retryText;
-				}
-
-				/* fall into next case */
-
-			case '?':  
-				if (*text++ == '\0')
-					return FALSE;
-
-				break;
-
-			case '\\':  
-				ch = *pattern++;
-
-				if (ch == '\0')
-					return FALSE;
-
-				/* fall into next case */
-
-			default:        
-				if (*text == ch)
-				{
-					if (*text)
-						text++;
-					break;
-				}
-
-				if (*text)
-				{
-					pattern = retryPat;
-					text = ++retryText;
-					break;
-				}
-
-				return FALSE;
-		}
-
-		if (pattern == NULL)
-			return FALSE;
-	}
-
-	return TRUE;
-}
-
-
-/*
- * Take a command string and break it up into an argc, argv list while
- * handling quoting and wildcards.  The returned argument list and
- * strings are in static memory, and so are overwritten on each call.
- * The argument list is ended with a NULL pointer for convenience.
- * Returns TRUE if successful, or FALSE on an error with a message
- * already output.
- */
-BOOL
-makeArgs(const char * cmd, int * retArgc, const char *** retArgv)
-{
-	const char *		argument;
-	char *			cp;
-	char *			cpOut;
-	char *			newStrings;
-	const char **		fileTable;
-	const char **		newArgTable;
-	int			newArgTableSize;
-	int			fileCount;
-	int			len;
-	int			ch;
-	int			quote;
-	BOOL			quotedWildCards;
-	BOOL			unquotedWildCards;
-
-	static int		stringsLength;
-	static char *		strings;
-	static int		argCount;
-	static int		argTableSize;
-	static const char **	argTable;
-
-	/*
-	 * Clear the returned values until we know them.
-	 */
-	argCount = 0;
-	*retArgc = 0;
-	*retArgv = NULL;
-
-	/*
-	 * Copy the command string into a buffer that we can modify,
-	 * reallocating it if necessary.
-	 */
-	len = strlen(cmd) + 1;
-
-	if (len > stringsLength)
-	{
-		newStrings = realloc(strings, len);
-
-		if (newStrings == NULL)
-		{
-			fprintf(stderr, "Cannot allocate string\n");
-
-			return FALSE;
-		}
-
-		strings = newStrings;
-		stringsLength = len;
-	}
-
-	memcpy(strings, cmd, len);
-	cp = strings;
-
-	/*
-	 * Keep parsing the command string as long as there are any
-	 * arguments left.
-	 */
-	while (*cp)
-	{
-		/*
-		 * Save the beginning of this argument.
-		 */
-		argument = cp;
-		cpOut = cp;
-
-		/*
-		 * Reset quoting and wildcarding for this argument.
-		 */
-		quote = '\0';
-		quotedWildCards = FALSE;
-		unquotedWildCards = FALSE;
-
-		/*
-		 * Loop over the string collecting the next argument while
-		 * looking for quoted strings or quoted characters, and
-		 * remembering whether there are any wildcard characters
-		 * in the argument.
-		 */
-		while (*cp)
-		{
-			ch = *cp++;
-
-			/*
-			 * If we are not in a quote and we see a blank then
-			 * this argument is done.
-			 */
-			if (isBlank(ch) && (quote == '\0'))
-				break;
-
-			/*
-			 * If we see a backslash then accept the next
-			 * character no matter what it is.
-			 */
-			if (ch == '\\')
-			{
-				ch = *cp++;
-
-				/*
-				 * Make sure there is a next character.
-				 */
-				if (ch == '\0')
-				{
-					fprintf(stderr,
-						"Bad quoted character\n");
-
-					return FALSE;
-				}
-
-				/*
-				 * Remember whether the quoted character
-				 * is a wildcard.
-				 */
-				if (isWildCard(ch))
-					quotedWildCards = TRUE;
-
-				*cpOut++ = ch;
-
-				continue;
-			}
-
-			/*
-			 * If we see one of the wildcard characters then
-			 * remember whether it was seen inside or outside
-			 * of quotes.
-			 */
-			if (isWildCard(ch))
-			{
-				if (quote)
-					quotedWildCards = TRUE;
-				else
-					unquotedWildCards = TRUE;
-			}
-
-			/*
-			 * If we were in a quote and we saw the same quote
-			 * character again then the quote is done.
-			 */
-			if (ch == quote)
-			{
-				quote = '\0';
-
-				continue;
-			}
-
-			/*
-			 * If we weren't in a quote and we see either type
-			 * of quote character, then remember that we are
-			 * now inside of a quote.
-			 */
-			if ((quote == '\0') && ((ch == '\'') || (ch == '"')))
-			{
-				quote = ch;
-
-				continue;
-			}
-
-			/*
-			 * Store the character.
-			 */
-			*cpOut++ = ch;
-		}
-
-		/*
-		 * Make sure that quoting is terminated properly.
-		 */
-		if (quote)
-		{
-			fprintf(stderr, "Unmatched quote character\n");
-
-			return FALSE;
-		}
-
-		/*
-		 * Null terminate the argument if it had shrunk, and then
-		 * skip over all blanks to the next argument, nulling them
-		 * out too.
-		 */
-		if (cp != cpOut)
-			*cpOut = '\0';
-
-		while (isBlank(*cp))
- 			*cp++ = '\0';
-
-		/*
-		 * If both quoted and unquoted wildcards were used then
-		 * complain since we don't handle them properly.
-		 */
-		if (quotedWildCards && unquotedWildCards)
-		{
-			fprintf(stderr,
-				"Cannot use quoted and unquoted wildcards\n");
-
-			return FALSE;
-		}
-
-		/*
-		 * Expand the argument into the matching filenames or accept
-		 * it as is depending on whether there were any unquoted
-		 * wildcard characters in it.
-		 */
-		if (unquotedWildCards)
-		{
-			/*
-			 * Expand the argument into the matching filenames.
-			 */
-			fileCount = expandWildCards(argument, &fileTable);
-
-			/*
-			 * Return an error if the wildcards failed to match.
-			 */
-			if (fileCount < 0)
-				return FALSE;
-
-			if (fileCount == 0)
-			{
-				fprintf(stderr, "Wildcard expansion error\n");
-
-				return FALSE;
-			}
-		}
-		else
-		{
-			/*
-			 * Set up to only store the argument itself.
-			 */
-			fileTable = &argument;
-			fileCount = 1;
-		}
-
-		/*
-		 * Now reallocate the argument table to hold the file name.
-		 */
-		if (argCount + fileCount >= argTableSize)
-		{
-			newArgTableSize = argCount + fileCount + 1;
-
-			newArgTable = (const char **) realloc(argTable,
-				(sizeof(const char *) * newArgTableSize));
-
-			if (newArgTable == NULL)
-			{
-				fprintf(stderr, "No memory for arg list\n");
-
-				return FALSE;
-			}
-
-			argTable = newArgTable;
-			argTableSize = newArgTableSize;
-		}
-
-		/*
-		 * Copy the new arguments to the end of the old ones.
-		 */
-		memcpy((void *) &argTable[argCount], (const void *) fileTable,
-			(sizeof(const char **) * fileCount));
-
-		/*
-		 * Add to the argument count.
-		 */
-		argCount += fileCount;
-	}
-
-	/*
-	 * Null terminate the argument list and return it.
-	 */
-	argTable[argCount] = NULL;
-
-	*retArgc = argCount;
-	*retArgv = argTable;
-
- 	return TRUE;
-}
-
-
-/*
  * Make a NULL-terminated string out of an argc, argv pair.
  * Returns TRUE if successful, or FALSE if the string is too long,
  * with an error message given.  This does not handle spaces within
@@ -1114,15 +468,14 @@
 
 
 /*
- * Read all of the supplied buffer from a file.
- * This does multiple reads as necessary.
- * Returns the amount read, or -1 on an error.
- * A short read is returned on an end of file.
+ * Walk down all the directories under the specified 
+ * location, and do something (something specified
+ * by the fileAction and dirAction function pointers).
  */
 int
-recursive( const char *fileName, BOOL followLinks, const char* pattern, 
-	int (*fileAction)(const char* fileName, const struct stat* statbuf), 
-	int (*dirAction)(const char* fileName, const struct stat* statbuf))
+recursiveAction( const char *fileName, BOOL followLinks,
+	int (*fileAction)(const char* fileName), 
+	int (*dirAction)(const char* fileName))
 {
     int             status;
     struct stat     statbuf;
@@ -1135,45 +488,44 @@
 
     if (status < 0) {
 	perror(fileName);
-	return( -1);
+	return( FALSE);
     }
 
-    if (S_ISREG(statbuf.st_mode)) {
-	if (match(fileName, pattern)) {
-	    if (fileAction==NULL)
-		fprintf( stdout, "%s\n", fileName);
-	    else
-		return(fileAction(fileName, &statbuf));
+    if (S_ISDIR(statbuf.st_mode)) {
+	DIR *dir;
+	dir = opendir(fileName);
+	if (!dir) {
+	    perror(fileName);
+	    return(FALSE);
 	}
-    }
-    else if (S_ISDIR(statbuf.st_mode)) {
-	if (dirAction==NULL) {
-	    DIR *dir;
-	    if (! match(fileName, pattern))
-		return 1;
-	    dir = opendir(fileName);
-	    if (!dir) {
-		perror(fileName);
-		return( -1);
-	    }
-	    while ((next = readdir (dir)) != NULL) {
-		    status = recursive(fileName, followLinks, pattern, fileAction, dirAction);
-		    if (status < 0) {
-			closedir(dir);
-			return(status);
-		    }
-	    }
-	    status = closedir (dir);
-	    if (status < 0) {
-		perror(fileName);
-		return( -1);
-	    }
+	while ((next = readdir (dir)) != NULL) {
+		char nextFile[NAME_MAX];
+		if ( (strcmp(next->d_name, "..") == 0) || (strcmp(next->d_name, ".") == 0) ) {
+		    continue;
+		}
+		sprintf(nextFile, "%s/%s", fileName, next->d_name);
+		status = recursiveAction(nextFile, followLinks, fileAction, dirAction);
+		if (status < 0) {
+		    closedir(dir);
+		    return(FALSE);
+		}
 	}
+	status = closedir (dir);
+	if (status < 0) {
+	    perror(fileName);
+	    return( FALSE);
+	}
+	if (dirAction==NULL)
+	    return(TRUE);
 	else
-	    return(dirAction(fileName, &statbuf));
+	    return(dirAction(fileName));
     }
-    return( 1);
-
+    else {
+	if (fileAction==NULL)
+	    return(TRUE);
+	else
+	    return(fileAction(fileName));
+    }
 }
 
 
diff --git a/utility.h b/utility.h
deleted file mode 100644
index 7b275ba..0000000
--- a/utility.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Utility routines.
- *
- * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Based in part on code from sash, Copyright (c) 1999 by David I. Bell 
- * Permission has been granted to redistribute this code under the GPL.
- *
- */
-
-#include "internal.h"
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-//#include <sys/types.h>
-//#include <sys/stat.h>
-#include <dirent.h>
-#include <time.h>
-#include <utime.h>
-
-/*
- * A chunk of data.
- * Chunks contain data which is allocated as needed, but which is
- * not freed until all of the data needs freeing, such as at
- * the beginning of the next command.
- */
-typedef struct chunk CHUNK;
-#define CHUNK_INIT_SIZE 4
-
-struct chunk {
-    CHUNK *next;
-    char data[CHUNK_INIT_SIZE];	/* actually of varying length */
-};
-
-const char *modeString(int mode);
-const char *timeString(time_t timeVal);
-BOOL isDirectory(const char *name);
-BOOL isDevice(const char *name);
-BOOL copyFile(const char *srcName, const char *destName, BOOL setModes);
-const char *buildName(const char *dirName, const char *fileName);
-BOOL match(const char *text, const char *pattern);
-BOOL makeArgs(const char *cmd, int *retArgc, const char ***retArgv);
-BOOL makeString(int argc, const char **argv, char *buf, int bufLen);
-char *getChunk(int size);
-char *chunkstrdup(const char *str);
-void freeChunks(void);
-int fullWrite(int fd, const char *buf, int len);
-int fullRead(int fd, char *buf, int len);
-int
-recursive(const char *fileName, BOOL followLinks, const char *pattern,
-	  int (*fileAction) (const char *fileName,
-			     const struct stat * statbuf),
-	  int (*dirAction) (const char *fileName,
-			    const struct stat * statbuf));
-
-int nameSort(const void *p1, const void *p2);
-int expandWildCards(const char *fileNamePattern,
-		    const char ***retFileTable);