Major coreutils update.
diff --git a/libbb/Makefile.in b/libbb/Makefile.in
index 6d2475b..c7916f1 100644
--- a/libbb/Makefile.in
+++ b/libbb/Makefile.in
@@ -42,26 +42,59 @@
 	restricted_shell.c run_parts.c run_shell.c safe_read.c safe_strncpy.c \
 	setup_environment.c simplify_path.c syscalls.c syslog_msg_with_name.c \
 	time_string.c trim.c u_signal_names.c vdprintf.c verror_msg.c \
-	vherror_msg.c vperror_msg.c wfopen.c xconnect.c xgetcwd.c xfuncs.c \
-	xgethostbyname.c xgethostbyname2.c xreadlink.c xregcomp.c xgetlarg.c 
-	
+	vherror_msg.c vperror_msg.c wfopen.c xconnect.c xgetcwd.c \
+	xgethostbyname.c xgethostbyname2.c xreadlink.c xregcomp.c xgetlarg.c \
+	\
+	fclose_nonstdin.c fflush_stdout_and_exit.c getopt_ulflags.c \
+	default_error_retval.c wfopen_input.c speed_table.c \
+	perror_nomsg_and_die.c perror_nomsg.c skip_whitespace.c \
+	warn_ignoring_args.c
 
 LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC))
 
-LIBBB_MSRC:=$(LIBBB_DIR)messages.c
-LIBBB_MOBJ:=full_version.o name_too_long.o omitting_directory.o not_a_directory.o \
-	memory_exhausted.o invalid_date.o invalid_option.o io_error.o dash_dash_help.o \
-	write_error.o too_few_args.o name_longer_than_foo.o unknown.o can_not_create_raw_socket.o \
-	shadow_file.o passwd_file.o group_file.o gshadow_file.o nologin_file.o securetty_file.o \
-	motd_file.o
-LIBBB_MOBJS=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ))
+LIBBB_MSRC0:=$(LIBBB_DIR)messages.c
+LIBBB_MOBJ0:=full_version.o \
+	memory_exhausted.o invalid_date.o io_error.o \
+	write_error.o name_longer_than_foo.o unknown.o \
+	can_not_create_raw_socket.o perm_denied_are_you_root.o \
+	shadow_file.o passwd_file.o group_file.o gshadow_file.o nologin_file.o \
+	securetty_file.o motd_file.o \
+	msg_standard_input.o msg_standard_output.o
+
+LIBBB_MSRC1:=$(LIBBB_DIR)xfuncs.c
+LIBBB_MOBJ1:=xmalloc.o xrealloc.o xcalloc.o xstrdup.o xstrndup.o \
+	xfopen.o xopen.o xread.o xread_all.o xread_char.o \
+	xferror.o xferror_stdout.o xfflush_stdout.o strlen.o
+
+LIBBB_MSRC2:=$(LIBBB_DIR)printf.c
+LIBBB_MOBJ2:=vfprintf.o vprintf.o fprintf.o printf.o
+
+LIBBB_MSRC3:=$(LIBBB_DIR)xgetularg.c
+LIBBB_MOBJ3:=xgetularg_bnd_sfx.o xgetlarg_bnd_sfx.o getlarg10_sfx.o \
+	xgetularg_bnd.o xgetularg10_bnd.o xgetularg10.o
+
+LIBBB_MOBJS0=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ0))
+LIBBB_MOBJS1=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ1))
+LIBBB_MOBJS2=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ2))
+LIBBB_MOBJS3=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ3))
 
 libraries-y+=$(LIBBB_DIR)$(LIBBB_AR)
 
-$(LIBBB_DIR)$(LIBBB_AR): $(LIBBB_OBJS) $(LIBBB_MOBJS) 
-	$(AR) -ro $@ $(LIBBB_OBJS) $(LIBBB_MOBJS)
+$(LIBBB_DIR)$(LIBBB_AR): $(LIBBB_OBJS) $(LIBBB_MOBJS0) $(LIBBB_MOBJS1) \
+	$(LIBBB_MOBJS2) $(LIBBB_MOBJS3)
+	$(AR) -ro $@ $(LIBBB_OBJS) $(LIBBB_MOBJS0) $(LIBBB_MOBJS1) \
+		$(LIBBB_MOBJS2) $(LIBBB_MOBJS3) 
 
-$(LIBBB_MOBJS): $(LIBBB_MSRC)
+$(LIBBB_MOBJS0): $(LIBBB_MSRC0)
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DL_$(notdir $*) -c $< -o $@
+
+$(LIBBB_MOBJS1): $(LIBBB_MSRC1)
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DL_$(notdir $*) -c $< -o $@
+
+$(LIBBB_MOBJS2): $(LIBBB_MSRC2)
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DL_$(notdir $*) -c $< -o $@
+
+$(LIBBB_MOBJS3): $(LIBBB_MSRC3)
 	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DL_$(notdir $*) -c $< -o $@
 
 $(LIBBB_DIR)loop.o: $(LIBBB_DIR)loop.h
diff --git a/libbb/ask_confirmation.c b/libbb/ask_confirmation.c
index d4d943a..a99a4e7 100644
--- a/libbb/ask_confirmation.c
+++ b/libbb/ask_confirmation.c
@@ -1,49 +1,49 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Utility routines.
+ * bb_ask_confirmation implementation for busybox
  *
- * Copyright (C) many different people.  If you wrote this, please
- * acknowledge your work.
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 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
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Read a line from stdin.  If the first non-whitespace char is 'y' or 'Y',
+ * return 1.  Otherwise return 0.
  */
 
 #include <stdio.h>
+#include <ctype.h>
 #include "libbb.h"
 
-
-int ask_confirmation()
+int bb_ask_confirmation(void)
 {
-	int c = '\0';
-	int ret = 0;
+	int retval = 0;
+	int first = 1;
+	int c;
 
-	while (c != '\n') {
-		c = getchar();
-		if ( c != '\n' ) {
-			ret = ((c=='y')||(c=='Y')) ? 1 : 0;
+	while (((c = getchar()) != EOF) && (c != '\n')) {
+		/* Make sure we get the actual function call for isspace,
+		 * as speed is not critical here. */
+		if (first && !(isspace)(c)) {
+			--first;
+			if ((c == 'y') || (c == 'Y')) {
+				++retval;
+			}
 		}
 	}
-	return ret;
-}
 
-/* END CODE */
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
+	return retval;
+}
diff --git a/libbb/bb_asprintf.c b/libbb/bb_asprintf.c
index 9a71be7..7075b46 100644
--- a/libbb/bb_asprintf.c
+++ b/libbb/bb_asprintf.c
@@ -5,17 +5,18 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
-
-
 #include "libbb.h"
 
-
-void bb_asprintf(char **string_ptr, const char *format, ...)
+void bb_xasprintf(char **string_ptr, const char *format, ...)
 {
-       va_list p;
+	va_list p;
+	int r;
+	
+	va_start(p, format);
+	r = vasprintf(string_ptr, format, p);
+	va_end(p);
 
-       va_start(p, format);
-       if(vasprintf(string_ptr, format, p)<0)
-		error_msg_and_die(memory_exhausted);
-       va_end(p);
+	if (r < 0) {
+		bb_perror_msg_and_die("bb_xasprintf");
+	}
 }
diff --git a/libbb/change_identity.c b/libbb/change_identity.c
index 819b216..c2b73ee 100644
--- a/libbb/change_identity.c
+++ b/libbb/change_identity.c
@@ -43,12 +43,12 @@
 void change_identity ( const struct passwd *pw )
 {
 	if ( initgroups ( pw-> pw_name, pw-> pw_gid ) == -1 )
-		perror_msg_and_die ( "cannot set groups" );
+		bb_perror_msg_and_die ( "cannot set groups" );
 	endgrent ( );
 
 	if ( setgid ( pw-> pw_gid ))
-		perror_msg_and_die ( "cannot set group id" );
+		bb_perror_msg_and_die ( "cannot set group id" );
 	if ( setuid ( pw->pw_uid ))
-		perror_msg_and_die ( "cannot set user id" );
+		bb_perror_msg_and_die ( "cannot set user id" );
 }
 
diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c
index b158ae4..993b462 100644
--- a/libbb/compare_string_array.c
+++ b/libbb/compare_string_array.c
@@ -27,4 +27,5 @@
 		}
 	}
 	return(i);
-}
\ No newline at end of file
+}
+
diff --git a/libbb/concat_path_file.c b/libbb/concat_path_file.c
index 0146606..b972ba6 100644
--- a/libbb/concat_path_file.c
+++ b/libbb/concat_path_file.c
@@ -38,7 +38,7 @@
 	lc = last_char_is(path, '/');
 	while (*filename == '/')
 		filename++;
-       bb_asprintf(&outbuf, "%s%s%s", path, (lc==NULL)? "/" : "", filename);
+	bb_xasprintf(&outbuf, "%s%s%s", path, (lc==NULL)? "/" : "", filename);
 
 	return outbuf;
 }
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index 23a2d75..81c5474 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -43,19 +43,19 @@
 			lstat(source, &source_stat) < 0) ||
 			((flags & FILEUTILS_DEREFERENCE) &&
 			 stat(source, &source_stat) < 0)) {
-		perror_msg("%s", source);
+		bb_perror_msg("%s", source);
 		return -1;
 	}
 
 	if (lstat(dest, &dest_stat) < 0) {
 		if (errno != ENOENT) {
-			perror_msg("unable to stat `%s'", dest);
+			bb_perror_msg("unable to stat `%s'", dest);
 			return -1;
 		}
 	} else {
 		if (source_stat.st_dev == dest_stat.st_dev &&
 			source_stat.st_ino == dest_stat.st_ino) {
-		error_msg("`%s' and `%s' are the same file", source, dest);
+		bb_error_msg("`%s' and `%s' are the same file", source, dest);
 		return -1;
 	}
 		dest_exists = 1;
@@ -67,14 +67,14 @@
 		mode_t saved_umask = 0;
 
 		if (!(flags & FILEUTILS_RECUR)) {
-			error_msg("%s: omitting directory", source);
+			bb_error_msg("%s: omitting directory", source);
 			return -1;
 		}
 
 		/* Create DEST.  */
 		if (dest_exists) {
 			if (!S_ISDIR(dest_stat.st_mode)) {
-				error_msg("`%s' is not a directory", dest);
+				bb_error_msg("`%s' is not a directory", dest);
 				return -1;
 			}
 		} else {
@@ -88,7 +88,7 @@
 
 			if (mkdir(dest, mode) < 0) {
 				umask(saved_umask);
-				perror_msg("cannot create directory `%s'", dest);
+				bb_perror_msg("cannot create directory `%s'", dest);
 				return -1;
 			}
 
@@ -97,7 +97,7 @@
 
 		/* Recursively copy files in SOURCE.  */
 		if ((dp = opendir(source)) == NULL) {
-			perror_msg("unable to open directory `%s'", source);
+			bb_perror_msg("unable to open directory `%s'", source);
 			status = -1;
 			goto end;
 		}
@@ -121,7 +121,7 @@
 
 		if (!dest_exists &&
 				chmod(dest, source_stat.st_mode & ~saved_umask) < 0) {
-			perror_msg("unable to change permissions of `%s'", dest);
+			bb_perror_msg("unable to change permissions of `%s'", dest);
 			status = -1;
 		}
 	} else if (S_ISREG(source_stat.st_mode)) {
@@ -132,7 +132,7 @@
 		if (!(flags & FILEUTILS_DEREFERENCE) &&
 				is_in_ino_dev_hashtable(&source_stat, &link_name)) {
 			if (link(link_name, dest) < 0) {
-				perror_msg("unable to link `%s'", dest);
+				bb_perror_msg("unable to link `%s'", dest);
 				return -1;
 			}
 
@@ -140,14 +140,14 @@
 		}
 #endif
 
-		if ((sfp = wfopen(source, "r")) == NULL) {
+		if ((sfp = bb_wfopen(source, "r")) == NULL) {
 			return -1;
 		}
 
 		if (dest_exists) {
 			if (flags & FILEUTILS_INTERACTIVE) {
-				fprintf(stderr, "%s: overwrite `%s'? ", applet_name, dest);
-				if (!ask_confirmation()) {
+				fprintf(stderr, "%s: overwrite `%s'? ", bb_applet_name, dest);
+				if (!bb_ask_confirmation()) {
 					fclose (sfp);
 					return 0;
 				}
@@ -155,13 +155,13 @@
 
 			if ((dfp = fopen(dest, "w")) == NULL) {
 				if (!(flags & FILEUTILS_FORCE)) {
-					perror_msg("unable to open `%s'", dest);
+					bb_perror_msg("unable to open `%s'", dest);
 					fclose (sfp);
 					return -1;
 				}
 
 				if (unlink(dest) < 0) {
-					perror_msg("unable to remove `%s'", dest);
+					bb_perror_msg("unable to remove `%s'", dest);
 					fclose (sfp);
 					return -1;
 				}
@@ -177,22 +177,22 @@
 					(dfp = fdopen(fd, "w")) == NULL) {
 				if (fd >= 0)
 					close(fd);
-				perror_msg("unable to open `%s'", dest);
+				bb_perror_msg("unable to open `%s'", dest);
 				fclose (sfp);
 				return -1;
 			}
 		}
 
-		if (copyfd(fileno(sfp), fileno(dfp), 0) == -1)
+		if (bb_copyfd(fileno(sfp), fileno(dfp), 0) == -1)
 			status = -1;
 
 		if (fclose(dfp) < 0) {
-			perror_msg("unable to close `%s'", dest);
+			bb_perror_msg("unable to close `%s'", dest);
 			status = -1;
 		}
 
 		if (fclose(sfp) < 0) {
-			perror_msg("unable to close `%s'", source);
+			bb_perror_msg("unable to close `%s'", source);
 			status = -1;
 		}
 			}
@@ -202,23 +202,23 @@
 
 		if (dest_exists &&
 		       ((flags & FILEUTILS_FORCE) == 0 || unlink(dest) < 0)) {
-				perror_msg("unable to remove `%s'", dest);
+				bb_perror_msg("unable to remove `%s'", dest);
 				return -1;
 
 			}
 	} else {
-		error_msg("internal error: unrecognized file type");
+		bb_error_msg("internal error: unrecognized file type");
 		return -1;
 		}
 	if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) ||
 	    S_ISSOCK(source_stat.st_mode)) {
 		if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) {
-			perror_msg("unable to create `%s'", dest);
+			bb_perror_msg("unable to create `%s'", dest);
 			return -1;
 		}
 	} else if (S_ISFIFO(source_stat.st_mode)) {
 		if (mkfifo(dest, source_stat.st_mode) < 0) {
-			perror_msg("cannot create fifo `%s'", dest);
+			bb_perror_msg("cannot create fifo `%s'", dest);
 			return -1;
 		}
 	} else if (S_ISLNK(source_stat.st_mode)) {
@@ -226,7 +226,7 @@
 
 		lpath = xreadlink(source);
 		if (symlink(lpath, dest) < 0) {
-			perror_msg("cannot create symlink `%s'", dest);
+			bb_perror_msg("cannot create symlink `%s'", dest);
 			return -1;
 		}
 		free(lpath);
@@ -234,7 +234,7 @@
 #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
 		if (flags & FILEUTILS_PRESERVE_STATUS)
 			if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0)
-				perror_msg("unable to preserve ownership of `%s'", dest);
+				bb_perror_msg("unable to preserve ownership of `%s'", dest);
 #endif
 
 #ifdef CONFIG_FEATURE_PRESERVE_HARDLINKS
@@ -256,13 +256,13 @@
 		times.actime = source_stat.st_atime;
 		times.modtime = source_stat.st_mtime;
 		if (utime(dest, &times) < 0)
-			perror_msg("unable to preserve times of `%s'", dest);
+			bb_perror_msg("unable to preserve times of `%s'", dest);
 		if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) {
 			source_stat.st_mode &= ~(S_ISUID | S_ISGID);
-			perror_msg("unable to preserve ownership of `%s'", dest);
+			bb_perror_msg("unable to preserve ownership of `%s'", dest);
 		}
 		if (chmod(dest, source_stat.st_mode) < 0)
-			perror_msg("unable to preserve permissions of `%s'", dest);
+			bb_perror_msg("unable to preserve permissions of `%s'", dest);
 	}
 
 	return status;
diff --git a/libbb/copy_file_chunk.c b/libbb/copy_file_chunk.c
deleted file mode 100644
index 63d2ab1..0000000
--- a/libbb/copy_file_chunk.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Utility routines.
- *
- * Copyright (C) many different people.  If you wrote this, please
- * acknowledge your work.
- *
- * 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 <sys/stat.h>
-#include "libbb.h"
-
-/* Copy CHUNKSIZE bytes (or until EOF if CHUNKSIZE equals -1) from SRC_FILE
- * to DST_FILE.  */
-extern int copy_file_chunk(FILE *src_file, FILE *dst_file, unsigned long long chunksize)
-{
-	size_t nread, nwritten, size;
-	char buffer[BUFSIZ];
-
-	while (chunksize != 0) {
-		if (chunksize > BUFSIZ)
-			size = BUFSIZ;
-		else
-			size = chunksize;
-
-		nread = fread (buffer, 1, size, src_file);
-
-		if (nread != size && ferror (src_file)) {
-			perror_msg ("read");
-			return -1;
-		} else if (nread == 0) {
-			if (chunksize != -1) {
-				error_msg ("Unable to read all data");
-				return -1;
-			}
-
-			return 0;
-		}
-
-		nwritten = fwrite (buffer, 1, nread, dst_file);
-
-		if (nwritten != nread) {
-			if (ferror (dst_file))
-				perror_msg ("write");
-			else
-				error_msg ("Unable to write all data");
-			return -1;
-		}
-
-		if (chunksize != -1)
-			chunksize -= nwritten;
-	}
-
-	return 0;
-}
diff --git a/libbb/copyfd.c b/libbb/copyfd.c
index 4df1fd0..41b78c7 100644
--- a/libbb/copyfd.c
+++ b/libbb/copyfd.c
@@ -22,65 +22,51 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include "libbb.h"
+#include "busybox.h"
 
-/* If chunksize is 0 copy untill EOF */
-extern int copyfd(int fd1, int fd2, const off_t chunksize)
+#if BUFSIZ < 4096
+#undef BUFSIZ
+#define BUFSIZ 4096
+#endif
+
+/* If chunksize is 0 copy until EOF */
+extern int bb_copyfd(int fd1, int fd2, const off_t chunksize)
 {
-	size_t nread;
-	size_t nwritten;
+	ssize_t nread;
 	size_t size;
-	size_t remaining;
-	char buffer[BUFSIZ];
+	off_t remaining;
+	RESERVE_CONFIG_BUFFER(buffer,BUFSIZ);
 
+	remaining = size = BUFSIZ;
 	if (chunksize) {
 		remaining = chunksize;
-	} else {
-		remaining = -1;
 	}
 
 	do {
-		if ((chunksize > BUFSIZ) || (chunksize == 0)) {
-			size = BUFSIZ;
-		} else {
-			size = chunksize;
+		if (size > remaining) {
+			size = remaining;
 		}
 
-		nread = safe_read(fd1, buffer, size);
-
-		if (nread == -1) {
-			perror_msg("read failure");
-			return(-1);
-		}
-		else if (nread == 0) {
-			if (chunksize) {
-				error_msg("Unable to read all data");
-				return(-1);
-			} else {
-				return(0);
+		if ((nread = safe_read(fd1, buffer, size)) > 0) {
+			if (bb_full_write(fd2, buffer, nread) < 0) {
+				bb_perror_msg(bb_msg_write_error);	/* match Read error below */
+				break;
 			}
+			if (chunksize && ((remaining -= nread) == 0)) {
+				return 0;
+			}
+		} else if (!nread) {
+			if (chunksize) {
+				bb_error_msg("Unable to read all data");
+				break;
+			}
+			return 0;
+		} else {				/* nread < 0 */
+			bb_perror_msg("Read error");	/* match bb_msg_write_error above */
+			break;
 		}
 
-		nwritten = full_write(fd2, buffer, nread);
+	} while (1);
 
-		if (nwritten != nread) {
-			error_msg("Unable to write all data");
-			return(-1);
-		}
-
-		if (chunksize) {
-			remaining -= nwritten;
-		}
-	} while (remaining != 0);
-
-	return 0;
+	return -1;
 }
-
-/* END CODE */
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
diff --git a/libbb/correct_password.c b/libbb/correct_password.c
index 758b89e..3962536 100644
--- a/libbb/correct_password.c
+++ b/libbb/correct_password.c
@@ -55,7 +55,7 @@
 		struct spwd *sp = getspnam ( pw-> pw_name );
 		
 		if ( !sp )
-			error_msg_and_die ( "no valid shadow password" );
+			bb_error_msg_and_die ( "no valid shadow password" );
 		
 		correct = sp-> sp_pwdp;
 	}
@@ -73,6 +73,6 @@
 		return 0;
 	}
 	encrypted = crypt ( unencrypted, correct );
-	memset ( unencrypted, 0, xstrlen ( unencrypted ));
+	memset ( unencrypted, 0, bb_strlen ( unencrypted ));
 	return ( strcmp ( encrypted, correct ) == 0 ) ? 1 : 0;
 }
diff --git a/libbb/create_icmp6_socket.c b/libbb/create_icmp6_socket.c
index 1d0b6b6..5966104 100644
--- a/libbb/create_icmp6_socket.c
+++ b/libbb/create_icmp6_socket.c
@@ -26,9 +26,9 @@
 	if ((sock = socket(AF_INET6, SOCK_RAW,
 			(proto ? proto->p_proto : IPPROTO_ICMPV6))) < 0) {
 		if (errno == EPERM)
-			error_msg_and_die("permission denied. (are you root?)");
+			bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
 		else
-			perror_msg_and_die(can_not_create_raw_socket);
+			bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
 	}
 
 	/* drop root privs if running setuid */
diff --git a/libbb/create_icmp_socket.c b/libbb/create_icmp_socket.c
index d804b39..58d792b 100644
--- a/libbb/create_icmp_socket.c
+++ b/libbb/create_icmp_socket.c
@@ -25,9 +25,9 @@
 	if ((sock = socket(AF_INET, SOCK_RAW,
 			(proto ? proto->p_proto : 1))) < 0) {        /* 1 == ICMP */
 		if (errno == EPERM)
-			error_msg_and_die("permission denied. (are you root?)");
+			bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
 		else
-			perror_msg_and_die(can_not_create_raw_socket);
+			bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
 	}
 
 	/* drop root privs if running setuid */
diff --git a/libbb/default_error_retval.c b/libbb/default_error_retval.c
new file mode 100644
index 0000000..7d2d89b
--- /dev/null
+++ b/libbb/default_error_retval.c
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Seems silly to copyright a global variable.  ;-)  Oh well.
+ *
+ * At least one applet (cmp) returns a value different from the typical
+ * EXIT_FAILURE values (1) when an error occurs.  So, make it configureable
+ * by the applet.  I suppose we could use a wrapper function to set it, but
+ * that too seems silly.
+ */
+
+#include <stdlib.h>
+#include "libbb.h"
+
+int bb_default_error_retval = EXIT_FAILURE;
diff --git a/libbb/dirname.c b/libbb/dirname.c
index df9a49d..8129873 100644
--- a/libbb/dirname.c
+++ b/libbb/dirname.c
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini dirname function.
+ * dirname implementation for busybox (for libc's missing one)
  *
- * Copyright (C) 2001  Matt Kraai.
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,39 +17,53 @@
  * 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
+ *
+ */
+
+/* Note: The previous busybox implementation did not handle NULL path
+ * and also moved a pointer before path, which is not portable in C.
+ * So I replaced it with my uClibc version.
  */
 
 #include <string.h>
 #include "libbb.h"
 
-#if defined __UCLIBC__ || __GNU_LIBRARY___ < 5
+#if __GNU_LIBRARY__ < 5
 
-/* Return a string containing the path name of the parent
- * directory of PATH.  */
-
+extern 
 char *dirname(char *path)
 {
-	char *s;
+	static const char null_or_empty_or_noslash[] = ".";
+	register char *s;
+	register char *last;
+	char *first;
 
-	/* Go to the end of the string.  */
-	s = path + strlen(path) - 1;
+	last = s = path;
 
-	/* Strip off trailing /s (unless it is also the leading /).  */
-	while (path < s && s[0] == '/')
-		s--;
+	if (s != NULL) {
 
-	/* Strip the last component.  */
-	while (path <= s && s[0] != '/')
-		s--;
+	LOOP:
+		while (*s && (*s != '/')) ++s;
+		first = s;
+		while (*s == '/') ++s;
+		if (*s) {
+			last = first;
+			goto LOOP;
+		}
 
-	while (path < s && s[0] == '/')
-		s--;
-
-	if (s < path)
-		return ".";
-
-	s[1] = '\0';
-	return path;
+		if (last == path) {
+			if (*last != '/') {
+				goto DOT;
+			}
+			if ((*++last == '/') && (last[1] == 0)) {
+				++last;
+			}
+		}
+		*last = 0;
+		return path;
+	}
+ DOT:
+	return (char *) null_or_empty_or_noslash;
 }
 
 #endif
diff --git a/libbb/dump.c b/libbb/dump.c
index 1afad83..26dabe5 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -25,94 +25,80 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>		/* for isdigit() */
-#include "dump.h"
 #include "libbb.h"
+#include "dump.h"
 
-enum _vflag vflag = FIRST;
-FS *fshead;				/* head of format strings */
-extern FS *fshead;		/* head of format strings */
-extern int blocksize;
+enum _vflag bb_dump_vflag = FIRST;
+FS *bb_dump_fshead;				/* head of format strings */
 static FU *endfu;
 static char **_argv;
 static off_t savaddress;	/* saved address/offset in stream */
 static off_t eaddress;	/* end address */
 static off_t address;	/* address/offset in stream */
-off_t skip;				/* bytes to skip */
-off_t saveaddress;
-int exitval;			/* final exit value */
-int blocksize;			/* data block size */
-int length = -1;		/* max bytes to read */
+off_t bb_dump_skip;				/* bytes to skip */
+static int exitval;			/* final exit value */
+int bb_dump_blocksize;			/* data block size */
+int bb_dump_length = -1;		/* max bytes to read */
 
+static const char index_str[] = ".#-+ 0123456789";
 
-int size(FS * fs)
+static const char size_conv_str[] =
+"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG";
+
+static const char lcc[] = "diouxX";
+
+int bb_dump_size(FS * fs)
 {
 	register FU *fu;
-	register int bcnt, cursize;
+	register int bcnt, cur_size;
 	register char *fmt;
+	const char *p;
 	int prec;
 
-	/* figure out the data block size needed for each format unit */
-	for (cursize = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
+	/* figure out the data block bb_dump_size needed for each format unit */
+	for (cur_size = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
 		if (fu->bcnt) {
-			cursize += fu->bcnt * fu->reps;
+			cur_size += fu->bcnt * fu->reps;
 			continue;
 		}
 		for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) {
 			if (*fmt != '%')
 				continue;
 			/*
-			 * skip any special chars -- save precision in
+			 * bb_dump_skip any special chars -- save precision in
 			 * case it's a %s format.
 			 */
-			while (index(".#-+ 0123456789" + 1, *++fmt));
+			while (strchr(index_str + 1, *++fmt));
 			if (*fmt == '.' && isdigit(*++fmt)) {
 				prec = atoi(fmt);
 				while (isdigit(*++fmt));
 			}
-			switch (*fmt) {
-			case 'c':
-				bcnt += 1;
-				break;
-			case 'd':
-			case 'i':
-			case 'o':
-			case 'u':
-			case 'x':
-			case 'X':
-				bcnt += 4;
-				break;
-			case 'e':
-			case 'E':
-			case 'f':
-			case 'g':
-			case 'G':
-				bcnt += 8;
-				break;
-			case 's':
-				bcnt += prec;
-				break;
-			case '_':
-				switch (*++fmt) {
-				case 'c':
-				case 'p':
-				case 'u':
-					bcnt += 1;
-					break;
+			if (!(p = strchr(size_conv_str + 12, *fmt))) {
+				if (*fmt == 's') {
+					bcnt += prec;
+				} else if (*fmt == '_') {
+					++fmt;
+					if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) {
+						bcnt += 1;
+					}
 				}
+			} else {
+				bcnt += size_conv_str[p - (size_conv_str + 12)];
 			}
 		}
-		cursize += bcnt * fu->reps;
+		cur_size += bcnt * fu->reps;
 	}
-	return (cursize);
+	return (cur_size);
 }
 
-void rewrite(FS * fs)
+static void rewrite(FS * fs)
 {
 	enum { NOTOKAY, USEBCNT, USEPREC } sokay;
 	register PR *pr, **nextpr = NULL;
 	register FU *fu;
 	register char *p1, *p2;
 	char savech, *fmtp;
+	const char *byte_count_str;
 	int nconv, prec = 0;
 
 	for (fu = fs->nextfu; fu; fu = fu->nextfu) {
@@ -128,7 +114,7 @@
 			else
 				*nextpr = pr;
 
-			/* skip preceding text and up to the next % sign */
+			/* bb_dump_skip preceding text and up to the next % sign */
 			for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
 
 			/* only text in the string */
@@ -144,11 +130,11 @@
 			 */
 			if (fu->bcnt) {
 				sokay = USEBCNT;
-				/* skip to conversion character */
-				for (++p1; index(".#-+ 0123456789", *p1); ++p1);
+				/* bb_dump_skip to conversion character */
+				for (++p1; strchr(index_str, *p1); ++p1);
 			} else {
-				/* skip any special chars, field width */
-				while (index(".#-+ 0123456789" + 1, *++p1));
+				/* bb_dump_skip any special chars, field width */
+				while (strchr(index_str + 1, *++p1));
 				if (*p1 == '.' && isdigit(*++p1)) {
 					sokay = USEPREC;
 					prec = atoi(p1);
@@ -162,104 +148,59 @@
 			/*
 			 * figure out the byte count for each conversion;
 			 * rewrite the format as necessary, set up blank-
-			 * padding for end of data.
+			 * pbb_dump_adding for end of data.
 			 */
-			switch (*p1) {
-			case 'c':
+
+			if (*p1 == 'c') {
 				pr->flags = F_CHAR;
-				switch (fu->bcnt) {
-				case 0:
-				case 1:
-					pr->bcnt = 1;
-					break;
-				default:
-					p1[1] = '\0';
-					error_msg_and_die
-						("bad byte count for conversion character %s.", p1);
+			DO_BYTE_COUNT_1:
+				byte_count_str = "\001";
+			DO_BYTE_COUNT:
+				if (fu->bcnt) {
+					do {
+						if (fu->bcnt == *byte_count_str) {
+							break;
+						}
+					} while (*++byte_count_str);
 				}
-				break;
-			case 'd':
-			case 'i':
-				pr->flags = F_INT;
-				goto sw1;
-			case 'l':
+				/* Unlike the original, output the remainder of the format string. */
+				if (!*byte_count_str) {
+					bb_error_msg_and_die("bad byte count for conversion character %s.", p1);
+				}
+				pr->bcnt = *byte_count_str;
+			} else if (*p1 == 'l') {
 				++p2;
-				switch (p1[1]) {
-				case 'd':
-				case 'i':
-					++p1;
+				++p1;
+			DO_INT_CONV:
+				{
+					const char *e;
+					if (!(e = strchr(lcc, *p1))) {
+						goto DO_BAD_CONV_CHAR;
+					}
 					pr->flags = F_INT;
-					goto sw1;
-				case 'o':
-				case 'u':
-				case 'x':
-				case 'X':
-					++p1;
-					pr->flags = F_UINT;
-					goto sw1;
-				default:
-					p1[2] = '\0';
-					error_msg_and_die
-						("hexdump: bad conversion character %%%s.\n", p1);
+					if (e > lcc + 1) {
+						pr->flags = F_UINT;
+					}
+					byte_count_str = "\004\002\001";
+					goto DO_BYTE_COUNT;
 				}
 				/* NOTREACHED */
-			case 'o':
-			case 'u':
-			case 'x':
-			case 'X':
-				pr->flags = F_UINT;
-			  sw1:switch (fu->bcnt) {
-				case 0:
-				case 4:
-					pr->bcnt = 4;
-					break;
-				case 1:
-					pr->bcnt = 1;
-					break;
-				case 2:
-					pr->bcnt = 2;
-					break;
-				default:
-					p1[1] = '\0';
-					error_msg_and_die
-						("bad byte count for conversion character %s.", p1);
-				}
-				break;
-			case 'e':
-			case 'E':
-			case 'f':
-			case 'g':
-			case 'G':
+			} else if (strchr(lcc, *p1)) {
+				goto DO_INT_CONV;
+			} else if (strchr("eEfgG", *p1)) {
 				pr->flags = F_DBL;
-				switch (fu->bcnt) {
-				case 0:
-				case 8:
-					pr->bcnt = 8;
-					break;
-				case 4:
-					pr->bcnt = 4;
-					break;
-				default:
-					p1[1] = '\0';
-					error_msg_and_die
-						("bad byte count for conversion character %s.", p1);
-				}
-				break;
-			case 's':
+				byte_count_str = "\010\004";
+				goto DO_BYTE_COUNT;
+			} else if (*p1 == 's') {
 				pr->flags = F_STR;
-				switch (sokay) {
-				case NOTOKAY:
-					error_msg_and_die
-						("%%s requires a precision or a byte count.");
-				case USEBCNT:
+				if (sokay == USEBCNT) {
 					pr->bcnt = fu->bcnt;
-					break;
-				case USEPREC:
+				} else if (sokay == USEPREC) {
 					pr->bcnt = prec;
-					break;
+				} else {	/* NOTOKAY */
+					bb_error_msg_and_die("%%s requires a precision or a byte count.");
 				}
-				break;
-			case '_':
+			} else if (*p1 == '_') {
 				++p2;
 				switch (p1[1]) {
 				case 'A':
@@ -269,51 +210,29 @@
 				case 'a':
 					pr->flags = F_ADDRESS;
 					++p2;
-					switch (p1[2]) {
-					case 'd':
-					case 'o':
-					case 'x':
-						*p1 = p1[2];
-						break;
-					default:
-						p1[3] = '\0';
-						error_msg_and_die
-							("hexdump: bad conversion character %%%s.\n", p1);
+					if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) {
+						goto DO_BAD_CONV_CHAR;
 					}
+					*p1 = p1[2];
 					break;
 				case 'c':
 					pr->flags = F_C;
 					/* *p1 = 'c';   set in conv_c */
-					goto sw2;
+					goto DO_BYTE_COUNT_1;
 				case 'p':
 					pr->flags = F_P;
 					*p1 = 'c';
-					goto sw2;
+					goto DO_BYTE_COUNT_1;
 				case 'u':
 					pr->flags = F_U;
 					/* *p1 = 'c';   set in conv_u */
-				  sw2:switch (fu->bcnt) {
-					case 0:
-					case 1:
-						pr->bcnt = 1;
-						break;
-					default:
-						p1[2] = '\0';
-						error_msg_and_die
-							("bad byte count for conversion character %s.",
-							 p1);
-					}
-					break;
+					goto DO_BYTE_COUNT_1;
 				default:
-					p1[2] = '\0';
-					error_msg_and_die
-						("hexdump: bad conversion character %%%s.\n", p1);
+					goto DO_BAD_CONV_CHAR;
 				}
-				break;
-			default:
-				p1[1] = '\0';
-				error_msg_and_die("hexdump: bad conversion character %%%s.\n",
-								  p1);
+			} else {
+			DO_BAD_CONV_CHAR:
+				bb_error_msg_and_die("bad conversion character %%%s.\n", p1);
 			}
 
 			/*
@@ -322,16 +241,14 @@
 			 */
 			savech = *p2;
 			p1[1] = '\0';
-			if (!(pr->fmt = strdup(fmtp)))
-				perror_msg_and_die("hexdump");
+			pr->fmt = bb_xstrdup(fmtp);
 			*p2 = savech;
 			pr->cchar = pr->fmt + (p1 - fmtp);
 			fmtp = p2;
 
 			/* only one conversion character if byte count */
 			if (!(pr->flags & F_ADDRESS) && fu->bcnt && nconv++) {
-				error_msg_and_die
-					("hexdump: byte count with multiple conversion characters.\n");
+				bb_error_msg_and_die("byte count with multiple conversion characters.\n");
 			}
 		}
 		/*
@@ -344,7 +261,7 @@
 	}
 	/*
 	 * if the format string interprets any data at all, and it's
-	 * not the same as the blocksize, and its last format unit
+	 * not the same as the bb_dump_blocksize, and its last format unit
 	 * interprets any data at all, and has no iteration count,
 	 * repeat it as necessary.
 	 *
@@ -352,9 +269,9 @@
 	 * gets output from the last iteration of the format unit.
 	 */
 	for (fu = fs->nextfu;; fu = fu->nextfu) {
-		if (!fu->nextfu && fs->bcnt < blocksize &&
+		if (!fu->nextfu && fs->bcnt < bb_dump_blocksize &&
 			!(fu->flags & F_SETREP) && fu->bcnt)
-			fu->reps += (blocksize - fs->bcnt) / fu->bcnt;
+			fu->reps += (bb_dump_blocksize - fs->bcnt) / fu->bcnt;
 		if (fu->reps > 1) {
 			for (pr = fu->nextpr;; pr = pr->nextpr)
 				if (!pr->nextpr)
@@ -369,31 +286,31 @@
 	}
 }
 
-static void doskip(char *fname, int statok)
+static void do_skip(char *fname, int statok)
 {
 	struct stat sbuf;
 
 	if (statok) {
 		if (fstat(fileno(stdin), &sbuf)) {
-			perror_msg_and_die("hexdump: %s", fname);
+			bb_perror_msg_and_die("%s", fname);
 		}
 		if ((!(S_ISCHR(sbuf.st_mode) ||
 			   S_ISBLK(sbuf.st_mode) ||
-			   S_ISFIFO(sbuf.st_mode))) && skip >= sbuf.st_size) {
-			/* If size valid and skip >= size */
-			skip -= sbuf.st_size;
+			   S_ISFIFO(sbuf.st_mode))) && bb_dump_skip >= sbuf.st_size) {
+			/* If bb_dump_size valid and bb_dump_skip >= size */
+			bb_dump_skip -= sbuf.st_size;
 			address += sbuf.st_size;
 			return;
 		}
 	}
-	if (fseek(stdin, skip, SEEK_SET)) {
-		perror_msg_and_die("hexdump: %s", fname);
+	if (fseek(stdin, bb_dump_skip, SEEK_SET)) {
+		bb_perror_msg_and_die("%s", fname);
 	}
-	savaddress = address += skip;
-	skip = 0;
+	savaddress = address += bb_dump_skip;
+	bb_dump_skip = 0;
 }
 
-int next(char **argv)
+static int next(char **argv)
 {
 	static int done;
 	int statok;
@@ -405,7 +322,7 @@
 	for (;;) {
 		if (*_argv) {
 			if (!(freopen(*_argv, "r", stdin))) {
-				perror_msg("%s", *_argv);
+				bb_perror_msg("%s", *_argv);
 				exitval = 1;
 				++_argv;
 				continue;
@@ -416,11 +333,11 @@
 				return (0);
 			statok = 0;
 		}
-		if (skip)
-			doskip(statok ? *_argv : "stdin", statok);
+		if (bb_dump_skip)
+			do_skip(statok ? *_argv : "stdin", statok);
 		if (*_argv)
 			++_argv;
-		if (!skip)
+		if (!bb_dump_skip)
 			return (1);
 	}
 	/* NOTREACHED */
@@ -435,26 +352,26 @@
 	u_char *tmpp;
 
 	if (!curp) {
-		curp = (u_char *) xmalloc(blocksize);
-		savp = (u_char *) xmalloc(blocksize);
+		curp = (u_char *) xmalloc(bb_dump_blocksize);
+		savp = (u_char *) xmalloc(bb_dump_blocksize);
 	} else {
 		tmpp = curp;
 		curp = savp;
 		savp = tmpp;
-		address = savaddress += blocksize;
+		address = savaddress += bb_dump_blocksize;
 	}
-	for (need = blocksize, nread = 0;;) {
+	for (need = bb_dump_blocksize, nread = 0;;) {
 		/*
 		 * if read the right number of bytes, or at EOF for one file,
 		 * and no other files are available, zero-pad the rest of the
 		 * block and set the end flag.
 		 */
-		if (!length || (ateof && !next((char **) NULL))) {
-			if (need == blocksize) {
+		if (!bb_dump_length || (ateof && !next((char **) NULL))) {
+			if (need == bb_dump_blocksize) {
 				return ((u_char *) NULL);
 			}
-			if (vflag != ALL && !bcmp(curp, savp, nread)) {
-				if (vflag != DUP) {
+			if (bb_dump_vflag != ALL && !bcmp(curp, savp, nread)) {
+				if (bb_dump_vflag != DUP) {
 					printf("*\n");
 				}
 				return ((u_char *) NULL);
@@ -464,31 +381,32 @@
 			return (curp);
 		}
 		n = fread((char *) curp + nread, sizeof(u_char),
-				  length == -1 ? need : MIN(length, need), stdin);
+				  bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin);
 		if (!n) {
 			if (ferror(stdin)) {
-				perror_msg("%s", _argv[-1]);
+				bb_perror_msg("%s", _argv[-1]);
 			}
 			ateof = 1;
 			continue;
 		}
 		ateof = 0;
-		if (length != -1) {
-			length -= n;
+		if (bb_dump_length != -1) {
+			bb_dump_length -= n;
 		}
 		if (!(need -= n)) {
-			if (vflag == ALL || vflag == FIRST || bcmp(curp, savp, blocksize)) {
-				if (vflag == DUP || vflag == FIRST) {
-					vflag = WAIT;
+			if (bb_dump_vflag == ALL || bb_dump_vflag == FIRST
+				|| bcmp(curp, savp, bb_dump_blocksize)) {
+				if (bb_dump_vflag == DUP || bb_dump_vflag == FIRST) {
+					bb_dump_vflag = WAIT;
 				}
 				return (curp);
 			}
-			if (vflag == WAIT) {
+			if (bb_dump_vflag == WAIT) {
 				printf("*\n");
 			}
-			vflag = DUP;
-			address = savaddress += blocksize;
-			need = blocksize;
+			bb_dump_vflag = DUP;
+			address = savaddress += bb_dump_blocksize;
+			need = bb_dump_blocksize;
 			nread = 0;
 		} else {
 			nread += n;
@@ -507,67 +425,59 @@
 	pr->flags = F_BPAD;
 	*pr->cchar = 's';
 	for (p1 = pr->fmt; *p1 != '%'; ++p1);
-	for (p2 = ++p1; *p1 && index(" -0+#", *p1); ++p1);
+	for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1);
 	while ((*p2++ = *p1++) != 0);
 }
 
-void conv_c(PR * pr, u_char * p)
-{
-	char buf[10], *str;
+static const char conv_str[] =
+	"\0\\0\0"
+	"\007\\a\0"				/* \a */
+	"\b\\b\0"
+	"\f\\b\0"
+	"\n\\n\0"
+	"\r\\r\0"
+	"\t\\t\0"
+	"\v\\v\0"
+	"\0";
 
-	switch (*p) {
-	case '\0':
-		str = "\\0";
-		goto strpr;
-		/* case '\a': */
-	case '\007':
-		str = "\\a";
-		goto strpr;
-	case '\b':
-		str = "\\b";
-		goto strpr;
-	case '\f':
-		str = "\\f";
-		goto strpr;
-	case '\n':
-		str = "\\n";
-		goto strpr;
-	case '\r':
-		str = "\\r";
-		goto strpr;
-	case '\t':
-		str = "\\t";
-		goto strpr;
-	case '\v':
-		str = "\\v";
-		goto strpr;
-	default:
-		break;
-	}
+
+static void conv_c(PR * pr, u_char * p)
+{
+	const char *str = conv_str;
+	char buf[10];
+
+	do {
+		if (*p == *str) {
+			++str;
+			goto strpr;
+		}
+		str += 4;
+	} while (*str);
+
 	if (isprint(*p)) {
 		*pr->cchar = 'c';
 		(void) printf(pr->fmt, *p);
 	} else {
-		sprintf(str = buf, "%03o", (int) *p);
+		sprintf(buf, "%03o", (int) *p);
+		str = buf;
 	  strpr:
 		*pr->cchar = 's';
 		printf(pr->fmt, str);
 	}
 }
 
-void conv_u(PR * pr, u_char * p)
+static void conv_u(PR * pr, u_char * p)
 {
-	static char *list[] = {
-		"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
-		"bs", "ht", "lf", "vt", "ff", "cr", "so", "si",
-		"dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb",
-		"can", "em", "sub", "esc", "fs", "gs", "rs", "us",
-	};
+	static const char list[] =
+		"nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0"
+		"bs\0_ht\0_lf\0_vt\0_ff\0_cr\0_so\0_si\0_"
+		"dle\0dcl\0dc2\0dc3\0dc4\0nak\0syn\0etb\0"
+		"can\0em\0_sub\0esc\0fs\0_gs\0_rs\0_us";
 
 	/* od used nl, not lf */
 	if (*p <= 0x1f) {
 		*pr->cchar = 's';
-		printf(pr->fmt, list[*p]);
+		printf(pr->fmt, list[4 * (int)(*p)]);
 	} else if (*p == 0x7f) {
 		*pr->cchar = 's';
 		printf(pr->fmt, "del");
@@ -580,7 +490,7 @@
 	}
 }
 
-void display(void)
+static void display(void)
 {
 /*  extern FU *endfu; */
 	register FS *fs;
@@ -589,11 +499,11 @@
 	register int cnt;
 	register u_char *bp;
 
-/*  off_t saveaddress; */
+	off_t saveaddress;
 	u_char savech = 0, *savebp;
 
 	while ((bp = get()) != NULL) {
-		for (fs = fshead, savebp = bp, saveaddress = address; fs;
+		for (fs = bb_dump_fshead, savebp = bp, saveaddress = address; fs;
 			 fs = fs->nextfs, bp = savebp, address = saveaddress) {
 			for (fu = fs->nextfu; fu; fu = fu->nextfu) {
 				if (fu->flags & F_IGNORE) {
@@ -707,8 +617,8 @@
 	}
 	if (endfu) {
 		/*
-		 * if eaddress not set, error or file size was multiple of
-		 * blocksize, and no partial block ever found.
+		 * if eaddress not set, error or file bb_dump_size was multiple of
+		 * bb_dump_blocksize, and no partial block ever found.
 		 */
 		if (!eaddress) {
 			if (!address) {
@@ -729,19 +639,19 @@
 	}
 }
 
-int dump(char **argv)
+int bb_dump_dump(char **argv)
 {
 	register FS *tfs;
 
-	/* figure out the data block size */
-	for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) {
-		tfs->bcnt = size(tfs);
-		if (blocksize < tfs->bcnt) {
-			blocksize = tfs->bcnt;
+	/* figure out the data block bb_dump_size */
+	for (bb_dump_blocksize = 0, tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) {
+		tfs->bcnt = bb_dump_size(tfs);
+		if (bb_dump_blocksize < tfs->bcnt) {
+			bb_dump_blocksize = tfs->bcnt;
 		}
 	}
 	/* rewrite the rules, do syntax checking */
-	for (tfs = fshead; tfs; tfs = tfs->nextfs) {
+	for (tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) {
 		rewrite(tfs);
 	}
 
@@ -751,21 +661,21 @@
 	return (exitval);
 }
 
-void add(char *fmt)
+void bb_dump_add(const char *fmt)
 {
-	register char *p;
+	register const char *p;
 	register char *p1;
 	register char *p2;
 	static FS **nextfs;
 	FS *tfs;
 	FU *tfu, **nextfu;
-	char *savep;
+	const char *savep;
 
 	/* start new linked list of format units */
 	/* NOSTRICT */
 	tfs = (FS *) xmalloc(sizeof(FS));
-	if (!fshead) {
-		fshead = tfs;
+	if (!bb_dump_fshead) {
+		bb_dump_fshead = tfs;
 	} else {
 		*nextfs = tfs;
 	}
@@ -774,8 +684,8 @@
 
 	/* take the format string and break it up into format units */
 	for (p = fmt;;) {
-		/* skip leading white space */
-		for (; isspace(*p); ++p);
+		/* bb_dump_skip leading white space */
+		p = bb_skip_whitespace(p);
 		if (!*p) {
 			break;
 		}
@@ -791,43 +701,41 @@
 		if (isdigit(*p)) {
 			for (savep = p; isdigit(*p); ++p);
 			if (!isspace(*p) && *p != '/') {
-				error_msg_and_die("hexdump: bad format {%s}", fmt);
+				bb_error_msg_and_die("bad format {%s}", fmt);
 			}
 			/* may overwrite either white space or slash */
 			tfu->reps = atoi(savep);
 			tfu->flags = F_SETREP;
-			/* skip trailing white space */
-			for (++p; isspace(*p); ++p);
+			/* bb_dump_skip trailing white space */
+			p = bb_skip_whitespace(++p);
 		}
 
-		/* skip slash and trailing white space */
+		/* bb_dump_skip slash and trailing white space */
 		if (*p == '/') {
-			while (isspace(*++p));
+			p = bb_skip_whitespace(++p);
 		}
 
 		/* byte count */
 		if (isdigit(*p)) {
 			for (savep = p; isdigit(*p); ++p);
 			if (!isspace(*p)) {
-				error_msg_and_die("hexdump: bad format {%s}", fmt);
+				bb_error_msg_and_die("bad format {%s}", fmt);
 			}
 			tfu->bcnt = atoi(savep);
-			/* skip trailing white space */
-			for (++p; isspace(*p); ++p);
+			/* bb_dump_skip trailing white space */
+			p = bb_skip_whitespace(++p);
 		}
 
 		/* format */
 		if (*p != '"') {
-			error_msg_and_die("hexdump: bad format {%s}", fmt);
+			bb_error_msg_and_die("bad format {%s}", fmt);
 		}
 		for (savep = ++p; *p != '"';) {
 			if (*p++ == 0) {
-				error_msg_and_die("hexdump: bad format {%s}", fmt);
+				bb_error_msg_and_die("bad format {%s}", fmt);
 			}
 		}
-		if (!(tfu->fmt = malloc(p - savep + 1))) {
-			perror_msg_and_die("hexdump");
-		}
+		tfu->fmt = xmalloc(p - savep + 1);
 		strncpy(tfu->fmt, savep, p - savep);
 		tfu->fmt[p - savep] = '\0';
 /*      escape(tfu->fmt); */
@@ -841,33 +749,16 @@
 				break;
 			}
 			if (*p1 == '\\') {
-				switch (*++p1) {
-				case 'a':
-					/* *p2 = '\a'; */
-					*p2 = '\007';
-					break;
-				case 'b':
-					*p2 = '\b';
-					break;
-				case 'f':
-					*p2 = '\f';
-					break;
-				case 'n':
-					*p2 = '\n';
-					break;
-				case 'r':
-					*p2 = '\r';
-					break;
-				case 't':
-					*p2 = '\t';
-					break;
-				case 'v':
-					*p2 = '\v';
-					break;
-				default:
-					*p2 = *p1;
-					break;
-				}
+				const char *cs = conv_str + 4;
+				++p1;
+				*p2 = *p1;
+				do {
+					if (*p1 == cs[2]) {
+						*p2 = cs[0];
+						break;
+					}
+					cs += 4;
+				} while (*cs);
 			}
 		}
 
diff --git a/libbb/error_msg.c b/libbb/error_msg.c
index 58308b6..5456dd3 100644
--- a/libbb/error_msg.c
+++ b/libbb/error_msg.c
@@ -25,12 +25,12 @@
 #include <stdlib.h>
 #include "libbb.h"
 
-extern void error_msg(const char *s, ...)
+extern void bb_error_msg(const char *s, ...)
 {
 	va_list p;
 
 	va_start(p, s);
-	verror_msg(s, p);
+	bb_verror_msg(s, p);
 	va_end(p);
 	putc('\n', stderr);
 }
diff --git a/libbb/error_msg_and_die.c b/libbb/error_msg_and_die.c
index 67a79c3..7e73937 100644
--- a/libbb/error_msg_and_die.c
+++ b/libbb/error_msg_and_die.c
@@ -25,15 +25,15 @@
 #include <stdlib.h>
 #include "libbb.h"
 
-extern void error_msg_and_die(const char *s, ...)
+extern void bb_error_msg_and_die(const char *s, ...)
 {
 	va_list p;
 
 	va_start(p, s);
-	verror_msg(s, p);
+	bb_verror_msg(s, p);
 	va_end(p);
 	putc('\n', stderr);
-	exit(EXIT_FAILURE);
+	exit(bb_default_error_retval);
 }
 
 
diff --git a/libbb/fclose_nonstdin.c b/libbb/fclose_nonstdin.c
new file mode 100644
index 0000000..97e303e
--- /dev/null
+++ b/libbb/fclose_nonstdin.c
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * fclose_nonstdin implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* A number of standard utilites can accept multiple command line args
+ * of '-' for stdin, according to SUSv3.  So we encapsulate the check
+ * here to save a little space.
+ */
+
+#include <stdio.h>
+#include <libbb.h>
+
+int bb_fclose_nonstdin(FILE *f)
+{
+	if (f != stdin) {
+		return fclose(f);
+	}
+	return 0;
+}
diff --git a/libbb/fflush_stdout_and_exit.c b/libbb/fflush_stdout_and_exit.c
new file mode 100644
index 0000000..cbba042
--- /dev/null
+++ b/libbb/fflush_stdout_and_exit.c
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * fflush_stdout_and_exit implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Attempt to fflush(stdout), and exit with an error code if stdout is
+ * in an error state.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libbb.h>
+
+void bb_fflush_stdout_and_exit(int retval)
+{
+	if (fflush(stdout)) {
+		retval = bb_default_error_retval;
+	}
+	exit(retval);
+}
diff --git a/libbb/find_root_device.c b/libbb/find_root_device.c
index 0a3f1bc..763ac75 100644
--- a/libbb/find_root_device.c
+++ b/libbb/find_root_device.c
@@ -38,14 +38,14 @@
 	dev_t dev;
 
 	if (stat("/", &rootStat) != 0) 
-		perror_msg("could not stat '/'");
+		bb_perror_msg("could not stat '/'");
 	else {
 		if ((dev = rootStat.st_rdev)==0) 
 			dev=rootStat.st_dev;
 
 		dir = opendir("/dev");
 		if (!dir) 
-			perror_msg("could not open '/dev'");
+			bb_perror_msg("could not open '/dev'");
 		else {
 			while((entry = readdir(dir)) != NULL) {
 
@@ -69,7 +69,7 @@
 		}
 	}
 	if(fileName==NULL)
-		fileName=xstrdup("/dev/root");
+		fileName=bb_xstrdup("/dev/root");
 	return fileName;
 }
 
diff --git a/libbb/full_read.c b/libbb/full_read.c
index ccf26fc..e75f967 100644
--- a/libbb/full_read.c
+++ b/libbb/full_read.c
@@ -23,17 +23,16 @@
 #include <unistd.h>
 #include "libbb.h"
 
-
 /*
  * 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.
  */
-int full_read(int fd, char *buf, int len)
+ssize_t bb_full_read(int fd, void *buf, size_t len)
 {
-	int cc;
-	int total;
+	ssize_t cc;
+	ssize_t total;
 
 	total = 0;
 
@@ -41,12 +40,12 @@
 		cc = read(fd, buf, len);
 
 		if (cc < 0)
-			return -1;
+			return cc;	/* read() returns -1 on failure. */
 
 		if (cc == 0)
 			break;
 
-		buf += cc;
+		buf = ((char *)buf) + cc;
 		total += cc;
 		len -= cc;
 	}
diff --git a/libbb/full_write.c b/libbb/full_write.c
index a2c07fb..1106a53 100644
--- a/libbb/full_write.c
+++ b/libbb/full_write.c
@@ -28,10 +28,10 @@
  * This does multiple writes as necessary.
  * Returns the amount written, or -1 on an error.
  */
-int full_write(int fd, const char *buf, int len)
+ssize_t bb_full_write(int fd, const void *buf, size_t len)
 {
-	int cc;
-	int total;
+	ssize_t cc;
+	ssize_t total;
 
 	total = 0;
 
@@ -39,10 +39,10 @@
 		cc = write(fd, buf, len);
 
 		if (cc < 0)
-			return -1;
+			return cc;		/* write() returns -1 on failure. */
 
-		buf += cc;
 		total += cc;
+		buf = ((const char *)buf) + cc;
 		len -= cc;
 	}
 
diff --git a/libbb/get_console.c b/libbb/get_console.c
index 794888f..562b577 100644
--- a/libbb/get_console.c
+++ b/libbb/get_console.c
@@ -106,7 +106,7 @@
 		if (is_a_console(fd))
 			return fd;
 
-	error_msg("Couldn't get a file descriptor referring to the console");
+	bb_error_msg("Couldn't get a file descriptor referring to the console");
 	return -1;					/* total failure */
 }
 
diff --git a/libbb/get_last_path_component.c b/libbb/get_last_path_component.c
index 6af726c..497d6ae 100644
--- a/libbb/get_last_path_component.c
+++ b/libbb/get_last_path_component.c
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * get_last_path_component implementation for busybox
+ * bb_get_last_path_component implementation for busybox
  *
- * Copyright (C) 2001  Manuel Novoa III  <mjn3@opensource.lineo.com>
+ * Copyright (C) 2001  Manuel Novoa III  <mjn3@codepoet.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
 /* WARNING!!! Doing so will break basename applet at least! */
 #define EMULATE_BASENAME	0
 
-char *get_last_path_component(char *path)
+char *bb_get_last_path_component(char *path)
 {
 #if EMULATE_BASENAME
 	static const char null_or_empty[] = ".";
diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c
index 5e70621..5af8989 100644
--- a/libbb/get_line_from_file.c
+++ b/libbb/get_line_from_file.c
@@ -21,41 +21,57 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include "libbb.h"
 
-
-
-/* get_line_from_file() - This function reads an entire line from a text file
+/* get_line_from_file() - This function reads an entire line from a text file,
  * up to a newline. It returns a malloc'ed char * which must be stored and
- * free'ed  by the caller. */
-extern char *get_line_from_file(FILE *file)
+ * free'ed  by the caller.  If 'c' is nonzero, the trailing '\n' (if any)
+ * is removed.  In event of a read error or EOF, NULL is returned. */
+
+static char *private_get_line_from_file(FILE *file, int c)
 {
-	static const int GROWBY = 80; /* how large we will grow strings by */
+#define GROWBY (80)		/* how large we will grow strings by */
 
 	int ch;
 	int idx = 0;
 	char *linebuf = NULL;
 	int linebufsz = 0;
 
-	while (1) {
-		ch = fgetc(file);
-		if (ch == EOF)
-			break;
+	while ((ch = getc(file)) != EOF) {
 		/* grow the line buffer as necessary */
-		while (idx > linebufsz-2)
+		if (idx > linebufsz-2) {
 			linebuf = xrealloc(linebuf, linebufsz += GROWBY);
+		}
 		linebuf[idx++] = (char)ch;
-		if (ch == '\n' || ch == '\0')
+		if (ch == '\n' || ch == '\0') {
+			if (c) {
+				--idx;
+			}
 			break;
+		}
 	}
 
-	if (idx == 0)
-		return NULL;
-
-	linebuf[idx] = 0;
+	if (linebuf) {
+		if (ferror(file)) {
+			free(linebuf);
+			return NULL;
+		}
+		linebuf[idx] = 0;
+	}
 	return linebuf;
 }
 
+extern char *bb_get_line_from_file(FILE *file)
+{
+	return private_get_line_from_file(file, 0);
+}
+
+extern char *bb_get_chomped_line_from_file(FILE *file)
+{
+	return private_get_line_from_file(file, 1);
+}
+
 
 /* END CODE */
 /*
diff --git a/libbb/getopt_ulflags.c b/libbb/getopt_ulflags.c
new file mode 100644
index 0000000..91de392
--- /dev/null
+++ b/libbb/getopt_ulflags.c
@@ -0,0 +1,41 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * getopt_ulflags implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <getopt.h>
+#include <string.h>
+#include "libbb.h"
+
+unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts)
+{
+	unsigned long flags = 0;
+	const char *s;
+	int c;
+
+	while ((c = getopt(argc, argv, applet_opts)) > 0) {
+		if (!(s = strchr(applet_opts, c))) {
+			bb_show_usage();
+		}
+		flags |= (1 << (s-applet_opts));
+	}
+
+	return flags;
+}
diff --git a/libbb/herror_msg.c b/libbb/herror_msg.c
index 1081a56..4fe921b 100644
--- a/libbb/herror_msg.c
+++ b/libbb/herror_msg.c
@@ -24,12 +24,12 @@
 
 #include "libbb.h"
 
-extern void herror_msg(const char *s, ...)
+extern void bb_herror_msg(const char *s, ...)
 {
 	va_list p;
 
 	va_start(p, s);
-	vherror_msg(s, p);
+	bb_vherror_msg(s, p);
 	va_end(p);
 }
 
diff --git a/libbb/herror_msg_and_die.c b/libbb/herror_msg_and_die.c
index a47c7ff..33a8c3e 100644
--- a/libbb/herror_msg_and_die.c
+++ b/libbb/herror_msg_and_die.c
@@ -24,14 +24,14 @@
 
 #include "libbb.h"
 
-extern void herror_msg_and_die(const char *s, ...)
+extern void bb_herror_msg_and_die(const char *s, ...)
 {
 	va_list p;
 
 	va_start(p, s);
-	vherror_msg(s, p);
+	bb_vherror_msg(s, p);
 	va_end(p);
-	exit(EXIT_FAILURE);
+	exit(bb_default_error_retval);
 }
 
 
diff --git a/libbb/inet_common.c b/libbb/inet_common.c
index 16dd1db..5e2343b 100644
--- a/libbb/inet_common.c
+++ b/libbb/inet_common.c
@@ -4,7 +4,7 @@
  *
  * Heavily modified by Manuel Novoa III       Mar 12, 2001
  *
- * Version:     $Id: inet_common.c,v 1.5 2002/11/28 09:52:23 bug1 Exp $
+ * Version:     $Id: inet_common.c,v 1.6 2003/03/19 09:12:07 mjn3 Exp $
  *
  */
 
@@ -44,7 +44,7 @@
 	/* If we expect this to be a hostname, try hostname database first */
 #ifdef DEBUG
 	if (hostfirst) {
-		error_msg("gethostbyname (%s)", name);
+		bb_error_msg("gethostbyname (%s)", name);
 	}
 #endif
 	if (hostfirst && (hp = gethostbyname(name)) != (struct hostent *) NULL) {
@@ -54,7 +54,7 @@
 	}
 	/* Try the NETWORKS database to see if this is a known network. */
 #ifdef DEBUG
-	error_msg("getnetbyname (%s)", name);
+	bb_error_msg("getnetbyname (%s)", name);
 #endif
 	if ((np = getnetbyname(name)) != (struct netent *) NULL) {
 		s_in->sin_addr.s_addr = htonl(np->n_net);
@@ -71,7 +71,7 @@
 #endif
 
 #ifdef DEBUG
-	error_msg("gethostbyname (%s)", name);
+	bb_error_msg("gethostbyname (%s)", name);
 #endif
 	if ((hp = gethostbyname(name)) == (struct hostent *) NULL) {
 		errno = h_errno;
@@ -109,7 +109,7 @@
 	/* Grmpf. -FvK */
 	if (s_in->sin_family != AF_INET) {
 #ifdef DEBUG
-		error_msg("rresolve: unsupport address family %d !",
+		bb_error_msg("rresolve: unsupport address family %d !",
 				  s_in->sin_family);
 #endif
 		errno = EAFNOSUPPORT;
@@ -117,7 +117,7 @@
 	}
 	ad = (unsigned long) s_in->sin_addr.s_addr;
 #ifdef DEBUG
-	error_msg("rresolve: %08lx, mask %08x, num %08x", ad, netmask, numeric);
+	bb_error_msg("rresolve: %08lx, mask %08x, num %08x", ad, netmask, numeric);
 #endif
 	if (ad == INADDR_ANY) {
 		if ((numeric & 0x0FFF) == 0) {
@@ -143,7 +143,7 @@
 		if (pn->addr.sin_addr.s_addr == ad && pn->host == host) {
 			safe_strncpy(name, pn->name, len);
 #ifdef DEBUG
-			error_msg("rresolve: found %s %08lx in cache",
+			bb_error_msg("rresolve: found %s %08lx in cache",
 					  (host ? "host" : "net"), ad);
 #endif
 			return (0);
@@ -156,7 +156,7 @@
 	ent = NULL;
 	if (host) {
 #ifdef DEBUG
-		error_msg("gethostbyaddr (%08lx)", ad);
+		bb_error_msg("gethostbyaddr (%08lx)", ad);
 #endif
 		ent = gethostbyaddr((char *) &ad, 4, AF_INET);
 		if (ent != NULL) {
@@ -164,7 +164,7 @@
 		}
 	} else {
 #ifdef DEBUG
-		error_msg("getnetbyaddr (%08lx)", host_ad);
+		bb_error_msg("getnetbyaddr (%08lx)", host_ad);
 #endif
 		np = getnetbyaddr(host_ad, AF_INET);
 		if (np != NULL) {
@@ -178,7 +178,7 @@
 	pn->addr = *s_in;
 	pn->next = INET_nn;
 	pn->host = host;
-	pn->name = xstrdup(name);
+	pn->name = bb_xstrdup(name);
 	INET_nn = pn;
 
 	return (0);
@@ -194,7 +194,7 @@
 	memset(&req, '\0', sizeof req);
 	req.ai_family = AF_INET6;
 	if ((s = getaddrinfo(name, NULL, &req, &ai))) {
-		error_msg("getaddrinfo: %s: %d", name, s);
+		bb_error_msg("getaddrinfo: %s: %d", name, s);
 		return -1;
 	}
 	memcpy(sin6, ai->ai_addr, sizeof(struct sockaddr_in6));
@@ -219,7 +219,7 @@
 	/* Grmpf. -FvK */
 	if (sin6->sin6_family != AF_INET6) {
 #ifdef DEBUG
-		error_msg(_("rresolve: unsupport address family %d !\n"),
+		bb_error_msg(_("rresolve: unsupport address family %d !\n"),
 				  sin6->sin6_family);
 #endif
 		errno = EAFNOSUPPORT;
@@ -240,7 +240,7 @@
 
 	s = getnameinfo((struct sockaddr *) sin6, sizeof(struct sockaddr_in6), name, len, NULL, 0, 0);
 	if (s) {
-		error_msg("getnameinfo failed");
+		bb_error_msg("getnameinfo failed");
 		return -1;
 	}
 	return (0);
diff --git a/libbb/interface.c b/libbb/interface.c
index fb79416..531700f 100644
--- a/libbb/interface.c
+++ b/libbb/interface.c
@@ -15,7 +15,7 @@
  *              that either displays or sets the characteristics of
  *              one or more of the system's networking interfaces.
  *
- * Version:     $Id: interface.c,v 1.14 2003/02/09 22:40:33 bug1 Exp $
+ * Version:     $Id: interface.c,v 1.15 2003/03/19 09:12:07 mjn3 Exp $
  *
  * Author:      Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  *              and others.  Copyright 1993 MicroWalt Corporation
@@ -619,7 +619,7 @@
 			if (strcmp(tmp1, paft->alias))
 				continue;
 			if (strlen(paft->name) + strlen(afname) + 1 >= sizeof(afname)) {
-				error_msg(_("Too many address family arguments."));
+				bb_error_msg(_("Too many address family arguments."));
 				return (0);
 			}
 			if (paft->flag)
@@ -630,7 +630,7 @@
 			break;
 		}
 		if (!paft->alias) {
-			error_msg(_("Unknown address family `%s'."), tmp1);
+			bb_error_msg(_("Unknown address family `%s'."), tmp1);
 			return (1);
 		}
 		tmp1 = tmp2;
@@ -693,7 +693,7 @@
 		afp++;
 	}
 	if (strchr(name, ','))
-		error_msg(_("Please don't supply more than one address family."));
+		bb_error_msg(_("Please don't supply more than one address family."));
 	return (NULL);
 }
 #endif							/* KEEP_UNUSED */
@@ -888,7 +888,7 @@
 			sfd = af->fd;
 	}
 	if (sfd < 0) {
-		error_msg(_("No usable address families found."));
+		bb_error_msg(_("No usable address families found."));
 	}
 	return sfd;
 }
@@ -960,7 +960,7 @@
 	   (as of 2.1.128) */
 	skfd2 = get_socket_for_af(AF_INET);
 	if (skfd2 < 0) {
-		perror_msg(("warning: no inet socket available"));
+		bb_perror_msg(("warning: no inet socket available"));
 		/* Try to soldier on with whatever socket we can get hold of.  */
 		skfd2 = sockets_open(0);
 		if (skfd2 < 0)
@@ -1106,7 +1106,7 @@
 
 	fh = fopen(_PATH_PROCNET_DEV, "r");
 	if (!fh) {
-		perror_msg(_("Warning: cannot open %s. Limited output."), _PATH_PROCNET_DEV);
+		bb_perror_msg(_("Warning: cannot open %s. Limited output."), _PATH_PROCNET_DEV);
 		return if_readconf();
 	}
 	fgets(buf, sizeof buf, fh);	/* eat line */
@@ -1366,7 +1366,7 @@
 		} else {
 			errmsg = strerror(errno);
 		}
-		error_msg(_("%s: error fetching interface information: %s\n"),
+		bb_error_msg(_("%s: error fetching interface information: %s\n"),
 				ife->name, errmsg);
 		return -1;
 	}
@@ -1441,7 +1441,7 @@
 			val = c - 'A' + 10;
 		else {
 #ifdef DEBUG
-			error_msg(_("in_ether(%s): invalid ether address!\n"), orig);
+			bb_error_msg(_("in_ether(%s): invalid ether address!\n"), orig);
 #endif
 			errno = EINVAL;
 			return (-1);
@@ -1458,7 +1458,7 @@
 			val >>= 4;
 		else {
 #ifdef DEBUG
-			error_msg(_("in_ether(%s): invalid ether address!"), orig);
+			bb_error_msg(_("in_ether(%s): invalid ether address!"), orig);
 #endif
 			errno = EINVAL;
 			return (-1);
@@ -1472,7 +1472,7 @@
 		if (*bufp == ':') {
 #ifdef DEBUG
 			if (i == ETH_ALEN) {
-				error_msg(_("in_ether(%s): trailing : ignored!"), orig);
+				bb_error_msg(_("in_ether(%s): trailing : ignored!"), orig);
 			}
 #endif
 			bufp++;
@@ -1482,11 +1482,11 @@
 #ifdef DEBUG
 	/* That's it.  Any trailing junk? */
 	if ((i == ETH_ALEN) && (*bufp != '\0')) {
-		error_msg(_("in_ether(%s): trailing junk!"), orig);
+		bb_error_msg(_("in_ether(%s): trailing junk!"), orig);
 		errno = EINVAL;
 		return (-1);
 	}
-	error_msg("in_ether(%s): %s", orig, pr_ether(sap->sa_data));
+	bb_error_msg("in_ether(%s): %s", orig, pr_ether(sap->sa_data));
 #endif
 
 	return (0);
@@ -1511,7 +1511,7 @@
 /* Start the PPP encapsulation on the file descriptor. */
 static int do_ppp(int fd)
 {
-	error_msg(_("You cannot start PPP with this program."));
+	bb_error_msg(_("You cannot start PPP with this program."));
 	return -1;
 }
 #endif							/* KEEP_UNUSED */
@@ -2052,7 +2052,7 @@
 
 	/* Create a channel to the NET kernel. */
 	if ((skfd = sockets_open(0)) < 0) {
-		perror_msg_and_die("socket");
+		bb_perror_msg_and_die("socket");
 	}
 
 	/* Do we have to show the current setup? */
diff --git a/libbb/kernel_version.c b/libbb/kernel_version.c
index 694af8e..14b1636 100644
--- a/libbb/kernel_version.c
+++ b/libbb/kernel_version.c
@@ -37,7 +37,7 @@
 	int i, r;
 
 	if (uname(&name) == -1) {
-		perror_msg("cannot get system information");
+		bb_perror_msg("cannot get system information");
 		return (0);
 	}
 
diff --git a/libbb/loop.c b/libbb/loop.c
index 7e58b2f..29128ab 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -33,11 +33,11 @@
 	int fd;
 
 	if ((fd = open(device, O_RDONLY)) < 0) {
-		perror_msg("%s", device);
+		bb_perror_msg("%s", device);
 		return (FALSE);
 	}
 	if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
-		perror_msg("ioctl: LOOP_CLR_FD");
+		bb_perror_msg("ioctl: LOOP_CLR_FD");
 		return (FALSE);
 	}
 	close(fd);
@@ -53,12 +53,12 @@
 	mode = *loopro ? O_RDONLY : O_RDWR;
 	if ((ffd = open(file, mode)) < 0 && !*loopro
 		&& (errno != EROFS || (ffd = open(file, mode = O_RDONLY)) < 0)) {
-		perror_msg("%s", file);
+		bb_perror_msg("%s", file);
 		return 1;
 	}
 	if ((fd = open(device, mode)) < 0) {
 		close(ffd);
-		perror_msg("%s", device);
+		bb_perror_msg("%s", device);
 		return 1;
 	}
 	*loopro = (mode == O_RDONLY);
@@ -70,14 +70,14 @@
 
 	loopinfo.lo_encrypt_key_size = 0;
 	if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
-		perror_msg("ioctl: LOOP_SET_FD");
+		bb_perror_msg("ioctl: LOOP_SET_FD");
 		close(fd);
 		close(ffd);
 		return 1;
 	}
 	if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
 		(void) ioctl(fd, LOOP_CLR_FD, 0);
-		perror_msg("ioctl: LOOP_SET_STATUS");
+		bb_perror_msg("ioctl: LOOP_SET_STATUS");
 		close(fd);
 		close(ffd);
 		return 1;
diff --git a/libbb/make_directory.c b/libbb/make_directory.c
index 65be397..e3d2c52 100644
--- a/libbb/make_directory.c
+++ b/libbb/make_directory.c
@@ -1,12 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini make_directory implementation for busybox
+ * parse_mode implementation for busybox
  *
- * Copyright (C) 2001  Matt Kraai.
- * 
- * Rewriten in 2002
- * Copyright (C) 2002 Glenn McGrath
- * Copyright (C) 2002 Vladimir N. Oleynik
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,57 +20,87 @@
  *
  */
 
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
+/* Mar 5, 2003    Manuel Novoa III
+ *
+ * This is the main work function for the 'mkdir' applet.  As such, it
+ * strives to be SUSv3 compliant in it's behaviour when recursively
+ * making missing parent dirs, and in it's mode setting of the final
+ * directory 'path'.
+ *
+ * To recursively build all missing intermediate directories, make
+ * sure that (flags & FILEUTILS_RECUR) is non-zero.  Newly created
+ * intermediate directories will have at least u+wx perms.
+ *
+ * To set specific permisions on 'path', pass the appropriate 'mode'
+ * val.  Otherwise, pass -1 to get default permisions.
+ */
 
+#include <errno.h>
+#include <unistd.h>
 #include "libbb.h"
 
-/* Create the directory PATH with mode MODE, or the default if MODE is -1.
- * Also create parent directories as necessary if flags contains
- * FILEUTILS_RECUR.  */
-
-int make_directory (char *path, long mode, int flags)
+int bb_make_directory (char *path, long mode, int flags)
 {
-	int ret;
+	mode_t mask;
+	const char *fail_msg;
+	char *s = path;
+	char c;
 
-	if (flags == FILEUTILS_RECUR) {
-		char *pp = strrchr(path, '/');
-		if ((pp) && (pp != path)) {
-			*pp = '\0';
-			make_directory(path, -1, flags);
-			*pp = '/';
-		}
-	}
+	mask = umask(0);
+	umask(mask & ~0300);
 
-	if (mode == -1) {
-		struct stat statbuf;
-		char *pp = strrchr(path, '/');
+	do {
+		c = 0;
 
-		statbuf.st_mode = 0777;
-
-		/* stat the directory */
-		if ((pp) && (pp != path)) {
-			*pp = '\0';
-			stat(path, &statbuf);
-			*pp = '/';
+		if (flags & FILEUTILS_RECUR) {	/* Get the parent. */
+			/* Bypass leading non-'/'s and then subsequent '/'s. */
+			while (*s) {
+				if (*s == '/') {
+					do {
+						++s;
+					} while (*s == '/');
+					c = *s;		/* Save the current char */
+					*s = 0;		/* and replace it with nul. */
+					break;
+				}
+				++s;
+			}
 		}
 
-		mode = statbuf.st_mode;
-	}
-
-	ret = mkdir(path, mode);
-	if (ret == -1) {
-		if ((flags == FILEUTILS_RECUR) && (errno == EEXIST)) {
-			ret = 0;
-		} else {
-			perror_msg_and_die("Cannot create directory '%s'", path);
+		if (mkdir(path, 0777) < 0) {
+			/* If we failed for any other reason than the directory
+			 * already exists, output a diagnostic and return -1.*/
+			if (errno != EEXIST) {
+				fail_msg = "create";
+				umask(mask);
+				break;
+			}
+			/* Since the directory exists, don't attempt to change
+			 * permissions if it was the full target.  Note that
+			 * this is not an error conditon. */
+			if (!c) {
+				umask(mask);
+				return 0;
+			}
 		}
-	}
 
-	return(ret);
+		if (!c) {
+			/* Done.  If necessary, updated perms on the newly
+			 * created directory.  Failure to update here _is_
+			 * an error.*/
+			umask(mask);
+			if ((mode != -1) && (chmod(path, mode) < 0)){
+				fail_msg = "set permissions of";
+				break;
+			}
+			return 0;
+		}
+
+		/* Remove any inserted nul from the path (recursive mode). */
+		*s = c;
+
+	} while (1);
+
+	bb_perror_msg ("Cannot %s directory `%s'", fail_msg, path);
+	return -1;
 }
diff --git a/libbb/messages.c b/libbb/messages.c
index cc7e214..e5ffbf7 100644
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -23,82 +23,71 @@
 #include "libbb.h"
 
 #ifdef L_full_version
-	const char * const full_version = BB_BANNER " multi-call binary";
-#endif
-#ifdef L_name_too_long
-	const char * const name_too_long = "file name too long";
-#endif
-
-#ifdef L_omitting_directory
-	const char * const omitting_directory = "%s: omitting directory";
-#endif
-#ifdef L_not_a_directory
-	const char * const not_a_directory = "%s: not a directory";
+	const char * const bb_msg_full_version = BB_BANNER " multi-call binary";
 #endif
 #ifdef L_memory_exhausted
-	const char * const memory_exhausted = "memory exhausted";
+	const char * const bb_msg_memory_exhausted = "memory exhausted";
 #endif
 #ifdef L_invalid_date
-	const char * const invalid_date = "invalid date `%s'";
-#endif
-#ifdef L_invalid_option
-	const char * const invalid_option = "invalid option -- %c";
+	const char * const bb_msg_invalid_date = "invalid date `%s'";
 #endif
 #ifdef L_io_error
-	const char * const io_error = "%s: input/output error -- %m";
-#endif
-#ifdef L_dash_dash_help
-	const char * const dash_dash_help = "--help";
+	const char * const bb_msg_io_error = "%s: input/output error -- %m";
 #endif
 #ifdef L_write_error
-	const char * const write_error = "Write Error";
-#endif
-#ifdef L_too_few_args
-	const char * const too_few_args = "too few arguments";
+	const char * const bb_msg_write_error = "Write Error";
 #endif
 #ifdef L_name_longer_than_foo
-	const char * const name_longer_than_foo = "Names longer than %d chars not supported.";
+	const char * const bb_msg_name_longer_than_foo = "Names longer than %d chars not supported.";
 #endif
 #ifdef L_unknown
-	const char * const unknown = "(unknown)";
+	const char * const bb_msg_unknown = "(unknown)";
 #endif
-
 #ifdef L_can_not_create_raw_socket
-	const char * const can_not_create_raw_socket = "can`t create raw socket";
+	const char * const bb_msg_can_not_create_raw_socket = "can`t create raw socket";
+#endif
+#ifdef L_perm_denied_are_you_root
+	const char * const bb_msg_perm_denied_are_you_root = "permission denied. (are you root?)";
+#endif
+#ifdef L_msg_standard_input
+	const char * const bb_msg_standard_input = "standard input";
+#endif
+#ifdef L_msg_standard_output
+	const char * const bb_msg_standard_output = "standard output";
 #endif
 
 #ifdef L_passwd_file
 #define PASSWD_FILE        "/etc/passwd"
-const char * const passwd_file = PASSWD_FILE;
+const char * const bb_path_passwd_file = PASSWD_FILE;
 #endif
 
 #ifdef L_shadow_file
 #define SHADOW_FILE        "/etc/shadow"
-const char * const shadow_file = SHADOW_FILE;
+const char * const bb_path_shadow_file = SHADOW_FILE;
 #endif
 
 #ifdef L_group_file
 #define GROUP_FILE         "/etc/group"
-const char * const group_file = GROUP_FILE;
+const char * const bb_path_group_file = GROUP_FILE;
 #endif
 
 #ifdef L_gshadow_file
 #define GSHADOW_FILE       "/etc/gshadow"
-const char * const gshadow_file = GSHADOW_FILE;
+const char * const bb_path_gshadow_file = GSHADOW_FILE;
 #endif
 
 #ifdef L_nologin_file
 #define NOLOGIN_FILE       "/etc/nologin"
-const char * const nologin_file = NOLOGIN_FILE;
+const char * const bb_path_nologin_file = NOLOGIN_FILE;
 #endif
 
 #ifdef L_securetty_file
 #define SECURETTY_FILE     "/etc/securetty"
-const char * const securetty_file = SECURETTY_FILE;
+const char * const bb_path_securetty_file = SECURETTY_FILE;
 #endif
 
 #ifdef L_motd_file
 #define MOTD_FILE          "/etc/motd"
-const char * const motd_file = MOTD_FILE;
+const char * const bb_path_motd_file = MOTD_FILE;
 #endif
 
diff --git a/libbb/mode_string.c b/libbb/mode_string.c
index 12dc179..8d4d736 100644
--- a/libbb/mode_string.c
+++ b/libbb/mode_string.c
@@ -1,78 +1,134 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Utility routines.
+ * mode_string implementation for busybox
  *
- * Copyright (C) many different people.  If you wrote this, please
- * acknowledge your work.
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 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
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
  */
 
-#include <stdio.h>
-#include "libbb.h"
+#include <assert.h>
+#include <sys/stat.h>
 
+#if ( S_ISUID != 04000 ) || ( S_ISGID != 02000 ) || ( S_ISVTX != 01000 ) \
+ || ( S_IRUSR != 00400 ) || ( S_IWUSR != 00200 ) || ( S_IXUSR != 00100 ) \
+ || ( S_IRGRP != 00040 ) || ( S_IWGRP != 00020 ) || ( S_IXGRP != 00010 ) \
+ || ( S_IROTH != 00004 ) || ( S_IWOTH != 00002 ) || ( S_IXOTH != 00001 )
+#error permission bitflag value assumption(s) violated!
+#endif
 
+#if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \
+ || ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 ) \
+ || ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \
+ || ( S_IFIFO != 0010000 )
+#warning mode type bitflag value assumption(s) violated! falling back to larger version
 
-#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
-#define TYPECHAR(mode)  ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
+#if (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX) == 07777
+#undef mode_t
+#define mode_t unsigned short
+#endif
 
-/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */
-static const mode_t SBIT[] = {
-	0, 0, S_ISUID,
-	0, 0, S_ISGID,
-	0, 0, S_ISVTX
+static const mode_t mode_flags[] = {
+	S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID,
+	S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID,
+	S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX
 };
 
-/* The 9 mode bits to test */
-static const mode_t MBIT[] = {
-	S_IRUSR, S_IWUSR, S_IXUSR,
-	S_IRGRP, S_IWGRP, S_IXGRP,
-	S_IROTH, S_IWOTH, S_IXOTH
-};
+/* The static const char arrays below are duplicated for the two cases
+ * because moving them ahead of the mode_flags declaration cause a text
+ * size increase with the gcc version I'm using. */
 
-static const char MODE1[]  = "rwxrwxrwx";
-static const char MODE0[]  = "---------";
-static const char SMODE1[] = "..s..s..t";
-static const char SMODE0[] = "..S..S..T";
+/* The previous version used "0pcCd?bB-?l?s???".  However, the '0', 'C',
+ * and 'B' types don't appear to be available on linux.  So I removed them. */
+static const char type_chars[16] = "?pc?d?b?-?l?s???";
+/*                                  0123456789abcdef */
+static const char mode_chars[7] = "rwxSTst";
 
-/*
- * Return the standard ls-like mode string from a file mode.
- * This is static and so is overwritten on each call.
- */
-const char *mode_string(int mode)
+const char *bb_mode_string(int mode)
 {
 	static char buf[12];
+	char *p = buf;
 
-	int i;
+	int i, j, k;
 
-	buf[0] = TYPECHAR(mode);
-	for (i = 0; i < 9; i++) {
-		if (mode & SBIT[i])
-			buf[i + 1] = (mode & MBIT[i]) ? SMODE1[i] : SMODE0[i];
-		else
-			buf[i + 1] = (mode & MBIT[i]) ? MODE1[i] : MODE0[i];
-	}
+	*p = type_chars[ (mode >> 12) & 0xf ];
+	i = 0;
+	do {
+		j = k = 0;
+		do {
+			*++p = '-';
+			if (mode & mode_flags[i+j]) {
+				*p = mode_chars[j];
+				k = j;
+			}
+		} while (++j < 3);
+		if (mode & mode_flags[i+j]) {
+			*p = mode_chars[3 + (k & 2) + ((i&8) >> 3)];
+		}
+		i += 4;
+	} while (i < 12);
+
+	/* Note: We don't bother with nul termination because bss initialization
+	 * should have taken care of that for us.  If the user scribbled in buf
+	 * memory, they deserve whatever happens.  But we'll at least assert. */
+	assert(buf[10] == 0);
+
 	return buf;
 }
 
-/* END CODE */
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
+#else
+
+/* The previous version used "0pcCd?bB-?l?s???".  However, the '0', 'C',
+ * and 'B' types don't appear to be available on linux.  So I removed them. */
+static const char type_chars[16] = "?pc?d?b?-?l?s???";
+/*                                  0123456789abcdef */
+static const char mode_chars[7] = "rwxSTst";
+
+const char *bb_mode_string(int mode)
+{
+	static char buf[12];
+	char *p = buf;
+
+	int i, j, k, m;
+
+	*p = type_chars[ (mode >> 12) & 0xf ];
+	i = 0;
+	m = 0400;
+	do {
+		j = k = 0;
+		do {
+			*++p = '-';
+			if (mode & m) {
+				*p = mode_chars[j];
+				k = j;
+			}
+			m >>= 1;
+		} while (++j < 3);
+		++i;
+		if (mode & (010000 >> i)) {
+			*p = mode_chars[3 + k + (i >> 1)];
+		}
+	} while (i < 3);
+
+	/* Note: We don't bother with nul termination because bss initialization
+	 * should have taken care of that for us.  If the user scribbled in buf
+	 * memory, they deserve whatever happens.  But we'll at least assert. */
+	assert(buf[10] == 0);
+
+	return buf;
+}
+
+#endif
diff --git a/libbb/module_syscalls.c b/libbb/module_syscalls.c
index 6bfff20..8fe9e52 100644
--- a/libbb/module_syscalls.c
+++ b/libbb/module_syscalls.c
@@ -51,7 +51,7 @@
 #warning -> The query_module system call is being stubbed out...
 int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret)
 {
-	error_msg("\n\nTo make this application work, you will need to recompile\n"
+	bb_error_msg("\n\nTo make this application work, you will need to recompile\n"
 		"with a kernel supporting the query_module system call. -Erik\n");
 	errno=ENOSYS;
 	return -1;
diff --git a/libbb/mtab.c b/libbb/mtab.c
index c521b1e..54905c7 100644
--- a/libbb/mtab.c
+++ b/libbb/mtab.c
@@ -27,21 +27,20 @@
 #include <mntent.h>
 #include "libbb.h"
 
-extern const char mtab_file[];	/* Defined in utility.c */
 static const int MS_RDONLY = 1;	/* Mount read-only.  */
 
 void erase_mtab(const char *name)
 {
 	struct mntent entries[20];
 	int count = 0;
-	FILE *mountTable = setmntent(mtab_file, "r");
+	FILE *mountTable = setmntent(bb_path_mtab_file, "r");
 	struct mntent *m;
 
 	/* Check if reading the mtab file failed */
 	if (mountTable == 0
 			/* Bummer.  fall back on trying the /proc filesystem */
 			&& (mountTable = setmntent("/proc/mounts", "r")) == 0) {
-		perror_msg("%s", mtab_file);
+		bb_perror_msg(bb_path_mtab_file);
 		return;
 	}
 
@@ -55,7 +54,7 @@
 		count++;
 	}
 	endmntent(mountTable);
-	if ((mountTable = setmntent(mtab_file, "w"))) {
+	if ((mountTable = setmntent(bb_path_mtab_file, "w"))) {
 		int i;
 
 		for (i = 0; i < count; i++) {
@@ -69,17 +68,17 @@
 		}
 		endmntent(mountTable);
 	} else if (errno != EROFS)
-		perror_msg("%s", mtab_file);
+		bb_perror_msg(bb_path_mtab_file);
 }
 
 void write_mtab(char *blockDevice, char *directory,
 				char *filesystemType, long flags, char *string_flags)
 {
-	FILE *mountTable = setmntent(mtab_file, "a+");
+	FILE *mountTable = setmntent(bb_path_mtab_file, "a+");
 	struct mntent m;
 
 	if (mountTable == 0) {
-		perror_msg("%s", mtab_file);
+		bb_perror_msg(bb_path_mtab_file);
 		return;
 	}
 	if (mountTable) {
diff --git a/libbb/mtab_file.c b/libbb/mtab_file.c
index 2124e01..898e2fa 100644
--- a/libbb/mtab_file.c
+++ b/libbb/mtab_file.c
@@ -26,9 +26,9 @@
 /* Busybox mount uses either /proc/mounts or /etc/mtab to 
  * get the list of currently mounted filesystems */ 
 #if defined CONFIG_FEATURE_MTAB_SUPPORT
-const char mtab_file[] = CONFIG_FEATURE_MTAB_FILENAME;
+const char bb_path_mtab_file[] = CONFIG_FEATURE_MTAB_FILENAME;
 #else
-const char mtab_file[] = "/proc/mounts";
+const char bb_path_mtab_file[] = "/proc/mounts";
 #endif
 
 
diff --git a/libbb/my_getgrnam.c b/libbb/my_getgrnam.c
index f80d3f8..eb5b581 100644
--- a/libbb/my_getgrnam.c
+++ b/libbb/my_getgrnam.c
@@ -33,7 +33,7 @@
 
 	mygroup  = getgrnam(name);
 	if (mygroup==NULL)
-		error_msg_and_die("unknown group name: %s", name);
+		bb_error_msg_and_die("unknown group name: %s", name);
 
 	return (mygroup->gr_gid);
 }
diff --git a/libbb/my_getpwnam.c b/libbb/my_getpwnam.c
index 04951a4..ada2ffb 100644
--- a/libbb/my_getpwnam.c
+++ b/libbb/my_getpwnam.c
@@ -33,7 +33,7 @@
 
 	myuser  = getpwnam(name);
 	if (myuser==NULL)
-		error_msg_and_die("unknown user name: %s", name);
+		bb_error_msg_and_die("unknown user name: %s", name);
 
 	return myuser->pw_uid;
 }
diff --git a/libbb/my_getpwnamegid.c b/libbb/my_getpwnamegid.c
index 07e02c1..06071c9 100644
--- a/libbb/my_getpwnamegid.c
+++ b/libbb/my_getpwnamegid.c
@@ -35,11 +35,11 @@
 
 	myuser=getpwnam(name);
 	if (myuser==NULL)
-		error_msg_and_die("unknown user name: %s", name);
+		bb_error_msg_and_die("unknown user name: %s", name);
 
 	mygroup  = getgrgid(myuser->pw_gid);
 	if (mygroup==NULL)
-		error_msg_and_die("unknown gid %ld", (long)myuser->pw_gid);
+		bb_error_msg_and_die("unknown gid %ld", (long)myuser->pw_gid);
 
 	return mygroup->gr_gid;
 }
diff --git a/libbb/obscure.c b/libbb/obscure.c
index 588ef5a..1a99b7c 100644
--- a/libbb/obscure.c
+++ b/libbb/obscure.c
@@ -143,7 +143,7 @@
 		return "too simple";
 
 	msg = NULL;
-	newmono = str_lower(xstrdup(newval));
+	newmono = str_lower(bb_xstrdup(newval));
 	lenwrap = strlen(old) * 2 + 1;
 	wrapped = (char *) xmalloc(lenwrap);
 	str_lower(strcpy(wrapped, old));
@@ -208,8 +208,8 @@
 	if (oldlen <= maxlen && newlen <= maxlen)
 		return NULL;
 
-	new1 = (char *) xstrdup(newval);
-	old1 = (char *) xstrdup(old);
+	new1 = (char *) bb_xstrdup(newval);
+	old1 = (char *) bb_xstrdup(old);
 	if (newlen > maxlen)
 		new1[maxlen] = '\0';
 	if (oldlen > maxlen)
diff --git a/libbb/parse_mode.c b/libbb/parse_mode.c
index ba34ea9..49573df 100644
--- a/libbb/parse_mode.c
+++ b/libbb/parse_mode.c
@@ -1,134 +1,177 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Utility routines.
+ * parse_mode implementation for busybox
  *
- * Copyright (C) many different people.  If you wrote this, please
- * acknowledge your work.
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 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
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
  */
 
-#include <stdio.h>
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */
+
 #include <stdlib.h>
+#include <assert.h>
+#include <sys/stat.h>
 #include "libbb.h"
 
+#define FILEMODEBITS    (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
 
-/* This function parses the sort of string you might pass
- * to chmod (i.e., [ugoa]{+|-|=}[rwxst] ) and returns the
- * correct mode described by the string. */
-extern int parse_mode(const char *s, mode_t * theMode)
+extern int bb_parse_mode(const char *s, mode_t *current_mode)
 {
-	static const mode_t group_set[] = { 
+	static const mode_t who_mask[] = { 
+		S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */
 		S_ISUID | S_IRWXU,		/* u */
 		S_ISGID | S_IRWXG,		/* g */
-		S_IRWXO,				/* o */
-		S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO /* a */
+		S_IRWXO					/* o */
 	};
 
-	static const mode_t mode_set[] = {
+	static const mode_t perm_mask[] = {
 		S_IRUSR | S_IRGRP | S_IROTH, /* r */
 		S_IWUSR | S_IWGRP | S_IWOTH, /* w */
 		S_IXUSR | S_IXGRP | S_IXOTH, /* x */
+		S_IXUSR | S_IXGRP | S_IXOTH, /* X -- special -- see below */
 		S_ISUID | S_ISGID,		/* s */
 		S_ISVTX					/* t */
 	};
 
-	static const char group_chars[] = "ugoa";
-	static const char mode_chars[] = "rwxst";
+	static const char who_chars[] = "augo";
+	static const char perm_chars[] = "rwxXst";
 
 	const char *p;
 
-	mode_t andMode =
-		S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
-	mode_t orMode = 0;
-	mode_t mode;
-	mode_t groups;
-	char type;
-	char c;
+	mode_t wholist;
+	mode_t permlist;
+	mode_t mask;
+	mode_t new_mode;
+	char op;
 
-	if (s==NULL) {
-		return (FALSE);
+	assert(s);
+
+	if (((unsigned int)(*s - '0')) < 8) {
+		unsigned long tmp;
+		char *e;
+
+		tmp = strtol(s, &e, 8);
+		if (*e || (tmp > 0xffffU)) { /* Check range and trailing chars. */
+			return 0;
+		}
+		*current_mode = tmp;
+		return 1;
 	}
 
-	do {
-		mode = 0;
-		groups = 0;
-	NEXT_GROUP:
-		if ((c = *s++) == '\0') {
-			return -1;
+	mask = umask(0);
+	umask(mask);
+
+	new_mode = *current_mode;
+
+	/* Note: We allow empty clauses, and hence empty modes.
+	 * We treat an empty mode as no change to perms. */
+
+	while (*s) {	/* Process clauses. */
+
+		if (*s == ',') {	/* We allow empty clauses. */
+			++s;
+			continue;
 		}
-		for (p=group_chars ; *p ; p++) {
-			if (*p == c) {
-				groups |= group_set[(int)(p-group_chars)];
-				goto NEXT_GROUP;
-			}
-		}
-		switch (c) {
-			case '=':
-			case '+':
-			case '-':
-				type = c;
-				if (groups == 0) { /* The default is "all" */
-					groups |= S_ISUID | S_ISGID | S_ISVTX
-							| S_IRWXU | S_IRWXG | S_IRWXO;
+
+		/* Get a wholist. */
+		wholist = 0;
+
+	WHO_LIST:
+		p = who_chars;
+		do {
+			if (*p == *s) {
+				wholist |= who_mask[(int)(p-who_chars)];
+				if (!*++s) {
+					return 0;
 				}
-				break;
-			default:
-				if ((c < '0') || (c > '7') || (mode | groups)) {
-					return (FALSE);
+				goto WHO_LIST;
+			}
+		} while (*++p);
+
+		do {	/* Process action list. */
+			if ((*s != '+') && (*s != '-')) {
+				if (*s != '=') {
+					return 0;
+				}
+				/* Since op is '=', clear all bits corresponding to the
+				 * wholist, of all file bits if wholist is empty. */
+				permlist = ~FILEMODEBITS;
+				if (wholist) {
+					permlist = ~wholist;
+				}
+				new_mode &= permlist;
+			}
+			op = *s++;
+
+			/* Check for permcopy. */
+			p = who_chars + 1;	/* Skip 'a' entry. */
+			do {
+				if (*p == *s) {
+					int i = 0;
+					permlist = who_mask[(int)(p-who_chars)]
+							 & (S_IRWXU | S_IRWXG | S_IRWXO)
+							 & new_mode;
+					do {
+						if (permlist & perm_mask[i]) {
+							permlist |= perm_mask[i];
+						}
+					} while (++i < 3);
+					++s;
+					goto GOT_ACTION;
+				}
+			} while (*++p);
+
+			/* It was not a permcopy, so get a permlist. */
+			permlist = 0;
+
+		PERM_LIST:
+			p = perm_chars;
+			do {
+				if (*p == *s) {
+					if ((*p != 'X')
+						|| (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH))
+					) {
+						permlist |= perm_mask[(int)(p-perm_chars)];
+					}
+					if (!*++s) {
+						break;
+					}
+					goto PERM_LIST;
+				}
+			} while (*++p);
+
+		GOT_ACTION:
+			if (permlist) {	/* The permlist was nonempty. */
+				mode_t tmp = ~mask;
+				if (wholist) {
+					tmp = wholist;
+				}
+				permlist &= tmp;
+
+				if (op == '-') {
+					new_mode &= ~permlist;
 				} else {
-					*theMode = strtol(--s, NULL, 8);
-					return (TRUE);
-				}
-		}
-
-	NEXT_MODE:
-		if (((c = *s++) != '\0') && (c != ',')) {
-			for (p=mode_chars ; *p ; p++) {
-				if (*p == c) {
-					mode |= mode_set[(int)(p-mode_chars)];
-					goto NEXT_MODE;
+					new_mode |= permlist;
 				}
 			}
-			break;				/* We're done so break out of loop.*/
-		}
-		switch (type) {
-			case '=':
-				andMode &= ~(groups); /* Now fall through. */
-			case '+':
-				orMode |= mode & groups;
-				break;
-			case '-':
-				andMode &= ~(mode & groups);
-				orMode &= ~(mode & groups);
-				break;
-		}
-	} while (c == ',');
+		} while (*s && (*s != ','));
+	}
 
-	*theMode &= andMode;
-	*theMode |= orMode;
+	*current_mode = new_mode;
 
-	return TRUE;
+	return 1;
 }
-
-/* END CODE */
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
diff --git a/libbb/parse_number.c b/libbb/parse_number.c
index 755a357..92ad6a2 100644
--- a/libbb/parse_number.c
+++ b/libbb/parse_number.c
@@ -1,70 +1,64 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Utility routines.
+ * bb_xparse_number implementation for busybox
  *
- * Copyright (C) many different people.  If you wrote this, please
- * acknowledge your work.
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 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
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
  */
 
-#include <stdio.h>
-#include <string.h>
 #include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+#include <assert.h>
 #include "libbb.h"
 
-
-unsigned long parse_number(const char *numstr,
-		const struct suffix_mult *suffixes)
+extern
+unsigned long bb_xparse_number(const char *numstr,
+							   const struct suffix_mult *suffixes)
 {
-	const struct suffix_mult *sm;
-	unsigned long int ret;
-	int len;
-	char *end;
+	unsigned long int r;
+	char *e;
+	int old_errno;
 	
-	ret = strtoul(numstr, &end, 10);
-	if (numstr == end)
-		error_msg_and_die("invalid number `%s'", numstr);
-	while (end[0] != '\0') {
-		sm = suffixes;
-		while ( sm != 0 ) {
-			if(sm->suffix) {
-				len = strlen(sm->suffix);
-				if (strncmp(sm->suffix, end, len) == 0) {
-					ret *= sm->mult;
-					end += len;
-					break;
-				}
-			sm++;
-			
-			} else
-				sm = 0;
+	/* Since this is a lib function, we're not allowed to reset errno to 0.
+	 * Doing so could break an app that is deferring checking of errno.
+	 * So, save the old value so that we can restore it if successful. */
+	old_errno = errno;
+	errno = 0;
+	r = strtoul(numstr, &e, 10);
+
+	if ((numstr != e) && !errno) {
+		errno = old_errno;	/* Ok.  So restore errno. */
+		if (!*e) {
+			return r;
 		}
-		if (sm == 0)
-			error_msg_and_die("invalid number `%s'", numstr);
+		if (suffixes) {
+			assert(suffixes->suffix);	/* No nul suffixes. */
+			do {
+				if (strcmp(suffixes->suffix, e) == 0) {
+					if (ULONG_MAX / suffixes->mult < r) {	/* Overflow! */
+						break;
+					}
+					return r * suffixes->mult;
+				}
+				++suffixes;
+			} while (suffixes->suffix);
+		}
 	}
-	return ret;
+	bb_error_msg_and_die("invalid number `%s'", numstr);
 }
-
-
-/* END CODE */
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
diff --git a/libbb/perror_msg.c b/libbb/perror_msg.c
index 8c57b0d..f32c1c8 100644
--- a/libbb/perror_msg.c
+++ b/libbb/perror_msg.c
@@ -25,12 +25,12 @@
 #include <stdlib.h>
 #include "libbb.h"
 
-extern void perror_msg(const char *s, ...)
+extern void bb_perror_msg(const char *s, ...)
 {
 	va_list p;
 
 	va_start(p, s);
-	vperror_msg(s, p);
+	bb_vperror_msg(s, p);
 	va_end(p);
 }
 
diff --git a/libbb/perror_msg_and_die.c b/libbb/perror_msg_and_die.c
index 9004925..57a2113 100644
--- a/libbb/perror_msg_and_die.c
+++ b/libbb/perror_msg_and_die.c
@@ -25,14 +25,14 @@
 #include <stdlib.h>
 #include "libbb.h"
 
-extern void perror_msg_and_die(const char *s, ...)
+extern void bb_perror_msg_and_die(const char *s, ...)
 {
 	va_list p;
 
 	va_start(p, s);
-	vperror_msg(s, p);
+	bb_vperror_msg(s, p);
 	va_end(p);
-	exit(EXIT_FAILURE);
+	exit(bb_default_error_retval);
 }
 
 
diff --git a/libbb/perror_nomsg.c b/libbb/perror_nomsg.c
new file mode 100644
index 0000000..464cb86
--- /dev/null
+++ b/libbb/perror_nomsg.c
@@ -0,0 +1,30 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_perror_nomsg implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stddef.h>
+#include <libbb.h>
+
+extern void bb_perror_nomsg(void)
+{
+	/* Ignore the gcc warning about a null format string. */
+	bb_perror_msg(NULL);
+}
diff --git a/libbb/perror_nomsg_and_die.c b/libbb/perror_nomsg_and_die.c
new file mode 100644
index 0000000..bab2284
--- /dev/null
+++ b/libbb/perror_nomsg_and_die.c
@@ -0,0 +1,30 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_perror_nomsg_and_die implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stddef.h>
+#include "libbb.h"
+
+extern void bb_perror_nomsg_and_die(void)
+{
+	/* Ignore the gcc warning about a null format string. */
+	bb_perror_msg_and_die(NULL);
+}
diff --git a/libbb/print_file.c b/libbb/print_file.c
index cdd60e7..8417c10 100644
--- a/libbb/print_file.c
+++ b/libbb/print_file.c
@@ -21,39 +21,50 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/stat.h>
 #include "libbb.h"
 
-
-extern void print_file(FILE *file)
+extern void bb_xprint_and_close_file(FILE *file)
 {
-	fflush(stdout);
-	if (copyfd(fileno(file), fileno(stdout), 0) == -1) {
-		exit(EXIT_FAILURE);
+	bb_xfflush_stdout();
+	/* Note: Do not use STDOUT_FILENO here, as this is a lib routine
+	 *       and the calling code may have reassigned stdout. */
+	if (bb_copyfd(fileno(file), fileno(stdout), 0) == -1) {
+		/* bb_copyfd outputs any needed messages, so just die. */
+		exit(bb_default_error_retval);
 	}
+	/* Note: Since we're reading, don't bother checking the return value
+	 *       of fclose().  The only possible failure is EINTR which
+	 *       should already have been taken care of. */
 	fclose(file);
 }
 
-extern int print_file_by_name(char *filename)
-{
-	struct stat statBuf;
-	int status = TRUE;
+/* Returns:
+ *    0      if successful
+ *   -1      if 'filename' does not exist or is a directory
+ *  exits with default error code if an error occurs
+ */
 
-	if(is_directory(filename, TRUE, &statBuf)==TRUE) {
-		error_msg("%s: Is directory", filename);
-		status = FALSE;
-	} else {
-		FILE *f = wfopen(filename, "r");
-		if(f!=NULL)
-			print_file(f);
-		else
-			status = FALSE;
+extern int bb_xprint_file_by_name(const char *filename)
+{
+	FILE *f;
+
+#if 0
+	/* This check shouldn't be necessary for linux, but is left
+	* here disabled just in case. */
+	struct stat statBuf;
+
+	if(is_directory(filename, TRUE, &statBuf)) {
+		bb_error_msg("%s: Is directory", filename);
+	} else
+#endif
+	if ((f = bb_wfopen(filename, "r")) != NULL) {
+		bb_xprint_and_close_file(f);
+		return 0;
 	}
 
-	return status;
+	return -1;
 }
 
-
 /* END CODE */
 /*
 Local Variables:
diff --git a/libbb/printf.c b/libbb/printf.c
new file mode 100644
index 0000000..6862576
--- /dev/null
+++ b/libbb/printf.c
@@ -0,0 +1,177 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * *printf implementations for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Mar 12, 2003     Manuel Novoa III
+ *
+ * While fwrite(), fputc(), fputs(), etc. all set the stream error flag
+ * on failure, the *printf functions are unique in that they can fail
+ * for reasons not related to the actual output itself.  Among the possible
+ * reasons for failure which don't set the streams error indicator,
+ * SUSv3 lists EILSEQ, EINVAL, and ENOMEM.
+ *
+ * In some cases, it would be desireable to have a group of *printf()
+ * functions available that _always_ set the stream error indicator on
+ * failure.  That would allow us to defer error checking until applet
+ * exit.  Unfortunately, there is no standard way of setting a streams
+ * error indicator... even though we can clear it with clearerr().
+ *
+ * Therefore, we have to resort to implementation dependent code.  Feel
+ * free to send patches for stdio implementations where the following
+ * fails.
+ *
+ * NOTE: None of this is threadsafe.  As busybox is a nonthreaded app,
+ *       that isn't currently an issue.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "libbb.h"
+
+#if defined(__UCLIBC__) 
+
+# if defined(__FLAG_ERROR)
+/* Using my newer stdio implementation.  Unlocked macros are:
+ * #define __CLEARERR(stream) \
+	  ((stream)->modeflags &= ~(__FLAG_EOF|__FLAG_ERROR), (void)0)
+ * #define __FEOF(stream)		((stream)->modeflags & __FLAG_EOF)
+ * #define __FERROR(stream)	((stream)->modeflags & __FLAG_ERROR)
+ */
+#define SET_FERROR_UNLOCKED(S)    ((S)->modeflags |= __FLAG_ERROR)
+
+#elif defined(__MODE_ERR)
+/* Using either the original stdio implementation (from dev86) or
+ * my original stdio rewrite.  Macros were:
+ * #define ferror(fp)	(((fp)->mode&__MODE_ERR) != 0)
+ * #define feof(fp)   	(((fp)->mode&__MODE_EOF) != 0)
+ * #define clearerr(fp)	((fp)->mode &= ~(__MODE_EOF|__MODE_ERR),0)
+ */
+#define SET_FERROR_UNLOCKED(S)    ((S)->mode |= __MODE_ERR)
+
+#else
+#error unknown uClibc stdio implemenation!
+#endif
+
+#elif defined(__GLIBC__)
+
+# if defined(_STDIO_USES_IOSTREAM)
+/* Apparently using the newer libio implementation, with associated defines:
+ * #define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0)
+ * #define _IO_ferror_unlocked(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0)
+ */
+#define SET_FERROR_UNLOCKED(S)    ((S)->_flags |= _IO_ERR_SEEN)
+
+# else
+/* Assume the older version of glibc which used a bitfield entry
+ * as a stream error flag.  The associated defines were:
+ * #define __clearerr(stream)      ((stream)->__error = (stream)->__eof = 0)
+ * #define feof_unlocked(stream)         ((stream)->__eof != 0)
+ * #define ferror_unlocked(stream)       ((stream)->__error != 0)
+ */
+#define SET_FERROR_UNLOCKED(S)    ((S)->__error = 1)
+
+# endif
+
+#elif defined(__NEWLIB_H__)
+/* I honestly don't know if there are different versions of stdio in
+ * newlibs history.  Anyway, here's what's current.
+ * #define __sfeof(p)      (((p)->_flags & __SEOF) != 0)
+ * #define __sferror(p)    (((p)->_flags & __SERR) != 0)
+ * #define __sclearerr(p)  ((void)((p)->_flags &= ~(__SERR|__SEOF)))
+ */
+#define SET_FERROR_UNLOCKED(S)    ((S)->_flags |= __SERR)
+
+#elif defined(__dietlibc__)
+/*
+ *     WARNING!!!  dietlibc is quite buggy.  WARNING!!!
+ *
+ * Some example bugs as of March 12, 2003...
+ *   1) fputc() doesn't set the error indicator on failure.
+ *   2) freopen() doesn't maintain the same stream object, contary to
+ *      standards.  This makes it useless in its primary role of
+ *      reassociating stdin/stdout/stderr.
+ *   3) printf() often fails to correctly format output when conversions
+ *      involve padding.  It is also practically useless for floating
+ *      point output.
+ *
+ * But, if you're determined to use it anyway, (as of the current version)
+ * you can extract the information you need from dietstdio.h.  See the
+ * other library implementations for examples.
+ */
+#error dietlibc is currently not supported.  Please see the commented source.
+
+#else /* some other lib */
+/* Please see the comments for the above supported libaries for examples
+ * of what is required to support your stdio implementation.
+ */
+#error Your stdio library is currently not supported.  Please see the commented source.
+#endif
+
+#ifdef L_vfprintf
+extern int bb_vfprintf(FILE * __restrict stream,
+					   const char * __restrict format,
+					   va_list arg)
+{
+	int rv;
+
+	if ((rv = vfprintf(stream, format, arg)) < 0) {
+		SET_FERROR_UNLOCKED(stream);
+	}
+
+	return rv;
+}
+#endif
+
+#ifdef L_vprintf
+extern int bb_vprintf(const char * __restrict format, va_list arg)
+{
+	return bb_vfprintf(stdout, format, arg);
+}
+#endif
+
+#ifdef L_fprintf
+extern int bb_fprintf(FILE * __restrict stream,
+					  const char * __restrict format, ...)
+{
+	va_list arg;
+	int rv;
+
+	va_start(arg, format);
+	rv = bb_vfprintf(stream, format, arg);
+	va_end(arg);
+
+	return rv;
+}
+#endif
+
+#ifdef L_printf
+extern int bb_printf(const char * __restrict format, ...)
+{
+	va_list arg;
+	int rv;
+
+	va_start(arg, format);
+	rv = bb_vfprintf(stdout, format, arg);
+	va_end(arg);
+
+	return rv;
+}
+#endif
diff --git a/libbb/process_escape_sequence.c b/libbb/process_escape_sequence.c
index 9a16f80..ef2717b 100644
--- a/libbb/process_escape_sequence.c
+++ b/libbb/process_escape_sequence.c
@@ -2,7 +2,7 @@
 /*
  * Utility routines.
  *
- * Copyright (C) Manuel Nova III <mnovoa3@bellsouth.net>
+ * Copyright (C) Manuel Novoa III <mjn3@codepoet.org>
  * and Vladimir Oleynik <dzo@simtreas.ru>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -26,9 +26,7 @@
 #include <limits.h>
 #include "libbb.h"
 
-
-
-char process_escape_sequence(const char **ptr)
+char bb_process_escape_sequence(const char **ptr)
 {
 	static const char charmap[] = {
 		'a',  'b',  'f',  'n',  'r',  't',  'v',  '\\', 0,
@@ -36,40 +34,43 @@
 
 	const char *p;
 	const char *q;
-	int num_digits;
+	unsigned int num_digits;
+	unsigned int r;
 	unsigned int n;
 	
 	n = 0;
 	q = *ptr;
 
-	for ( num_digits = 0 ; num_digits < 3 ; ++num_digits) {
-		if ((*q < '0') || (*q > '7')) { /* not a digit? */
-			break;
+	num_digits = 0;
+	do {
+		if (((unsigned int)(*q - '0')) <= 7) {
+			r = n * 8 + (*q - '0');
+			if (r <= UCHAR_MAX) {
+				n = r;
+				++q;
+				if (++num_digits < 3) {
+					continue;
+				}
+			}
 		}
-		n = n * 8 + (*q++ - '0');
-	}
+		break;
+	} while (1);
 
 	if (num_digits == 0) {	/* mnemonic escape sequence? */
-		for (p=charmap ; *p ; p++) {
+		p = charmap;
+		do {
 			if (*p == *q) {
 				q++;
 				break;
 			}
-		}
+		} while (*++p);
 		n = *(p+(sizeof(charmap)/2));
 	}
 
-	   /* doesn't hurt to fall through to here from mnemonic case */
-	if (n > UCHAR_MAX) {	/* is octal code too big for a char? */
-		n /= 8;			/* adjust value and */
-		--q;				/* back up one char */
-	}
-
 	*ptr = q;
 	return (char) n;
 }
 
-
 /* END CODE */
 /*
 Local Variables:
diff --git a/libbb/procps.c b/libbb/procps.c
index fcc9c2d..a513f3f 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -34,7 +34,7 @@
 	if (!dir) {
 		dir = opendir("/proc");
 		if(!dir)
-			error_msg_and_die("Can't open /proc");
+			bb_error_msg_and_die("Can't open /proc");
 	}
 	for(;;) {
 		if((entry = readdir(dir)) == NULL) {
diff --git a/libbb/read_package_field.c b/libbb/read_package_field.c
index 867b198..42628f3 100644
--- a/libbb/read_package_field.c
+++ b/libbb/read_package_field.c
@@ -102,10 +102,10 @@
 	if (name_length == 0) {
 		*field_name = NULL;
 	} else {
-		*field_name = xstrndup(&package_buffer[offset_name_start], name_length);
+		*field_name = bb_xstrndup(&package_buffer[offset_name_start], name_length);
 	}
 	if (value_length > 0) {
-		*field_value = xstrndup(&package_buffer[offset_value_start], value_length);
+		*field_value = bb_xstrndup(&package_buffer[offset_value_start], value_length);
 	} else {
 		*field_value = NULL;
 	}
diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c
index 8f9cc2f..a4a4a7b 100644
--- a/libbb/recursive_action.c
+++ b/libbb/recursive_action.c
@@ -60,10 +60,10 @@
 
 	if (status < 0) {
 #ifdef DEBUG_RECURS_ACTION
-		error_msg("status=%d followLinks=%d TRUE=%d",
+		bb_error_msg("status=%d followLinks=%d TRUE=%d",
 				status, followLinks, TRUE);
 #endif
-		perror_msg("%s", fileName);
+		bb_perror_msg("%s", fileName);
 		return FALSE;
 	}
 
@@ -89,14 +89,14 @@
 		if (dirAction != NULL && ! depthFirst) {
 			status = dirAction(fileName, &statbuf, userData);
 			if (! status) {
-				perror_msg("%s", fileName);
+				bb_perror_msg("%s", fileName);
 				return FALSE;
 			} else if (status == SKIP)
 				return TRUE;
 		}
 		dir = opendir(fileName);
 		if (!dir) {
-			perror_msg("%s", fileName);
+			bb_perror_msg("%s", fileName);
 			return FALSE;
 		}
 		status = TRUE;
@@ -117,7 +117,7 @@
 		closedir(dir);
 		if (dirAction != NULL && depthFirst) {
 			if (! dirAction(fileName, &statbuf, userData)) {
-				perror_msg("%s", fileName);
+				bb_perror_msg("%s", fileName);
 				return FALSE;
 			}
 		}
diff --git a/libbb/remove_file.c b/libbb/remove_file.c
index 988b091..65708a2 100644
--- a/libbb/remove_file.c
+++ b/libbb/remove_file.c
@@ -37,7 +37,7 @@
 
 	if (lstat(path, &path_stat) < 0) {
 		if (errno != ENOENT) {
-			perror_msg("unable to stat `%s'", path);
+			bb_perror_msg("unable to stat `%s'", path);
 			return -1;
 		}
 
@@ -46,7 +46,7 @@
 
 	if (!path_exists) {
 		if (!(flags & FILEUTILS_FORCE)) {
-			perror_msg("cannot remove `%s'", path);
+			bb_perror_msg("cannot remove `%s'", path);
 			return -1;
 		}
 		return 0;
@@ -58,21 +58,21 @@
 		int status = 0;
 
 		if (!(flags & FILEUTILS_RECUR)) {
-			error_msg("%s: is a directory", path);
+			bb_error_msg("%s: is a directory", path);
 			return -1;
 		}
 
 		if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 &&
 					isatty(0)) ||
 				(flags & FILEUTILS_INTERACTIVE)) {
-			fprintf(stderr, "%s: descend into directory `%s'? ", applet_name,
+			fprintf(stderr, "%s: descend into directory `%s'? ", bb_applet_name,
 					path);
-			if (!ask_confirmation())
+			if (!bb_ask_confirmation())
 				return 0;
 		}
 
 		if ((dp = opendir(path)) == NULL) {
-			perror_msg("unable to open `%s'", path);
+			bb_perror_msg("unable to open `%s'", path);
 			return -1;
 		}
 
@@ -90,18 +90,18 @@
 		}
 
 		if (closedir(dp) < 0) {
-			perror_msg("unable to close `%s'", path);
+			bb_perror_msg("unable to close `%s'", path);
 			return -1;
 		}
 
 		if (flags & FILEUTILS_INTERACTIVE) {
-			fprintf(stderr, "%s: remove directory `%s'? ", applet_name, path);
-			if (!ask_confirmation())
+			fprintf(stderr, "%s: remove directory `%s'? ", bb_applet_name, path);
+			if (!bb_ask_confirmation())
 				return status;
 		}
 
 		if (rmdir(path) < 0) {
-			perror_msg("unable to remove `%s'", path);
+			bb_perror_msg("unable to remove `%s'", path);
 			return -1;
 		}
 
@@ -111,13 +111,13 @@
 					!S_ISLNK(path_stat.st_mode) &&
 					isatty(0)) ||
 				(flags & FILEUTILS_INTERACTIVE)) {
-			fprintf(stderr, "%s: remove `%s'? ", applet_name, path);
-			if (!ask_confirmation())
+			fprintf(stderr, "%s: remove `%s'? ", bb_applet_name, path);
+			if (!bb_ask_confirmation())
 				return 0;
 		}
 
 		if (unlink(path) < 0) {
-			perror_msg("unable to remove `%s'", path);
+			bb_perror_msg("unable to remove `%s'", path);
 			return -1;
 		}
 
diff --git a/libbb/run_parts.c b/libbb/run_parts.c
index 7829a84..5864566 100644
--- a/libbb/run_parts.c
+++ b/libbb/run_parts.c
@@ -69,7 +69,7 @@
 		if (test_mode & 2) {
 			return(2);
 		}
-		perror_msg_and_die("failed to open directory %s", arg0);
+		bb_perror_msg_and_die("failed to open directory %s", arg0);
 	}
 
 	for (i = 0; i < entries; i++) {
@@ -77,7 +77,7 @@
 		filename = concat_path_file(arg0, namelist[i]->d_name);
 
 		if (stat(filename, &st) < 0) {
-			perror_msg_and_die("failed to stat component %s", filename);
+			bb_perror_msg_and_die("failed to stat component %s", filename);
 		}
 		if (S_ISREG(st.st_mode) && !access(filename, X_OK)) {
 			if (test_mode & 1) {
@@ -89,7 +89,7 @@
 				int pid;
 
 				if ((pid = vfork()) < 0) {
-					perror_msg_and_die("failed to fork");
+					bb_perror_msg_and_die("failed to fork");
 				} else if (!pid) {
 					args[0] = filename;
 					execv(filename, args);
@@ -100,19 +100,19 @@
 				waitpid(pid, &result, 0);
 				if(exec_errno) {
 					errno = exec_errno;
-					perror_msg_and_die("failed to exec %s", filename);
+					bb_perror_msg_and_die("failed to exec %s", filename);
 				}
 				if (WIFEXITED(result) && WEXITSTATUS(result)) {
-					perror_msg("%s exited with return code %d", filename, WEXITSTATUS(result));
+					bb_perror_msg("%s exited with return code %d", filename, WEXITSTATUS(result));
 					exitstatus = 1;
 				} else if (WIFSIGNALED(result)) {
-					perror_msg("%s exited because of uncaught signal %d", filename, WTERMSIG(result));
+					bb_perror_msg("%s exited because of uncaught signal %d", filename, WTERMSIG(result));
 					exitstatus = 1;
 				}
 			}
 		} 
 		else if (!S_ISDIR(st.st_mode)) {
-			error_msg("component %s is not an executable plain file", filename);
+			bb_error_msg("component %s is not an executable plain file", filename);
 			exitstatus = 1;
 		}
 
diff --git a/libbb/run_shell.c b/libbb/run_shell.c
index b26eba1..d154b98 100644
--- a/libbb/run_shell.c
+++ b/libbb/run_shell.c
@@ -57,11 +57,11 @@
 	else
 		args = (const char **) xmalloc (sizeof (char *) * 4 );
 		
-	args [0] = get_last_path_component ( xstrdup ( shell ));
+	args [0] = bb_get_last_path_component ( bb_xstrdup ( shell ));
 	
 	if ( loginshell ) {
 		char *args0;
-		bb_asprintf ( &args0, "-%s", args [0] );
+		bb_xasprintf ( &args0, "-%s", args [0] );
 		args [0] = args0;
 	}
     
@@ -75,6 +75,6 @@
 	}
 	args [argno] = 0;
 	execv ( shell, (char **) args );
-	perror_msg_and_die ( "cannot run %s", shell );
+	bb_perror_msg_and_die ( "cannot run %s", shell );
 }
 
diff --git a/libbb/setup_environment.c b/libbb/setup_environment.c
index dc171fa..30d317c 100644
--- a/libbb/setup_environment.c
+++ b/libbb/setup_environment.c
@@ -45,7 +45,7 @@
 static void xsetenv ( const char *key, const char *value )
 {
 	    if ( setenv ( key, value, 1 ))
-			        error_msg_and_die ( "out of memory" );
+			        bb_error_msg_and_die ( "out of memory" );
 }
 
 void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw )
@@ -62,7 +62,7 @@
 		if ( chdir ( pw-> pw_dir )) {
 			if ( chdir ( "/" )) {
 				syslog ( LOG_WARNING, "unable to cd to %s' for user %s'\n", pw-> pw_dir, pw-> pw_name );
-				error_msg_and_die ( "cannot cd to home directory or /" );
+				bb_error_msg_and_die ( "cannot cd to home directory or /" );
 			}
 			fputs ( "warning: cannot change to home directory\n", stderr );
 		}
diff --git a/libbb/simplify_path.c b/libbb/simplify_path.c
index 7b2a1ca..743133c 100644
--- a/libbb/simplify_path.c
+++ b/libbb/simplify_path.c
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * simplify_path implementation for busybox
+ * bb_simplify_path implementation for busybox
  *
- * Copyright (C) 2001  Manuel Novoa III  <mjn3@opensource.lineo.com>
+ * Copyright (C) 2001  Manuel Novoa III  <mjn3@codepoet.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,15 +21,14 @@
  */
 
 #include <stdlib.h>
-
 #include "libbb.h"
 
-char *simplify_path(const char *path)
+char *bb_simplify_path(const char *path)
 {
 	char *s, *start, *p;
 
 	if (path[0] == '/')
-		start = xstrdup(path);
+		start = bb_xstrdup(path);
 	else {
 		s = xgetcwd(NULL);
 		start = concat_path_file(s, path);
diff --git a/libbb/skip_whitespace.c b/libbb/skip_whitespace.c
new file mode 100644
index 0000000..bf049a2
--- /dev/null
+++ b/libbb/skip_whitespace.c
@@ -0,0 +1,33 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * skip_whitespace implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <ctype.h>
+#include "libbb.h"
+
+extern const char *bb_skip_whitespace(const char *s)
+{
+	while (isspace(*s)) {
+		++s;
+	}
+
+	return s;
+}
diff --git a/libbb/speed_table.c b/libbb/speed_table.c
new file mode 100644
index 0000000..b04429e
--- /dev/null
+++ b/libbb/speed_table.c
@@ -0,0 +1,130 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * compact speed_t <-> speed functions for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <termios.h>
+#include "libbb.h"
+
+struct speed_map {
+	unsigned short speed;
+	unsigned short value;
+};
+
+static const struct speed_map speeds[] = {
+	{B0, 0},
+	{B50, 50},
+	{B75, 75},
+	{B110, 110},
+	{B134, 134},
+	{B150, 150},
+	{B200, 200},
+	{B300, 300},
+	{B600, 600},
+	{B1200, 1200},
+	{B1800, 1800},
+	{B2400, 2400},
+	{B4800, 4800},
+	{B9600, 9600},
+#ifdef	B19200
+	{B19200, 19200},
+#elif defined(EXTA)
+	{EXTA, 19200},
+#endif
+#ifdef	B38400
+	{B38400, 38400/256 + 0x8000U},
+#elif defined(EXTB)
+	{EXTB, 38400/256 + 0x8000U},
+#endif
+#ifdef B57600
+	{B57600, 57600/256 + 0x8000U},
+#endif
+#ifdef B115200
+	{B115200, 115200/256 + 0x8000U},
+#endif
+#ifdef B230400
+	{B230400, 230400/256 + 0x8000U},
+#endif
+#ifdef B460800
+	{B460800, 460800/256 + 0x8000U},
+#endif
+};
+
+static const int NUM_SPEEDS = (sizeof(speeds) / sizeof(struct speed_map));
+
+unsigned long bb_baud_to_value(speed_t speed)
+{
+	int i = 0;
+
+	do {
+		if (speed == speeds[i].speed) {
+			if (speeds[i].value & 0x8000U) {
+				return ((unsigned long) (speeds[i].value) & 0x7fffU) * 256;
+			}
+			return speeds[i].value;
+		}
+	} while (++i < NUM_SPEEDS);
+
+	return 0;
+}
+
+speed_t bb_value_to_baud(unsigned long value)
+{
+	int i = 0;
+
+	do {
+		if (value == bb_baud_to_value(speeds[i].speed)) {
+			return speeds[i].speed;
+		}
+	} while (++i < NUM_SPEEDS);
+
+	return (speed_t) - 1;
+}
+
+#if 0
+/* testing code */
+#include <stdio.h>
+
+int main(void)
+{
+	unsigned long v;
+	speed_t s;
+
+	for (v = 0 ; v < 500000 ; v++) {
+		s = bb_value_to_baud(v);
+		if (s == (speed_t) -1) {
+			continue;
+		}
+		printf("v = %lu -- s = %0lo\n", v, (unsigned long) s);
+	}
+
+	printf("-------------------------------\n");
+
+	for (s = 0 ; s < 010017+1 ; s++) {
+		v = bb_baud_to_value(s);
+		if (!v) {
+			continue;
+		}
+		printf("v = %lu -- s = %0lo\n", v, (unsigned long) s);
+	}
+
+	return 0;
+}
+#endif
diff --git a/libbb/syscalls.c b/libbb/syscalls.c
index 91e97b1..8d8c689 100644
--- a/libbb/syscalls.c
+++ b/libbb/syscalls.c
@@ -53,7 +53,7 @@
 	 *  you will need to recompile with a kernel supporting the
 	 *  pivot_root system call.
 	 */
-	error_msg("\n\nTo make this application work, you will need to recompile\n"
+	bb_error_msg("\n\nTo make this application work, you will need to recompile\n"
 		"with a kernel supporting the pivot_root system call. -Erik\n");
 	errno=ENOSYS;
 	return -1;
@@ -91,7 +91,7 @@
 	 *  you will need to recompile with a kernel supporting the
 	 *  umount2 system call.
 	 */
-	error_msg("\n\nTo make this application work, you will need to recompile\n"
+	bb_error_msg("\n\nTo make this application work, you will need to recompile\n"
 		"with a kernel supporting the umount2 system call. -Erik\n");
 	errno=ENOSYS;
 	return -1;
diff --git a/libbb/syslog_msg_with_name.c b/libbb/syslog_msg_with_name.c
index 6474da4..bd3f448 100644
--- a/libbb/syslog_msg_with_name.c
+++ b/libbb/syslog_msg_with_name.c
@@ -32,7 +32,7 @@
 
 void syslog_msg(int facility, int pri, const char *msg)
 {
- 	syslog_msg_with_name(applet_name, facility, pri, msg);
+ 	syslog_msg_with_name(bb_applet_name, facility, pri, msg);
 }
 
 /* END CODE */
diff --git a/libbb/time_string.c b/libbb/time_string.c
deleted file mode 100644
index d103a02..0000000
--- a/libbb/time_string.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Utility routines.
- *
- * Copyright (C) 1999,2000,2001 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 <string.h>
-#include <time.h>
-#include <utime.h>
-#include "libbb.h"
-
-
-/*
- * Return the standard ls-like time string from a time_t
- * This is static and so is overwritten on each call.
- */
-const char *time_string(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;
-}
-
-
-/* END CODE */
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c
index 21cde20..4612bf3 100644
--- a/libbb/verror_msg.c
+++ b/libbb/verror_msg.c
@@ -25,10 +25,10 @@
 #include <stdlib.h>
 #include "libbb.h"
 
-extern void verror_msg(const char *s, va_list p)
+extern void bb_verror_msg(const char *s, va_list p)
 {
 	fflush(stdout);
-	fprintf(stderr, "%s: ", applet_name);
+	fprintf(stderr, "%s: ", bb_applet_name);
 	vfprintf(stderr, s, p);
 }
 
diff --git a/libbb/vherror_msg.c b/libbb/vherror_msg.c
index 67db17f..eb341bf 100644
--- a/libbb/vherror_msg.c
+++ b/libbb/vherror_msg.c
@@ -26,11 +26,11 @@
 #include "libbb.h"
 
 
-extern void vherror_msg(const char *s, va_list p)
+extern void bb_vherror_msg(const char *s, va_list p)
 {
 	if(s == 0)
 		s = "";
-	verror_msg(s, p);
+	bb_verror_msg(s, p);
 	if (*s)
 		fputs(": ", stderr);
 	herror("");
diff --git a/libbb/vperror_msg.c b/libbb/vperror_msg.c
index 7da5bae..febe4e2 100644
--- a/libbb/vperror_msg.c
+++ b/libbb/vperror_msg.c
@@ -25,11 +25,11 @@
 #include <stdlib.h>
 #include "libbb.h"
 
-extern void vperror_msg(const char *s, va_list p)
+extern void bb_vperror_msg(const char *s, va_list p)
 {
 	int err=errno;
 	if(s == 0) s = "";
-	verror_msg(s, p);
+	bb_verror_msg(s, p);
 	if (*s) s = ": ";
 	fprintf(stderr, "%s%s\n", s, strerror(err));
 }
diff --git a/libbb/warn_ignoring_args.c b/libbb/warn_ignoring_args.c
new file mode 100644
index 0000000..223831f
--- /dev/null
+++ b/libbb/warn_ignoring_args.c
@@ -0,0 +1,30 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * warn_ingoring_args implementations for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <libbb.h>
+
+extern void bb_warn_ignoring_args(int n)
+{
+	if (n) {
+		bb_perror_msg("ignoring all arguments");
+	}
+}
diff --git a/libbb/wfopen.c b/libbb/wfopen.c
index f58ec90..22f22b3 100644
--- a/libbb/wfopen.c
+++ b/libbb/wfopen.c
@@ -23,11 +23,11 @@
 #include <errno.h>
 #include "libbb.h"
 
-FILE *wfopen(const char *path, const char *mode)
+FILE *bb_wfopen(const char *path, const char *mode)
 {
 	FILE *fp;
 	if ((fp = fopen(path, mode)) == NULL) {
-		perror_msg("%s", path);
+		bb_perror_msg("%s", path);
 		errno = 0;
 	}
 	return fp;
diff --git a/libbb/wfopen_input.c b/libbb/wfopen_input.c
new file mode 100644
index 0000000..bff6606
--- /dev/null
+++ b/libbb/wfopen_input.c
@@ -0,0 +1,54 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * wfopen_input implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* A number of applets need to open a file for reading, where the filename
+ * is a command line arg.  Since often that arg is '-' (meaning stdin),
+ * we avoid testing everywhere by consolidating things in this routine.
+ *
+ * Note: We also consider "" to main stdin (for 'cmp' at least).
+ */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <libbb.h>
+
+FILE *bb_wfopen_input(const char *filename)
+{
+	FILE *fp = stdin;
+
+	if ((filename != bb_msg_standard_input)
+		&& filename[0] && ((filename[0] != '-') || filename[1])
+	) {
+#if 0
+		/* This check shouldn't be necessary for linux, but is left
+		 * here disabled just in case. */
+		struct stat stat_buf;
+		if (is_directory(filename, 1, &stat_buf)) {
+			bb_error_msg("%s: Is a directory", filename);
+			return NULL;
+		}
+#endif
+		fp = bb_wfopen(filename, "r");
+	}
+
+	return fp;
+}
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
index bc6505a..2945d76 100644
--- a/libbb/xconnect.c
+++ b/libbb/xconnect.c
@@ -30,7 +30,7 @@
 	hints.ai_socktype = SOCK_STREAM;
 	error = getaddrinfo(host, port, &hints, &res);
 	if (error||!res)
-		perror_msg_and_die(gai_strerror(error));
+		bb_perror_msg_and_die(gai_strerror(error));
 	addr_info=res;
 	while (res) {
 		s=socket(res->ai_family, res->ai_socktype, res->ai_protocol);
@@ -50,7 +50,7 @@
 	freeaddrinfo(addr_info);
 	if (error < 0)
 	{
-		perror_msg_and_die("Unable to connect to remote host (%s)", host);
+		bb_perror_msg_and_die("Unable to connect to remote host (%s)", host);
 	}
 	return s;
 #else
@@ -72,7 +72,7 @@
 
 	if (connect(s, (struct sockaddr *)&s_addr, sizeof s_addr) < 0)
 	{
-		perror_msg_and_die("Unable to connect to remote host (%s)", host);
+		bb_perror_msg_and_die("Unable to connect to remote host (%s)", host);
 	}
 	return s;
 #endif
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 820a0d7..43e8aef 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -30,31 +30,38 @@
 
 
 #ifndef DMALLOC
+#ifdef L_xmalloc
 extern void *xmalloc(size_t size)
 {
 	void *ptr = malloc(size);
 	if (ptr == NULL && size != 0)
-		error_msg_and_die(memory_exhausted);
+		bb_error_msg_and_die(bb_msg_memory_exhausted);
 	return ptr;
 }
+#endif
 
+#ifdef L_xrealloc
 extern void *xrealloc(void *ptr, size_t size)
 {
 	ptr = realloc(ptr, size);
 	if (ptr == NULL && size != 0)
-		error_msg_and_die(memory_exhausted);
+		bb_error_msg_and_die(bb_msg_memory_exhausted);
 	return ptr;
 }
+#endif
 
+#ifdef L_xcalloc
 extern void *xcalloc(size_t nmemb, size_t size)
 {
 	void *ptr = calloc(nmemb, size);
 	if (ptr == NULL && nmemb != 0 && size != 0)
-		error_msg_and_die(memory_exhausted);
+		bb_error_msg_and_die(bb_msg_memory_exhausted);
 	return ptr;
 }
+#endif
 
-extern char * xstrdup (const char *s) {
+#ifdef L_xstrdup
+extern char * bb_xstrdup (const char *s) {
 	char *t;
 
 	if (s == NULL)
@@ -63,79 +70,121 @@
 	t = strdup (s);
 
 	if (t == NULL)
-		error_msg_and_die(memory_exhausted);
+		bb_error_msg_and_die(bb_msg_memory_exhausted);
 
 	return t;
 }
 #endif
+#endif /* DMALLOC */
 
-extern char * xstrndup (const char *s, int n) {
+#ifdef L_xstrndup
+extern char * bb_xstrndup (const char *s, int n) {
 	char *t;
 
 	if (s == NULL)
-		error_msg_and_die("xstrndup bug");
+		bb_error_msg_and_die("bb_xstrndup bug");
 
 	t = xmalloc(++n);
 	
 	return safe_strncpy(t,s,n);
 }
+#endif
 
-FILE *xfopen(const char *path, const char *mode)
+#ifdef L_xfopen
+FILE *bb_xfopen(const char *path, const char *mode)
 {
 	FILE *fp;
 	if ((fp = fopen(path, mode)) == NULL)
-		perror_msg_and_die("%s", path);
+		bb_perror_msg_and_die("%s", path);
 	return fp;
 }
+#endif
 
-extern int xopen(const char *pathname, int flags)
+#ifdef L_xopen
+extern int bb_xopen(const char *pathname, int flags)
 {
 	int ret;
 	
 	ret = open(pathname, flags, 0777);
 	if (ret == -1) {
-		perror_msg_and_die("%s", pathname);
+		bb_perror_msg_and_die("%s", pathname);
 	}
 	return ret;
 }
+#endif
 
-extern ssize_t xread(int fd, void *buf, size_t count)
+#ifdef L_xread
+extern ssize_t bb_xread(int fd, void *buf, size_t count)
 {
 	ssize_t size;
 
 	size = read(fd, buf, count);
 	if (size == -1) {
-		perror_msg_and_die("Read error");
+		bb_perror_msg_and_die("Read error");
 	}
 	return(size);
 }
+#endif
 
-extern void xread_all(int fd, void *buf, size_t count)
+#ifdef L_xread_all
+extern void bb_xread_all(int fd, void *buf, size_t count)
 {
 	ssize_t size;
 
-	size = xread(fd, buf, count);
-	if (size != count) {
-		error_msg_and_die("Short read");
+	while (count) {
+		if ((size = bb_xread(fd, buf, count)) == 0) {	/* EOF */
+			bb_error_msg_and_die("Short read");
+		}
+		count -= size;
 	}
 	return;
 }
+#endif
 
-extern unsigned char xread_char(int fd)
+#ifdef L_xread_char
+extern unsigned char bb_xread_char(int fd)
 {
 	char tmp;
 	
-	xread_all(fd, &tmp, 1);
+	bb_xread_all(fd, &tmp, 1);
 
 	return(tmp);	
 }
+#endif
 
+#ifdef L_xferror
+extern void bb_xferror(FILE *fp, const char *fn)
+{
+	if (ferror(fp)) {
+		bb_error_msg_and_die("%s", fn);
+	}
+}
+#endif
+
+#ifdef L_xferror_stdout
+extern void bb_xferror_stdout(void)
+{
+	bb_xferror(stdout, bb_msg_standard_output);
+}
+#endif
+
+#ifdef L_xfflush_stdout
+extern void bb_xfflush_stdout(void)
+{
+	if (fflush(stdout)) {
+		bb_perror_msg_and_die(bb_msg_standard_output);
+	}
+}
+#endif
+
+#ifdef L_strlen
 /* Stupid gcc always includes its own builtin strlen()... */
 #undef strlen
-size_t xstrlen(const char *string)
+size_t bb_strlen(const char *string)
 {
 	    return(strlen(string));
 }
+#endif
 
 /* END CODE */
 /*
diff --git a/libbb/xgetcwd.c b/libbb/xgetcwd.c
index 54e9785..85a5c41 100644
--- a/libbb/xgetcwd.c
+++ b/libbb/xgetcwd.c
@@ -40,7 +40,7 @@
 
   if (ret == NULL) {
       free (cwd);
-      perror_msg("getcwd()");
+      bb_perror_msg("getcwd()");
       return NULL;
   }
 
diff --git a/libbb/xgethostbyname.c b/libbb/xgethostbyname.c
index b719797..6b2dff7 100644
--- a/libbb/xgethostbyname.c
+++ b/libbb/xgethostbyname.c
@@ -29,7 +29,7 @@
 	struct hostent *retval;
 
 	if ((retval = gethostbyname(name)) == NULL)
-		herror_msg_and_die("%s", name);
+		bb_herror_msg_and_die("%s", name);
 
 	return retval;
 }
diff --git a/libbb/xgethostbyname2.c b/libbb/xgethostbyname2.c
index f4cbb6a..3a16ae4 100644
--- a/libbb/xgethostbyname2.c
+++ b/libbb/xgethostbyname2.c
@@ -30,7 +30,7 @@
 	struct hostent *retval;
 
 	if ((retval = gethostbyname2(name, af)) == NULL)
-		herror_msg_and_die("%s", name);
+		bb_herror_msg_and_die("%s", name);
 
 	return retval;
 }
diff --git a/libbb/xgetlarg.c b/libbb/xgetlarg.c
index 598b0b3..06e776d 100644
--- a/libbb/xgetlarg.c
+++ b/libbb/xgetlarg.c
@@ -9,6 +9,7 @@
 #include <getopt.h>
 #include <errno.h>
 #include <assert.h>
+#include <ctype.h>
 
 #include "busybox.h"
 
@@ -19,10 +20,16 @@
 	int errno_save = errno;
 
 	assert(arg!=NULL);
+
+	/* Don't allow leading whitespace. */
+	if ((isspace)(*arg)) {	/* Use an actual funciton call for minimal size. */
+		bb_show_usage();
+	}
+
 	errno = 0;
 	result = strtol(arg, &endptr, base);
-	if (errno != 0 || *endptr!='\0' || result < lower || result > upper)
-		show_usage();
+	if (errno != 0 || *endptr!='\0' || endptr==arg || result < lower || result > upper)
+		bb_show_usage();
 	errno = errno_save;
 	return result;
 }
diff --git a/libbb/xgetularg.c b/libbb/xgetularg.c
new file mode 100644
index 0000000..d743520
--- /dev/null
+++ b/libbb/xgetularg.c
@@ -0,0 +1,160 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * xgetularg* implementations for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <assert.h>
+#include "libbb.h"
+
+#ifdef L_xgetularg_bnd_sfx
+extern 
+unsigned long bb_xgetularg_bnd_sfx(const char *arg, int base,
+								   unsigned long lower,
+								   unsigned long upper,
+								   const struct suffix_mult *suffixes)
+{
+	unsigned long r;
+	int old_errno;
+	char *e;
+
+	assert(arg);
+
+	/* Disallow '-' and any leading whitespace.  Speed isn't critical here
+	 * since we're parsing commandline args.  So make sure we get the
+	 * actual isspace function rather than a larger macro implementaion. */
+	if ((*arg == '-') || (isspace)(*arg)) {
+		bb_show_usage();
+	}
+
+	/* Since this is a lib function, we're not allowed to reset errno to 0.
+	 * Doing so could break an app that is deferring checking of errno.
+	 * So, save the old value so that we can restore it if successful. */
+	old_errno = errno;
+	errno = 0;
+	r = strtoul(arg, &e, base);
+	/* Do the initial validity check.  Note: The standards do not
+	 * guarantee that errno is set if no digits were found.  So we
+	 * must test for this explicitly. */
+	if (errno || (arg == e)) {	/* error or no digits */
+		bb_show_usage();
+	}
+	errno = old_errno;	/* Ok.  So restore errno. */
+	
+	/* Do optional suffix parsing.  Allow 'empty' suffix tables.
+	 * Note that we also all nul suffixes with associated multipliers,
+	 * to allow for scaling of the arg by some default multiplier. */
+
+	if (suffixes) {
+		while (suffixes->suffix) {
+			if (strcmp(suffixes->suffix, e) == 0) {
+				if (ULONG_MAX / suffixes->mult < r) {	/* Overflow! */
+					bb_show_usage();
+				}
+				++e;
+				r *= suffixes->mult;
+				break;
+ 			}
+			++suffixes;
+		}
+	}		
+
+	/* Finally, check for illegal trailing chars and range limits. */
+	/* Note: although we allow leading space (via stroul), trailing space
+	 * is an error.  It would be easy enough to allow though if desired. */
+	if (*e || (r < lower) || (r > upper)) {
+		bb_show_usage();
+	}
+
+	return r;
+}
+#endif
+
+#ifdef L_xgetlarg_bnd_sfx
+extern 
+long bb_xgetlarg_bnd_sfx(const char *arg, int base,
+						 long lower,
+						 long upper,
+						 const struct suffix_mult *suffixes)
+{
+	unsigned long u = LONG_MAX;
+	long r;
+	const char *p = arg;
+
+	if ((*p == '-') && (p[1] != '+')) {
+		++p;
+#if LONG_MAX == (-(LONG_MIN + 1))
+		++u;	/* two's complement */
+#endif
+	}
+
+	r = bb_xgetularg_bnd_sfx(p, base, 0, u, suffixes);
+
+	if (*arg == '-') {
+		r = -r;
+	}
+
+	if ((r < lower) || (r > upper)) {
+		bb_show_usage();
+	}
+
+	return r;
+}
+#endif
+
+#ifdef L_getlarg10_sfx
+extern 
+long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes)
+{
+	return bb_xgetlarg_bnd_sfx(arg, 10, LONG_MIN, LONG_MAX, suffixes);
+}
+#endif
+
+#ifdef L_xgetularg_bnd
+extern 
+unsigned long bb_xgetularg_bnd(const char *arg, int base,
+							   unsigned long lower,
+							   unsigned long upper)
+{
+	return bb_xgetularg_bnd_sfx(arg, base, lower, upper, NULL);
+}
+#endif
+
+#ifdef L_xgetularg10_bnd
+extern 
+unsigned long bb_xgetularg10_bnd(const char *arg,
+								 unsigned long lower,
+								 unsigned long upper)
+{
+	return bb_xgetularg_bnd(arg, 10, lower, upper);
+}
+#endif
+
+#ifdef L_xgetularg10
+extern 
+unsigned long bb_xgetularg10(const char *arg)
+{
+	return bb_xgetularg10_bnd(arg, 0, ULONG_MAX);
+}
+#endif
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
index 9944b51..b8cfe61 100644
--- a/libbb/xreadlink.c
+++ b/libbb/xreadlink.c
@@ -24,7 +24,7 @@
 		buf = xrealloc(buf, bufsize += GROWBY);
 		readsize = readlink(path, buf, bufsize); /* 1st try */
 		if (readsize == -1) {
-                   perror_msg("%s", path);
+                   bb_perror_msg("%s", path);
 		    return NULL;
 		}
 	}           
diff --git a/libbb/xregcomp.c b/libbb/xregcomp.c
index 07cf779..56746ac 100644
--- a/libbb/xregcomp.c
+++ b/libbb/xregcomp.c
@@ -34,7 +34,7 @@
 		int errmsgsz = regerror(ret, preg, NULL, 0);
 		char *errmsg = xmalloc(errmsgsz);
 		regerror(ret, preg, errmsg, errmsgsz);
-		error_msg_and_die("xregcomp: %s", errmsg);
+		bb_error_msg_and_die("xregcomp: %s", errmsg);
 	}
 }