[BusyBox-cvs] busybox/coreutils Config.in,1.2,1.3 basename.c,1.20,1.21 cal.c,1.4,1.5 cat.c,1.27,1.28 chgrp.c,1.11,1.12 chmod.c,1.13,1.14 chown.c,1.20,1.21 chroot.c,1.27,1.28 cmp.c,1.8,1.9 cp.c,1.20,1.21 cut.c,1.24,1.25 date.c,1.38,1.39 dd.c,1.52,1.53 df.c,1.49,1.50 dirname.c,1.17,1.18 dos2unix.c,1.16,1.17 du.c,1.55,1.56 echo.c,1.16,1.17 env.c,1.4,1.5 expr.c,1.11,1.12 false.c,1.1,1.2 head.c,1.28,1.29 hostid.c,1.12,1.13 id.c,1.21,1.22 length.c,1.13,1.14 ln.c,1.40,1.41 logname.c,1.16,1.17 ls.c,1.96,1.97 md5sum.c,1.27,1.28 mkdir.c,1.33,1.34 mkfifo.c,1.14,1.15 mknod.c,1.23,1.24 mv.c,1.17,1.18 od.c,1.4,1.5 printf.c,1.17,1.18 pwd.c,1.22,1.23 realpath.c,1.2,1.3 rm.c,1.35,1.36 rmdir.c,1.22,1.23 sha1sum.c,1.2,1.3 sleep.c,1.16,1.17 sort.c,1.34,1.35 stty.c,1.7,1.8 sync.c,1.18,1.19 tail.c,1.43,1.44 tee.c,1.21,1.22 test.c,1.21,1.22 touch.c,1.25,1.26 tr.c,1.33,1.34 true.c,1.1,1.2 tty.c,1.11,1.12 uname.c,1.18,1.19 uniq.c,1.20,1.21 usleep.c,1.10,1.11 uudecode.c,1.19,1.20 uuencode.c,1.24,1.25 watch.c,1.3,1.4 wc.c,1.26,1.27 who.c,1.1,1.2 whoami.c,1.20,1.21 yes.c,1.13,1.14

Manuel Novoa III mjn3 at busybox.net
Wed Mar 19 09:14:13 UTC 2003


Update of /var/cvs/busybox/coreutils
In directory winder:/home/mjn3/work/busybox/coreutils

Modified Files:
	Config.in basename.c cal.c cat.c chgrp.c chmod.c chown.c 
	chroot.c cmp.c cp.c cut.c date.c dd.c df.c dirname.c 
	dos2unix.c du.c echo.c env.c expr.c false.c head.c hostid.c 
	id.c length.c ln.c logname.c ls.c md5sum.c mkdir.c mkfifo.c 
	mknod.c mv.c od.c printf.c pwd.c realpath.c rm.c rmdir.c 
	sha1sum.c sleep.c sort.c stty.c sync.c tail.c tee.c test.c 
	touch.c tr.c true.c tty.c uname.c uniq.c usleep.c uudecode.c 
	uuencode.c watch.c wc.c who.c whoami.c yes.c 
Log Message:
Major coreutils update.


Index: Config.in
===================================================================
RCS file: /var/cvs/busybox/coreutils/Config.in,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Config.in	17 Feb 2003 08:23:21 -0000	1.2
+++ Config.in	19 Mar 2003 09:11:32 -0000	1.3
@@ -111,17 +111,31 @@
 	  Please submit a patch to add help text for this item.
 
 config CONFIG_DU
-	bool "du"
+	bool "du (default blocksize of 512 bytes)"
 	default n
 	help
 	  Please submit a patch to add help text for this item.
 
+config CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
+	bool "  Use a default blocksize of 1024 bytes (1K)"
+	default y
+	depends on CONFIG_DU
+	help
+	  Please submit a patch to add help text for this item.
+
 config CONFIG_ECHO
-	bool "echo"
+	bool "echo (basic SUSv3 version taking no options"
 	default n
 	help
 	  Please submit a patch to add help text for this item.
 
+config CONFIG_FEATURE_FANCY_ECHO
+	bool "  Enable echo options (-n and -e)"
+	default y
+	depends on CONFIG_ECHO
+	help
+	  Please submit a patch to add help text for this item.
+
 config CONFIG_ENV
 	bool "env"
 	default n
@@ -154,6 +168,13 @@
 	help
 	  Please submit a patch to add help text for this item.
 
+config CONFIG_FEATURE_FANCY_HEAD
+	bool "  Enable head options (-c, -q, and -v)"
+	default n
+	depends on CONFIG_HEAD
+	help
+	  Please submit a patch to add help text for this item.
+
 config CONFIG_HOSTID
 	bool "hostid"
 	default n
@@ -313,8 +334,15 @@
 	  Compute and check SHA1 message digest
 
 config CONFIG_SLEEP
-	bool "sleep"
+	bool "sleep (single integer arg with no suffix)"
+	default n
+	help
+	  Please submit a patch to add help text for this item.
+
+config CONFIG_FEATURE_FANCY_SLEEP
+	bool "  Enable multiple integer args and optional time suffixes"
 	default n
+	depends on CONFIG_SLEEP
 	help
 	  Please submit a patch to add help text for this item.
 
@@ -366,6 +394,13 @@
 config CONFIG_TEE
 	bool "tee"
 	default n
+	help
+	  Please submit a patch to add help text for this item.
+
+config CONFIG_FEATURE_TEE_USE_BLOCK_IO
+	bool "  Enable block i/o (larger/faster) instead of byte i/o."
+	default n
+	depends on CONFIG_TEE
 	help
 	  Please submit a patch to add help text for this item.
 

Index: basename.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/basename.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- basename.c	24 Oct 2001 05:00:18 -0000	1.20
+++ basename.c	19 Mar 2003 09:11:32 -0000	1.21
@@ -21,32 +21,43 @@
  *
  */
 
-/* getopt not needed */
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */
+
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Changes:
+ * 1) Now checks for too many args.  Need at least one and at most two.
+ * 2) Don't check for options, as per SUSv3.
+ * 3) Save some space by using strcmp().  Calling strncmp() here was silly.
+ */
 
 #include <stdlib.h>
-#include "busybox.h"
+#include <stdio.h>
 #include <string.h>
+#include "busybox.h"
 
 extern int basename_main(int argc, char **argv)
 {
-	int m, n;
+	size_t m, n;
 	char *s;
 
-	if ((argc < 2) || (**(argv + 1) == '-')) {
-		show_usage();
+	if (((unsigned int)(argc-2)) >= 2) {
+		bb_show_usage();
 	}
 
-	argv++;
-
-	s = get_last_path_component(*argv);
+	s = bb_get_last_path_component(*++argv);
 
-	if (argc>2) {
-		argv++;
+	if (*++argv) {
 		n = strlen(*argv);
 		m = strlen(s);
-		if (m>n && strncmp(s+m-n, *argv, n)==0)
+		if ((m > n) && ((strcmp)(s+m-n, *argv) == 0)) {
 			s[m-n] = '\0';
+		}
 	}
+
 	puts(s);
-	return EXIT_SUCCESS;
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 }

Index: cal.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/cal.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- cal.c	23 Jun 2002 22:25:21 -0000	1.4
+++ cal.c	19 Mar 2003 09:11:32 -0000	1.5
@@ -1,3 +1,14 @@
+/* NOTE:
+ *
+ * Apparently, all "Steven J. Merrifield" did was grab the util-linux cal applet,
+ * spend maybe 5 minutes integrating it into busybox, slapped a copyright on it,
+ * and submitted it.  I certainly saw no evidence of any attempt at size reduction.
+ * Not only do I consider his copyright below meaningless, I also consider his
+ * actions shameful.
+ *
+ * Manuel Novoa III   (mjn3 at codepoet.org)
+ */
+
 /*
  * Calendar implementation for busybox
  *
@@ -20,7 +31,16 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
 */
-       
+
+/* BB_AUDIT SUSv3 compliant with -j and -y extensions (from util-linux). */
+/* BB_AUDIT BUG: The output of 'cal -j 1752' is incorrect.  The upstream
+ * BB_AUDIT BUG: version in util-linux seems to be broken as well. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cal.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Major size reduction... over 50% (>1.5k) on i386.
+ */
 
 #include <sys/types.h>
 #include <ctype.h>
@@ -46,44 +66,30 @@
 #define	MAXDAYS			42		/* max slots in a month array */
 #define	SPACE			-1		/* used in day array */
 
-static int days_in_month[2][13] = {
-	{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
-	{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+static const char days_in_month[] = {
+	0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
 };
 
-int sep1752[MAXDAYS] = {
-	SPACE,	SPACE,	1,	2,	14,	15,	16,
+static const char sep1752[] = {
+	         1,	2,	14,	15,	16,
 	17,	18,	19,	20,	21,	22,	23,
-	24,	25,	26,	27,	28,	29,	30,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-}, j_sep1752[MAXDAYS] = {
-	SPACE,	SPACE,	245,	246,	258,	259,	260,
-	261,	262,	263,	264,	265,	266,	267,
-	268,	269,	270,	271,	272,	273,	274,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-}, empty[MAXDAYS] = {
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
-	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
+	24,	25,	26,	27,	28,	29,	30
 };
 
-char *month_names[12];
-
-char day_headings[] = "                    ";
-char j_day_headings[] = "                           ";
+static int julian;
 
 /* leap year -- account for gregorian reformation in 1752 */
 #define	leap_year(yr) \
 	((yr) <= 1752 ? !((yr) % 4) : \
 	(!((yr) % 4) && ((yr) % 100)) || !((yr) % 400))
 
+static int is_leap_year(int year)
+{
+	return leap_year(year);
+}
+#undef leap_year
+#define leap_year(yr) is_leap_year(yr)
+
 /* number of centuries since 1700, not inclusive */
 #define	centuries_since_1700(yr) \
 	((yr) > 1700 ? (yr) / 100 - 17 : 0)
@@ -96,178 +102,129 @@
 #define	leap_years_since_year_1(yr) \
 	((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))
 
-int julian;
-void ascii_day __P((char *, int));
-void center __P((char *, int, int));
-void day_array __P((int, int, int *));
-int day_in_week __P((int, int, int));
-int day_in_year __P((int, int, int));
-void j_yearly __P((int));
-void monthly __P((int, int));
-void trim_trailing_spaces __P((char *));
-void yearly __P((int));
+static void center __P((char *, int, int));
+static void day_array __P((int, int, int *));
+static void trim_trailing_spaces_and_print __P((char *));
+
+static void blank_string(char *buf, size_t buflen);
+static char *build_row(char *p, int *dp);
+
+#define	DAY_LEN		3		/* 3 spaces per day */
+#define	J_DAY_LEN	(DAY_LEN + 1)
+#define	WEEK_LEN	20		/* 7 * 3 - one space at the end */
+#define	J_WEEK_LEN	(WEEK_LEN + 7)
+#define	HEAD_SEP	2		/* spaces between day headings */
 
 int cal_main(int argc, char **argv)
 {
 	struct tm *local_time;
-	static struct tm zero_tm;
+	struct tm zero_tm;
 	time_t now;
-	int ch, month, year, yflag, i;
+	int month, year, flags, i;
+	char *month_names[12];
+	char day_headings[28];	/* 28 for julian, 21 for nonjulian */
 	char buf[40];
 
 #ifdef CONFIG_LOCALE_SUPPORT
 	setlocale(LC_TIME, "");
 #endif
 
-	yflag = 0;
-	while ((ch = getopt(argc, argv, "jy")) != -1)
-		switch(ch) {
-		case 'j':
-			julian = 1;
-			break;
-		case 'y':
-			yflag = 1;
-			break;
-		default:
-			show_usage();
-		}
-	argc -= optind;
+	flags = bb_getopt_ulflags(argc, argv, "jy");
+
+	julian = flags & 1;
+
 	argv += optind;
 
 	month = 0;
-	switch(argc) {
-	case 2:
-		if ((month = atoi(*argv++)) < 1 || month > 12)
-			error_msg_and_die("Illegal month value: use 1-12");
-		/* FALLTHROUGH */
-	case 1:
-		if ((year = atoi(*argv)) < 1 || year > 9999)
-			error_msg_and_die("Illegal year value: use 1-9999");
-		break;
-	case 0:
+
+	if ((argc -= optind) > 2) {
+		bb_show_usage();
+	}
+
+	if (!argc) {
 		time(&now);
 		local_time = localtime(&now);
 		year = local_time->tm_year + 1900;
-		if (!yflag)
+		if (!(flags & 2)) {
 			month = local_time->tm_mon + 1;
-		break;
-	default:
-		show_usage();
+		}
+	} else {
+		if (argc == 2) {
+			month = bb_xgetularg10_bnd(*argv++, 1, 12);
+		}
+		year = bb_xgetularg10_bnd(*argv, 1, 9999);
 	}
 
-	for (i = 0; i < 12; i++) {
+	blank_string(day_headings, sizeof(day_headings) - 7 +  7*julian);
+
+	i = 0;
+	do {
 		zero_tm.tm_mon = i;
 		strftime(buf, sizeof(buf), "%B", &zero_tm);
-		month_names[i] = xstrdup(buf);
-	}
-	for (i = 0; i < 7; i++) {
-		zero_tm.tm_wday = i;
-		strftime(buf, sizeof(buf), "%a", &zero_tm);
-		strncpy(day_headings + i * 3, buf, 2);
-		strncpy(j_day_headings + i * 4 + 1, buf, 2);
-	}
-
-	if (month)
-		monthly(month, year);
-	else if (julian)
-		j_yearly(year);
-	else
-		yearly(year);
-	exit(0);
-}
-
-#define	DAY_LEN		3		/* 3 spaces per day */
-#define	J_DAY_LEN	4		/* 4 spaces per day */
-#define	WEEK_LEN	20		/* 7 * 3 - one space at the end */
-#define	J_WEEK_LEN	27		/* 7 * 4 - one space at the end */
-#define	HEAD_SEP	2		/* spaces between day headings */
-#define	J_HEAD_SEP	2
-
-void monthly(int month, int year)
-{
-	int col, row, len, days[MAXDAYS];
-	char *p, lineout[30];
-
-	day_array(month, year, days);
-	len = sprintf(lineout, "%s %d", month_names[month - 1], year);
-	printf("%*s%s\n%s\n",
-	    ((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "",
-	    lineout, julian ? j_day_headings : day_headings);
-	for (row = 0; row < 6; row++) {
-		for (col = 0, p = lineout; col < 7; col++,
-		    p += julian ? J_DAY_LEN : DAY_LEN)
-			ascii_day(p, days[row * 7 + col]);
-		*p = '\0';
-		trim_trailing_spaces(lineout);
-		printf("%s\n", lineout);
-	}
-}
-
-void j_yearly(int year)
-{
-	int col, *dp, i, month, row, which_cal;
-	int days[12][MAXDAYS];
-	char *p, lineout[80];
+		month_names[i] = bb_xstrdup(buf);
 
-	sprintf(lineout, "%d", year);
-	center(lineout, J_WEEK_LEN * 2 + J_HEAD_SEP, 0);
-	printf("\n\n");
-	for (i = 0; i < 12; i++)
-		day_array(i + 1, year, days[i]);
-	memset(lineout, ' ', sizeof(lineout) - 1);
-	lineout[sizeof(lineout) - 1] = '\0';
-	for (month = 0; month < 12; month += 2) {
-		center(month_names[month], J_WEEK_LEN, J_HEAD_SEP);
-		center(month_names[month + 1], J_WEEK_LEN, 0);
-		printf("\n%s%*s%s\n", j_day_headings, J_HEAD_SEP, "",
-		    j_day_headings);
-		for (row = 0; row < 6; row++) {
-			for (which_cal = 0; which_cal < 2; which_cal++) {
-				p = lineout + which_cal * (J_WEEK_LEN + 2);
-				dp = &days[month + which_cal][row * 7];
-				for (col = 0; col < 7; col++, p += J_DAY_LEN)
-					ascii_day(p, *dp++);
-			}
-			*p = '\0';
-			trim_trailing_spaces(lineout);
-			printf("%s\n", lineout);
+		if (i < 7) {
+			zero_tm.tm_wday = i;
+			strftime(buf, sizeof(buf), "%a", &zero_tm);
+			strncpy(day_headings + i * (3+julian) + julian, buf, 2);
 		}
-	}
-	printf("\n");
-}
-
-void yearly(int year)
-{
-	int col, *dp, i, month, row, which_cal;
-	int days[12][MAXDAYS];
-	char *p, lineout[80];
+	} while (++i < 12);
 
-	sprintf(lineout, "%d", year);
-	center(lineout, WEEK_LEN * 3 + HEAD_SEP * 2, 0);
-	printf("\n\n");
-	for (i = 0; i < 12; i++)
-		day_array(i + 1, year, days[i]);
-	memset(lineout, ' ', sizeof(lineout) - 1);
-	lineout[sizeof(lineout) - 1] = '\0';
-	for (month = 0; month < 12; month += 3) {
-		center(month_names[month], WEEK_LEN, HEAD_SEP);
-		center(month_names[month + 1], WEEK_LEN, HEAD_SEP);
-		center(month_names[month + 2], WEEK_LEN, 0);
-		printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP,
-		    "", day_headings, HEAD_SEP, "", day_headings);
+	if (month) {
+		int row, len, days[MAXDAYS];
+		int *dp = days;
+		char lineout[30];
+		
+		day_array(month, year, dp);
+		len = sprintf(lineout, "%s %d", month_names[month - 1], year);
+		bb_printf("%*s%s\n%s\n",
+			   ((7*julian + WEEK_LEN) - len) / 2, "",
+			   lineout, day_headings);
 		for (row = 0; row < 6; row++) {
-			for (which_cal = 0; which_cal < 3; which_cal++) {
-				p = lineout + which_cal * (WEEK_LEN + 2);
-				dp = &days[month + which_cal][row * 7];
-				for (col = 0; col < 7; col++, p += DAY_LEN)
-					ascii_day(p, *dp++);
+			build_row(lineout, dp)[0] = '\0';
+			dp += 7;
+			trim_trailing_spaces_and_print(lineout);
+		}
+	} else {
+		int row, which_cal, week_len, days[12][MAXDAYS];
+		int *dp;
+		char lineout[80];
+		
+		sprintf(lineout, "%d", year);
+		center(lineout,
+			   (WEEK_LEN * 3 + HEAD_SEP * 2)
+			   + julian * (J_WEEK_LEN * 2 + HEAD_SEP
+						   - (WEEK_LEN * 3 + HEAD_SEP * 2)),
+			   0);
+		puts("\n");		/* two \n's */
+		for (i = 0; i < 12; i++) {
+			day_array(i + 1, year, days[i]);
+		}
+		blank_string(lineout, sizeof(lineout));
+		week_len = WEEK_LEN + julian * (J_WEEK_LEN - WEEK_LEN);
+		for (month = 0; month < 12; month += 3-julian) {
+			center(month_names[month], week_len, HEAD_SEP);
+			if (!julian) {
+				center(month_names[month + 1], week_len, HEAD_SEP);
+			}
+			center(month_names[month + 2 - julian], week_len, 0);
+			bb_printf("\n%s%*s%s", day_headings, HEAD_SEP, "", day_headings);
+			if (!julian) {
+				bb_printf("%*s%s", HEAD_SEP, "", day_headings);
+			}
+			putchar('\n');
+			for (row = 0; row < (6*7); row += 7) {
+				for (which_cal = 0; which_cal < 3-julian; which_cal++) {
+					dp = days[month + which_cal] + row;
+					build_row(lineout + which_cal * (week_len + 2), dp);
+				}
+				/* blank_string took care of nul termination. */
+				trim_trailing_spaces_and_print(lineout);
 			}
-			*p = '\0';
-			trim_trailing_spaces(lineout);
-			printf("%s\n", lineout);
 		}
 	}
-	printf("\n");
+
+	bb_fflush_stdout_and_exit(0);
 }
 
 /*
@@ -277,117 +234,128 @@
  *	out end to end.  You would have 42 numbers or spaces.  This routine
  *	builds that array for any month from Jan. 1 through Dec. 9999.
  */
-void day_array(int month, int year, int *days)
+static void day_array(int month, int year, int *days)
 {
+	long temp;
+	int i;
+	int j_offset;
 	int day, dw, dm;
 
+	memset(days, SPACE, MAXDAYS * sizeof(int));
+
 	if ((month == 9) && (year == 1752)) {
-		memmove(days,
-			julian ? j_sep1752 : sep1752, MAXDAYS * sizeof(int));
+		j_offset = julian * 244;
+		i = 0;
+		do {
+			days[i+2] = sep1752[i] + j_offset;
+		} while (++i < sizeof(sep1752));
+
 		return;
 	}
-	memmove(days, empty, MAXDAYS * sizeof(int));
-	dm = days_in_month[leap_year(year)][month];
-	dw = day_in_week(1, month, year);
-	day = julian ? day_in_year(1, month, year) : 1;
-	while (dm--)
-		days[dw++] = day++;
-}
 
-/*
- * day_in_year --
- *	return the 1 based day number within the year
- */
-int day_in_year(int day, int month, int year)
-{
-	int i, leap;
-
-	leap = leap_year(year);
-	for (i = 1; i < month; i++)
-		day += days_in_month[leap][i];
-	return (day);
-}
+	/* day_in_year
+	 *	return the 1 based day number within the year
+	 */
+	day = 1;
+	if ((month > 2) && leap_year(year)) {
+		++day;
+	}
 
-/*
- * day_in_week
- *	return the 0 based day number for any date from 1 Jan. 1 to
- *	31 Dec. 9999.  Assumes the Gregorian reformation eliminates
- *	3 Sep. 1752 through 13 Sep. 1752.  Returns Thursday for all
- *	missing days.
- */
-int day_in_week(int day, int month, int year)
-{
-	long temp;
+	i = month;
+	while (i) {
+		day += days_in_month[--i];
+	}
 
+	/* day_in_week
+	 *	return the 0 based day number for any date from 1 Jan. 1 to
+	 *	31 Dec. 9999.  Assumes the Gregorian reformation eliminates
+	 *	3 Sep. 1752 through 13 Sep. 1752.  Returns Thursday for all
+	 *	missing days.
+	 */
+	dw = THURSDAY;
 	temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
-	    + day_in_year(day, month, year);
-	if (temp < FIRST_MISSING_DAY)
-		return ((temp - 1 + SATURDAY) % 7);
-	if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS))
-		return (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
-	return (THURSDAY);
+		+ day;
+	if (temp < FIRST_MISSING_DAY) {
+		dw = ((temp - 1 + SATURDAY) % 7);
+	} else if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) {
+		dw = (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
+	}
+
+	if (!julian) {
+		day = 1;
+	}
+
+	dm = days_in_month[month];
+	if ((month == 2) && leap_year(year)) {
+		++dm;
+	}
+
+	while (dm) {
+		days[dw++] = day++;
+		--dm;
+	}
 }
 
-void ascii_day(char *p, int day)
+static void trim_trailing_spaces_and_print(char *s)
 {
-	int display, val;
-	static char *aday[] = {
-		"",
-		" 1", " 2", " 3", " 4", " 5", " 6", " 7",
-		" 8", " 9", "10", "11", "12", "13", "14",
-		"15", "16", "17", "18", "19", "20", "21",
-		"22", "23", "24", "25", "26", "27", "28",
-		"29", "30", "31",
-	};
+	char *p = s;
 
-	if (day == SPACE) {
-		memset(p, ' ', julian ? J_DAY_LEN : DAY_LEN);
-		return;
+	while (*p) {
+		++p;
 	}
-	if (julian) {
-		if ((val = day / 100) != 0) {
-			day %= 100;
-			*p++ = val + '0';
-			display = 1;
-		} else {
-			*p++ = ' ';
-			display = 0;
+	while (p > s) {
+		--p;
+		if (!(isspace)(*p)) {	/* We want the function... not the inline. */
+			p[1] = '\0';
+			break;
 		}
-		val = day / 10;
-		if (val || display)
-			*p++ = val + '0';
-		else
-			*p++ = ' ';
-		*p++ = day % 10 + '0';
-	} else {
-		*p++ = aday[day][0];
-		*p++ = aday[day][1];
 	}
-	*p = ' ';
+
+	puts(s);
 }
 
-void trim_trailing_spaces(char *s)
+static void center(char *str, int len, int separate)
 {
-	char *p;
+	int n = strlen(str);
+	len -= n;
+	bb_printf("%*s%*s", (len/2) + n, str, (len/2) + (len % 2) + separate, "");
+}
 
-	for (p = s; *p; ++p)
-		continue;
-	while (p > s && (--p, isspace(*p)))
-		continue;
-	if (p > s)
-		++p;
-	*p = '\0';
+static void blank_string(char *buf, size_t buflen)
+{
+	memset(buf, ' ', buflen);
+	buf[buflen-1] = '\0';
 }
 
-void center(char *str, int len, int separate)
+static char *build_row(char *p, int *dp)
 {
+	int col, val, day;
+		
+	memset(p, ' ', (julian + DAY_LEN) * 7);
 
-	len -= strlen(str);
-	printf("%*s%s%*s", len / 2, "", str, len / 2 + len % 2, "");
-	if (separate)
-		printf("%*s", separate, "");
-}
+	col = 0;
+	do {
+		if ((day = *dp++) != SPACE) {
+			if (julian) {
+				*++p;
+				if (day >= 100) {
+					*p = '0';
+					p[-1] = (day / 100) + '0';
+					day %= 100;
+				}
+			}
+			if ((val = day / 10) > 0) {
+				*p = val + '0';
+			}
+			*++p = day % 10 + '0';
+			p += 2;
+		} else {
+			p += DAY_LEN + julian;
+		}
+	} while (++col < 7);
 
+	return p;
+}
 
 /*
  * Copyright (c) 1989, 1993, 1994

Index: cat.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/cat.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- cat.c	20 Dec 2001 23:13:24 -0000	1.27
+++ cat.c	19 Mar 2003 09:11:32 -0000	1.28
@@ -1,9 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini Cat implementation for busybox
+ * cat implementation for busybox
  *
- * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
- * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee at debian.org>
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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,33 +20,48 @@
  *
  */
 
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * This is a new implementation of 'cat' which aims to be SUSv3 compliant.
+ *
+ * Changes from the previous implementation include:
+ * 1) Multiple '-' args are accepted as required by SUSv3.  The previous
+ *    implementation would close stdin and segfault on a subsequent '-'.
+ * 2) The '-u' options is required by SUSv3.  Note that the specified
+ *    behavior for '-u' is done by default, so all we need do is accept
+ *    the option.
+ */
+
 #include <stdlib.h>
-#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
 #include "busybox.h"
 
 extern int cat_main(int argc, char **argv)
 {
-	int status = EXIT_SUCCESS;
+	FILE *f;
+	int retval = EXIT_SUCCESS;
 
-	if (argc == 1) {
-		print_file(stdin);
-		return status;
+	bb_getopt_ulflags(argc, argv, "u");
+
+	argv += optind;
+	if (!*argv) {
+		*--argv = "-";
 	}
 
-	while (--argc > 0) {
-		if(!(strcmp(*++argv, "-"))) {
-			print_file(stdin);
-		} else if (! print_file_by_name(*argv)) {
-			status = EXIT_FAILURE;
+	do {
+		if ((f = bb_wfopen_input(*argv)) != NULL) {
+			int r = bb_copyfd(fileno(f), STDOUT_FILENO, 0);
+			bb_fclose_nonstdin(f);
+			if (r >= 0) {
+				continue;
+			}
 		}
-	}
-	return status;
-}
+		retval = EXIT_FAILURE;
+	} while (*++argv);
 
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
+	return retval;
+}

Index: chgrp.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/chgrp.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- chgrp.c	20 Dec 2001 23:12:50 -0000	1.11
+++ chgrp.c	19 Mar 2003 09:11:32 -0000	1.12
@@ -21,9 +21,12 @@
  *
  */
 
-#include <stdio.h>
+/* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */
+/* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */
+/* BB_AUDIT Note: gnu chgrp does not support -H, -L, or -P. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chgrp.html */
+
 #include <stdlib.h>
-#include <string.h>
 #include <unistd.h>
 #include "busybox.h"
 
@@ -32,53 +35,46 @@
 #define lchown	chown
 #endif
 
-
-static long gid;
-
 static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
 {
-	if (lchown(fileName, statbuf->st_uid, (gid == -1) ? statbuf->st_gid : gid) == 0) {
+	if (lchown(fileName, statbuf->st_uid, *((long *) junk)) == 0) {
 		return (TRUE);
 	}
-	perror(fileName);
+	bb_perror_msg("%s", fileName);	/* Avoid multibyte problems. */
 	return (FALSE);
 }
 
 int chgrp_main(int argc, char **argv)
 {
-	int opt;
-	int recursiveFlag = FALSE;
-	char *p=NULL;
+	long gid;
+	int recursiveFlag;;
+	int retval = EXIT_SUCCESS;
+	char *p;
 
-	/* do normal option parsing */
-	while ((opt = getopt(argc, argv, "R")) > 0) {
-		switch (opt) {
-			case 'R':
-				recursiveFlag = TRUE;
-				break;
-			default:
-				show_usage();
-		}
+	recursiveFlag = bb_getopt_ulflags(argc, argv, "R");
+
+	if (argc - optind < 2) {
+		bb_show_usage();
 	}
 
-	if (argc > optind && argc > 2 && argv[optind]) {
-		/* Find the selected group */
-		gid = strtoul(argv[optind], &p, 10);	/* maybe it's already numeric */
-		if (argv[optind] == p)
-			gid = my_getgrnam(argv[optind]);
-	} else {
-		error_msg_and_die(too_few_args);
+	argv += optind;
+
+	/* Find the selected group */
+	gid = strtoul(*argv, &p, 10);	/* maybe it's already numeric */
+	if (*p || (p == *argv)) {		/* trailing chars or nonnumeric */
+		gid = my_getgrnam(*argv);
 	}
+	++argv;
 
 	/* Ok, ready to do the deed now */
-	while (++optind < argc) {
-		if (! recursive_action (argv[optind], recursiveFlag, FALSE, FALSE, 
-					fileAction, fileAction, NULL)) {
-			return EXIT_FAILURE;
+	do {
+		if (! recursive_action (*argv, recursiveFlag, FALSE, FALSE, 
+								fileAction, fileAction, &gid)) {
+			retval = EXIT_FAILURE;
 		}
-	}
-	return EXIT_SUCCESS;
+	} while (*++argv);
 
+	return retval;
 }
 
 /*

Index: chmod.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/chmod.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- chmod.c	10 Oct 2002 03:47:01 -0000	1.13
+++ chmod.c	19 Mar 2003 09:11:32 -0000	1.14
@@ -24,67 +24,84 @@
  *
  */
 
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU defects - unsupported options -c, -f, -v, and long options. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <getopt.h>
+#include <sys/stat.h>
 #include "busybox.h"
 
 static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
 {
-	if (!parse_mode((char *)junk, &(statbuf->st_mode)))
-		error_msg_and_die( "unknown mode: %s", (char *)junk);
+	if (!bb_parse_mode((char *)junk, &(statbuf->st_mode)))
+		bb_error_msg_and_die( "unknown mode: %s", (char *)junk);
 	if (chmod(fileName, statbuf->st_mode) == 0)
 		return (TRUE);
-	perror(fileName);
+	bb_perror_msg("%s", fileName);	/* Avoid multibyte problems. */
 	return (FALSE);
 }
 
 int chmod_main(int argc, char **argv)
 {
-	int opt;
+	int retval = EXIT_SUCCESS;
 	int recursiveFlag = FALSE;
-	int modeind = 0;   /* Index of the mode argument in `argv'. */
+	int count;
 	char *smode;
-	static const char chmod_modes[] = "Rrwxstugoa,+-=";
+	char **p;
+	char *p0;
+	char opt = '-';
 
-	/* do normal option parsing */
-	while (1) {
-		int thisind = optind ? optind : 1;
+	++argv;
+	count = 0;
 
-		opt = getopt(argc, argv, chmod_modes);
-		if (opt == EOF)
-				break;
-		smode = strchr(chmod_modes, opt);
-		if(smode == NULL)
-				show_usage();
-		if(smode == chmod_modes) {      /* 'R' */
-			recursiveFlag = TRUE;
-		} else {
-		      if (modeind != 0 && modeind != thisind)
-			show_usage();
-		      modeind = thisind;
+	for (p = argv  ; *p ; p++) {
+		p0 = p[0];
+		if (p0[0] == opt) {
+			if ((p0[1] == '-') && !p0[2]) {
+				opt = 0;	/* Disable further option processing. */
+				continue;
+			}
+			if (p0[1] == 'R') {
+				char *s = p0 + 2;
+				while (*s == 'R') {
+					++s;
+				}
+				if (*s) {
+					bb_show_usage();
+				}
+				recursiveFlag = TRUE;
+				continue;
+			}
+			if (count) {
+				bb_show_usage();
+			}
 		}
+		argv[count] = p0;
+		++count;
 	}
 
-	if (modeind == 0)
-		modeind = optind++;
+	argv[count] = NULL;
 
-	opt = optind;
-	if (opt >= argc) {
-		error_msg_and_die(too_few_args);
+	if (count < 2) {
+		bb_show_usage();
 	}
 
-	smode = argv[modeind];
+	smode = *argv;
+	++argv;
+
 	/* Ok, ready to do the deed now */
-	for (; opt < argc; opt++) {
-		if (! recursive_action (argv[opt], recursiveFlag, FALSE, FALSE, fileAction,
-					fileAction, smode)) {
-			return EXIT_FAILURE;
+	do {
+		if (! recursive_action (*argv, recursiveFlag, FALSE, FALSE,
+								fileAction,	fileAction, smode)) {
+			retval = EXIT_FAILURE;
 		}
-	}
-	return EXIT_SUCCESS;
+	} while (*++argv);
+
+	return retval;
 }
 
 /*

Index: chown.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/chown.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- chown.c	8 Feb 2003 23:36:15 -0000	1.20
+++ chown.c	19 Mar 2003 09:11:32 -0000	1.21
@@ -21,10 +21,14 @@
  *
  */
 
-#include <stdio.h>
+/* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */
+/* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */
+/* BB_AUDIT Note: gnu chown does not support -H, -L, or -P. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */
+
 #include <stdlib.h>
-#include <string.h>
 #include <unistd.h>
+#include <string.h>
 #include "busybox.h"
 
 /* Don't use lchown for libc5 or glibc older then 2.1.x */
@@ -42,65 +46,67 @@
 	if (chown_func(fileName, uid, (gid == -1) ? statbuf->st_gid : gid) == 0) {
 		return (TRUE);
 	}
-	perror(fileName);
+	bb_perror_msg("%s", fileName);	/* Avoid multibyte problems. */
 	return (FALSE);
 }
 
+#define FLAG_R 1
+#define FLAG_h 2
+
+static unsigned long get_ug_id(const char *s, long (*my_getxxnam)(const char *))
+{
+	unsigned long r;
+	char *p;
+
+	r = strtoul(s, &p, 10);
+	if (*p || (s == p)) {
+		r = my_getxxnam(s);
+	}
+
+	return r;
+}
+
 int chown_main(int argc, char **argv)
 {
-	int opt;
-	int recursiveFlag = FALSE,
-		noderefFlag = FALSE;
-	char *groupName=NULL;
-	char *p=NULL;
+	int flags;
+	int retval = EXIT_SUCCESS;
+	char *groupName;
 
-	/* do normal option parsing */
-	while ((opt = getopt(argc, argv, "Rh")) > 0) {
-		switch (opt) {
-			case 'R':
-				recursiveFlag = TRUE;
-				break;
-			case 'h':
-				noderefFlag = TRUE;
-				break;
-			default:
-				show_usage();
-		}
+	flags = bb_getopt_ulflags(argc, argv, "Rh");
+
+	if (flags & FLAG_h) chown_func = lchown;
+
+	if (argc - optind < 2) {
+		bb_show_usage();
 	}
 
-	if (noderefFlag) chown_func = lchown;
+	argv += optind;
 
-	if (argc > optind && argc > 2 && argv[optind]) {
-		/* First, check if there is a group name here */
-		groupName = strchr(argv[optind], '.');
-		if (groupName == NULL)
-			groupName = strchr(argv[optind], ':');
-		if (groupName) {
-			*groupName++ = '\0';
-			gid = strtoul(groupName, &p, 10);
-			if (groupName == p)
-				gid = my_getgrnam(groupName);
-		} else {
-			gid = -1;
-		}
-		/* Now check for the username */
-		uid = strtoul(argv[optind], &p, 10);	/* Is is numeric? */
-		if (argv[optind] == p) {
-			uid = my_getpwnam(argv[optind]);
-		}
-	} else {
-		error_msg_and_die(too_few_args);
+	/* First, check if there is a group name here */
+	if ((groupName = strchr(*argv, '.')) == NULL) {
+		groupName = strchr(*argv, ':');
 	}
 
+	gid = -1;
+	if (groupName) {
+		*groupName++ = '\0';
+		gid = get_ug_id(groupName, my_getgrnam);
+	}
+
+	/* Now check for the username */
+	uid = get_ug_id(*argv, my_getpwnam);
+
+	++argv;
+	
 	/* Ok, ready to do the deed now */
-	while (++optind < argc) {
-		if (! recursive_action (argv[optind], recursiveFlag, FALSE, FALSE, 
-					fileAction, fileAction, NULL)) {
-			return EXIT_FAILURE;
+	do {
+		if (! recursive_action (*argv, (flags & FLAG_R), FALSE, FALSE, 
+								fileAction, fileAction, NULL)) {
+			retval = EXIT_FAILURE;
 		}
-	}
-	return EXIT_SUCCESS;
+	} while (*++argv);
 
+	return retval;
 }
 
 /*

Index: chroot.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/chroot.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- chroot.c	24 Oct 2001 05:00:18 -0000	1.27
+++ chroot.c	19 Mar 2003 09:11:32 -0000	1.28
@@ -21,6 +21,8 @@
  *
  */
 
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -29,46 +31,24 @@
 
 int chroot_main(int argc, char **argv)
 {
-	char *prog;
-
-	if ((argc < 2) || (**(argv + 1) == '-')) {
-		show_usage();
+	if (argc < 2) {
+		bb_show_usage();
 	}
-	argc--;
-	argv++;
 
+	++argv;
 	if (chroot(*argv) || (chdir("/"))) {
-		perror_msg_and_die("cannot change root directory to %s", *argv);
+		bb_perror_msg_and_die("cannot change root directory to %s", *argv);
 	}
 
-	argc--;
-	argv++;
-	if (argc >= 1) {
-		prog = *argv;
-		execvp(*argv, argv);
-	} else {
-#if defined shell_main && defined CONFIG_FEATURE_SH_STANDALONE_SHELL
-		char shell[] = "/bin/sh";
-		char *shell_argv[2] = { shell, NULL };
-		applet_name = shell;
-		shell_main(1, shell_argv);
-		return EXIT_SUCCESS;
-#else
-		prog = getenv("SHELL");
-		if (!prog)
-			prog = "/bin/sh";
-		execlp(prog, prog, NULL);
-#endif
+	++argv;
+	if (argc == 2) {
+		argv -= 2;
+		if (!(*argv = getenv("SHELL"))) {
+			*argv = (char *) "/bin/sh";
+		}
+		argv[1] = (char *) "-i";
 	}
-	perror_msg_and_die("cannot execute %s", prog);
 
+	execvp(*argv, argv);
+	bb_perror_msg_and_die("cannot execute %s", *argv);
 }
-
-
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/

Index: cmp.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/cmp.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- cmp.c	24 Oct 2001 05:00:26 -0000	1.8
+++ cmp.c	19 Mar 2003 09:11:32 -0000	1.9
@@ -20,59 +20,133 @@
  *
  */
 
+/* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Original version majorly reworked for SUSv3 compliance, bug fixes, and
+ * size optimizations.  Changes include:
+ * 1) Now correctly distingusishes between errors and actual file differences.
+ * 2) Proper handling of '-' args.
+ * 3) Actual error checking of i/o.
+ * 4) Accept SUSv3 -l option.  Note that we use the slightly nicer gnu format
+ *    in the '-l' case.
+ */
+
 #include <stdio.h>
-#include <string.h>
-#include <errno.h>
 #include <stdlib.h>
-#include <getopt.h>
+#include <unistd.h>
 #include "busybox.h"
 
+static FILE *cmp_xfopen_input(const char *filename)
+{
+	FILE *fp;
+
+	if ((fp = bb_wfopen_input(filename)) != NULL) {
+		return fp;
+	}
+
+	exit(bb_default_error_retval);	/* We already output an error message. */
+}
+
+static const char fmt_eof[] = "cmp: EOF on %s\n";
+static const char fmt_differ[] = "%s %s differ: char %d, line %d\n";
+#if 0
+static const char fmt_l_opt[] = "%.0s%.0s%d %o %o\n";	/* SUSv3 format */
+#else
+static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n";	/* nicer gnu format */
+#endif
+
+static const char opt_chars[] = "sl";
+
+enum {
+	OPT_s = 1,
+	OPT_l = 2
+};
+
 int cmp_main(int argc, char **argv)
 {
-	FILE *fp1 = NULL, *fp2 = stdin;
-	char *filename1, *filename2 = "-";
-	int c, c1, c2, char_pos = 1, line_pos = 1, silent = FALSE;
+	FILE *fp1, *fp2, *outfile = stdout;
+	const char *filename1, *filename2;
+	const char *fmt;
+	int c1, c2, char_pos, line_pos;
+	int opt_flags;
+	int exit_val = 0;
 
-	while ((c = getopt(argc, argv, "s")) != EOF) {
-		switch (c) {
-			case 's':
-				silent = TRUE;
-				break;
-			default:
-				show_usage();
-		}
+	bb_default_error_retval = 2;	/* 1 is returned if files are different. */
+
+	opt_flags = bb_getopt_ulflags(argc, argv, opt_chars);
+
+	if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > 1)) {
+		bb_show_usage();
 	}
 
-	filename1 = argv[optind];
-	switch (argc - optind) {
-		case 2:
-			fp2 = xfopen(filename2 = argv[optind + 1], "r");
-		case 1:
-			fp1 = xfopen(filename1, "r");
-			break;
-		default:
-			show_usage();
+	fp1 = cmp_xfopen_input(filename1 = *(argv += optind));
+
+	filename2 = "-";
+	if (*++argv) {
+		filename2 = *argv;
+	}
+	fp2 = cmp_xfopen_input(filename2);
+
+	if (fp1 == fp2) {			/* Paranioa check... stdin == stdin? */
+		/* Note that we don't bother reading stdin.  Neither does gnu wc.
+		 * But perhaps we should, so that other apps down the chain don't
+		 * get the input.  Consider 'echo hello | (cmp - - && cat -)'.
+		 */
+		return 0;
+	}
+
+	fmt = fmt_differ;
+	if (opt_flags == OPT_l) {
+		fmt = fmt_l_opt;
 	}
 
+	char_pos = 0;
+	line_pos = 1;
 	do {
-		c1 = fgetc(fp1);
-		c2 = fgetc(fp2);
-		if (c1 != c2) {
-			if (silent)
-				return EXIT_FAILURE;
-			if (c1 == EOF)
-				printf("EOF on %s\n", filename1);
-			else if (c2 == EOF)
-				printf("EOF on %s\n", filename2);
-			else
-				printf("%s %s differ: char %d, line %d\n", filename1, filename2,
-						char_pos, line_pos);
-			return EXIT_FAILURE;
+		c1 = getc(fp1);
+		c2 = getc(fp2);
+		++char_pos;
+		if (c1 != c2) {			/* Remember -- a read error may have occurred. */
+			exit_val = 1;		/* But assume the files are different for now. */
+			if (c2 == EOF) {
+				/* We know that fp1 isn't at EOF or in an error state.  But to
+				 * save space below, things are setup to expect an EOF in fp1
+				 * if an EOF occurred.  So, swap things around.
+				 */
+				fp1 = fp2;
+				filename1 = filename2;
+				c1 = c2;
+			}
+			if (c1 == EOF) {
+				bb_xferror(fp1, filename1);
+				fmt = fmt_eof;	/* Well, no error, so it must really be EOF. */
+				outfile = stderr;
+				/* There may have been output to stdout (option -l), so
+				 * make sure we fflush before writing to stderr. */
+				bb_xfflush_stdout();
+			}
+			if (opt_flags != OPT_s) {
+				if (opt_flags == OPT_l) {
+					line_pos = c1;	/* line_pos is unused in the -l case. */
+				}
+				bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2);
+				if (opt_flags) {	/* This must be -l since not -s. */
+					/* If we encountered and EOF, the while check will catch it. */
+					continue;
+				}
+			}
+			break;
+		}
+		if (c1 == '\n') {
+			++line_pos;
 		}
-		char_pos++;
-		if (c1 == '\n')
-			line_pos++;
 	} while (c1 != EOF);
 
-	return EXIT_SUCCESS;
+	bb_xferror(fp1, filename1);
+	bb_xferror(fp2, filename2);
+
+	bb_fflush_stdout_and_exit(exit_val);
 }

Index: cp.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/cp.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- cp.c	5 Oct 2001 01:35:08 -0000	1.20
+++ cp.c	19 Mar 2003 09:11:32 -0000	1.21
@@ -2,7 +2,6 @@
 /*
  * Mini cp implementation for busybox
  *
- *
  * Copyright (C) 2000 by Matt Kraai <kraai at alumni.carnegiemellon.edu>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,6 +20,15 @@
  *
  */
 
+/* BB_AUDIT SUSv3 defects - unsupported options -H, -L, and -P. */
+/* BB_AUDIT GNU defects - only extension options supported are -a and -d.  */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Size reduction.
+ */
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -29,86 +37,76 @@
 #include <errno.h>
 #include <dirent.h>
 #include <stdlib.h>
-
+#include <assert.h>
 #include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+static const char cp_opts[] = "pdRfia";	/* WARNING!! ORDER IS IMPORTANT!! */
 
 extern int cp_main(int argc, char **argv)
 {
+	struct stat source_stat;
+	struct stat dest_stat;
+	const char *last;
+	const char *dest;
+	int s_flags;
+	int d_flags;
+	int flags;
 	int status = 0;
-	int opt;
-	int flags = FILEUTILS_DEREFERENCE;
-	int i;
 
-	while ((opt = getopt(argc, argv, "adfipR")) != -1)
-		switch (opt) {
-		case 'a':
-			flags |= FILEUTILS_PRESERVE_STATUS | FILEUTILS_RECUR;
-			/* fallthrough */
-		case 'd':
-			flags &= ~FILEUTILS_DEREFERENCE;
-			break;
-		case 'f':
-			flags |= FILEUTILS_FORCE;
-			break;
-		case 'i':
-			flags |= FILEUTILS_INTERACTIVE;
-			break;
-		case 'p':
-			flags |= FILEUTILS_PRESERVE_STATUS;
-			break;
-		case 'R':
-			flags |= FILEUTILS_RECUR;
-			break;
-		default:
-			show_usage();
-		}
-	
-	if (optind + 2 > argc)
-		show_usage();
+	/* Since these are enums, #if tests will not work.  So use assert()s. */
+	assert(FILEUTILS_PRESERVE_STATUS == 1);
+	assert(FILEUTILS_DEREFERENCE == 2);
+	assert(FILEUTILS_RECUR == 4);
+	assert(FILEUTILS_FORCE == 8);
+	assert(FILEUTILS_INTERACTIVE == 16);
 
-	/* If there are only two arguments and...  */
-	if (optind + 2 == argc) {
-		struct stat source_stat;
-		struct stat dest_stat;
-		int source_exists = 1;
-		int dest_exists = 1;
+	flags = bb_getopt_ulflags(argc, argv, cp_opts);
 
-		if ((!(flags & FILEUTILS_DEREFERENCE) &&
-				lstat(argv[optind], &source_stat) < 0) ||
-				((flags & FILEUTILS_DEREFERENCE) &&
-				 stat(argv[optind], &source_stat))) {
-			if (errno != ENOENT)
-				perror_msg_and_die("unable to stat `%s'", argv[optind]);
-			source_exists = 0;
-		}
+	if (flags & 32) {
+		flags |= (FILEUTILS_PRESERVE_STATUS | FILEUTILS_RECUR | FILEUTILS_DEREFERENCE);
+	}
 
-		if (stat(argv[optind + 1], &dest_stat) < 0) {
-			if (errno != ENOENT)
-				perror_msg_and_die("unable to stat `%s'", argv[optind + 1]);
-			dest_exists = 0;
+	flags ^= FILEUTILS_DEREFERENCE;		/* The sense of this flag was reversed. */
+
+	if (optind + 2 > argc) {
+		bb_show_usage();
+	}
+
+	last = argv[argc - 1];
+	argv += optind;
+
+	/* If there are only two arguments and...  */
+	if (optind + 2 == argc) {
+		s_flags = cp_mv_stat2(*argv, &source_stat,
+								 (flags & FILEUTILS_DEREFERENCE) ? stat : lstat);
+		if ((s_flags < 0) || ((d_flags = cp_mv_stat(last, &dest_stat)) < 0)) {
+			exit(EXIT_FAILURE);
 		}
-		
 		/* ...if neither is a directory or...  */
-		if (((!source_exists || !S_ISDIR(source_stat.st_mode)) &&
-				(!dest_exists || !S_ISDIR(dest_stat.st_mode))) ||
-				/* ...recursing, the first is a directory, and the
-				 * second doesn't exist, then... */
-				((flags & FILEUTILS_RECUR) && S_ISDIR(source_stat.st_mode) &&
-				 !dest_exists)) {
+		if ( !((s_flags | d_flags) & 2) ||
+			/* ...recursing, the 1st is a directory, and the 2nd doesn't exist... */
+			/* ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags) */
+			/* Simplify the above since FILEUTILS_RECUR >> 1 == 2. */
+			((((flags & FILEUTILS_RECUR) >> 1) & s_flags) && !d_flags)
+		) {
 			/* ...do a simple copy.  */
-			if (copy_file(argv[optind], argv[optind + 1], flags) < 0)
-				status = 1;
-			return status;
+				dest = last;
+				goto DO_COPY; /* Note: optind+2==argc implies argv[1]==last below. */
 		}
 	}
 
-	for (i = optind; i < argc - 1; i++) {
-		char *dest = concat_path_file(argv[argc - 1],
-				get_last_path_component(argv[i]));
-		if (copy_file(argv[i], dest, flags) < 0)
+	do {
+		dest = concat_path_file(last, bb_get_last_path_component(*argv));
+	DO_COPY:
+		if (copy_file(*argv, dest, flags) < 0) {
 			status = 1;
-		free(dest);
-	}
+		}
+		if (*++argv == last) {
+			break;
+		}
+		free((void *) dest);
+	} while (1);
 
-	return status;
+	exit(status);
 }

Index: cut.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/cut.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- cut.c	2 Aug 2001 05:02:45 -0000	1.24
+++ cut.c	19 Mar 2003 09:11:32 -0000	1.25
@@ -92,7 +92,7 @@
 		} else {
 			s = strtoul(ntok, &junk, 10);
 			if(*junk != '\0' || s < 0)
-				error_msg_and_die("invalid byte or field list");
+				bb_error_msg_and_die("invalid byte or field list");
 			
 			/* account for the fact that arrays are zero based, while the user
 			 * expects the first char on the line to be char # 1 */
@@ -109,7 +109,7 @@
 		} else {
 			e = strtoul(ntok, &junk, 10);
 			if(*junk != '\0' || e < 0)
-				error_msg_and_die("invalid byte or field list");
+				bb_error_msg_and_die("invalid byte or field list");
 			/* if the user specified and end position of 0, that means "til the
 			 * end of the line */
 			if (e == 0)
@@ -121,7 +121,7 @@
 
 		/* if there's something left to tokenize, the user past an invalid list */
 		if (ltok)
-			error_msg_and_die("invalid byte or field list");
+			bb_error_msg_and_die("invalid byte or field list");
 		
 		/* add the new list */
 		cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
@@ -131,7 +131,7 @@
 
 	/* make sure we got some cut positions out of all that */
 	if (nlists == 0)
-		error_msg_and_die("missing list of positions");
+		bb_error_msg_and_die("missing list of positions");
 
 	/* now that the lists are parsed, we need to sort them to make life easier
 	 * on us when it comes time to print the chars / fields / lines */
@@ -267,8 +267,7 @@
 	unsigned int linenum = 0; /* keep these zero-based to be consistent */
 
 	/* go through every line in the file */
-	while ((line = get_line_from_file(file)) != NULL) {
-		chomp(line);
+	while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
 
 		/* cut based on chars/bytes XXX: only works when sizeof(char) == byte */
 		if (part == 'c' || part == 'b')
@@ -299,14 +298,14 @@
 			case 'f':
 				/* make sure they didn't ask for two types of lists */
 				if (part != 0) {
-					error_msg_and_die("only one type of list may be specified");
+					bb_error_msg_and_die("only one type of list may be specified");
 				}
 				part = (char)opt;
 				parse_lists(optarg);
 				break;
 			case 'd':
 				if (strlen(optarg) > 1) {
-					error_msg_and_die("the delimiter must be a single character");
+					bb_error_msg_and_die("the delimiter must be a single character");
 				}
 				delim = optarg[0];
 				break;
@@ -320,17 +319,17 @@
 	}
 
 	if (part == 0) {
-		error_msg_and_die("you must specify a list of bytes, characters, or fields");
+		bb_error_msg_and_die("you must specify a list of bytes, characters, or fields");
 	}
 
 	/*  non-field (char or byte) cutting has some special handling */
 	if (part != 'f') {
 		if (supress_non_delimited_lines) {
-			error_msg_and_die("suppressing non-delimited lines makes sense"
+			bb_error_msg_and_die("suppressing non-delimited lines makes sense"
 					" only when operating on fields");
 		}
 		if (delim != '\t' && part != 'f') {
-			error_msg_and_die("a delimiter may be specified only when operating on fields");
+			bb_error_msg_and_die("a delimiter may be specified only when operating on fields");
 		}
 	}
 
@@ -344,7 +343,7 @@
 		int i;
 		FILE *file;
 		for (i = optind; i < argc; i++) {
-			file = wfopen(argv[i], "r");
+			file = bb_wfopen(argv[i], "r");
 			if(file) {
 				cut_file(file);
 				fclose(file);

Index: date.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/date.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- date.c	23 Aug 2002 05:58:38 -0000	1.38
+++ date.c	19 Mar 2003 09:11:32 -0000	1.39
@@ -53,7 +53,7 @@
 				&(tm_time->tm_year));
 
 	if (nr < 4 || nr > 5) {
-		error_msg_and_die(invalid_date, t_string);
+		bb_error_msg_and_die(bb_msg_invalid_date, t_string);
 	}
 
 	/* correct for century  - minor Y2K problem here? */
@@ -108,7 +108,7 @@
 		t.tm_year -= 1900;	/* Adjust years */
 		t.tm_mon -= 1;	/* Adjust dates from 1-12 to 0-11 */
 	} else {
-		error_msg_and_die(invalid_date, t_string);
+		bb_error_msg_and_die(bb_msg_invalid_date, t_string);
 	}
 	*tm_time = t;
 	return (tm_time);
@@ -145,25 +145,25 @@
 		case 's':
 			set_time = 1;
 			if ((date_str != NULL) || ((date_str = optarg) == NULL)) {
-				show_usage();
+				bb_show_usage();
 			}
 			break;
 		case 'u':
 			utc = 1;
 			if (putenv("TZ=UTC0") != 0)
-				error_msg_and_die(memory_exhausted);
+				bb_error_msg_and_die(bb_msg_memory_exhausted);
 			break;
 		case 'd':
 			use_arg = 1;
 			if ((date_str != NULL) || ((date_str = optarg) == NULL))
-				show_usage();
+				bb_show_usage();
 			break;
 #ifdef CONFIG_FEATURE_DATE_ISOFMT
 		case 'I':
 			if (!optarg)
 				ifmt = 1;
 			else {
-				int ifmt_len = xstrlen(optarg);
+				int ifmt_len = bb_strlen(optarg);
 
 				if ((ifmt_len <= 4)
 					&& (strncmp(optarg, "date", ifmt_len) == 0)) {
@@ -180,11 +180,11 @@
 				}
 			}
 			if (ifmt) {
-				break;	/* else show_usage(); */
+				break;	/* else bb_show_usage(); */
 			}
 #endif
 		default:
-			show_usage();
+			bb_show_usage();
 		}
 	}
 
@@ -220,15 +220,15 @@
 		/* Correct any day of week and day of year etc. fields */
 		tm = mktime(&tm_time);
 		if (tm < 0) {
-			error_msg_and_die(invalid_date, date_str);
+			bb_error_msg_and_die(bb_msg_invalid_date, date_str);
 		}
 		if (utc && (putenv("TZ=UTC0") != 0)) {
-			error_msg_and_die(memory_exhausted);
+			bb_error_msg_and_die(bb_msg_memory_exhausted);
 		}
 
 		/* if setting time, set it */
 		if (set_time && (stime(&tm) < 0)) {
-			perror_msg("cannot set date");
+			bb_perror_msg("cannot set date");
 		}
 	}
 

Index: dd.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/dd.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- dd.c	28 Nov 2002 11:05:28 -0000	1.52
+++ dd.c	19 Mar 2003 09:11:33 -0000	1.53
@@ -62,19 +62,19 @@
 	int ifd;
 	int ofd;
 	int i;
-	char *infile = NULL;
-	char *outfile = NULL;
+	const char *infile = NULL;
+	const char *outfile = NULL;
 	char *buf;
 
 	for (i = 1; i < argc; i++) {
 		if (strncmp("bs=", argv[i], 3) == 0)
-			bs = parse_number(argv[i]+3, dd_suffixes);
+			bs = bb_xparse_number(argv[i]+3, dd_suffixes);
 		else if (strncmp("count=", argv[i], 6) == 0)
-			count = parse_number(argv[i]+6, dd_suffixes);
+			count = bb_xparse_number(argv[i]+6, dd_suffixes);
 		else if (strncmp("seek=", argv[i], 5) == 0)
-			seek = parse_number(argv[i]+5, dd_suffixes);
+			seek = bb_xparse_number(argv[i]+5, dd_suffixes);
 		else if (strncmp("skip=", argv[i], 5) == 0)
-			skip = parse_number(argv[i]+5, dd_suffixes);
+			skip = bb_xparse_number(argv[i]+5, dd_suffixes);
 		else if (strncmp("if=", argv[i], 3) == 0)
 			infile = argv[i]+3;
 		else if (strncmp("of=", argv[i], 3) == 0)
@@ -92,7 +92,7 @@
 					noerror = TRUE;
 					buf += 7;
 				} else {
-					error_msg_and_die("invalid conversion `%s'", argv[i]+5);
+					bb_error_msg_and_die("invalid conversion `%s'", argv[i]+5);
 				}
 				if (buf[0] == '\0')
 					break;
@@ -100,18 +100,18 @@
 					buf++;
 			}
 		} else
-			show_usage();
+			bb_show_usage();
 	}
 
 	buf = xmalloc(bs);
 
 	if (infile != NULL) {
 		if ((ifd = open(infile, O_RDONLY)) < 0) {
-			perror_msg_and_die("%s", infile);
+			bb_perror_msg_and_die("%s", infile);
 		}
 	} else {
 		ifd = STDIN_FILENO;
-		infile = "standard input";
+		infile = bb_msg_standard_input;
 	}
 
 	if (outfile != NULL) {
@@ -122,7 +122,7 @@
 		}
 
 		if ((ofd = open(outfile, oflag, 0666)) < 0) {
-			perror_msg_and_die("%s", outfile);
+			bb_perror_msg_and_die("%s", outfile);
 		}
 
 		if (seek && trunc) {
@@ -131,24 +131,24 @@
 
 				if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) ||
 						S_ISDIR (st.st_mode)) {
-					perror_msg_and_die("%s", outfile);
+					bb_perror_msg_and_die("%s", outfile);
 				}
 			}
 		}
 	} else {
 		ofd = STDOUT_FILENO;
-		outfile = "standard output";
+		outfile = bb_msg_standard_output;
 	}
 
 	if (skip) {
 		if (lseek(ifd, skip * bs, SEEK_CUR) < 0) {
-			perror_msg_and_die("%s", infile);
+			bb_perror_msg_and_die("%s", infile);
 		}
 	}
 
 	if (seek) {
 		if (lseek(ofd, seek * bs, SEEK_CUR) < 0) {
-			perror_msg_and_die("%s", outfile);
+			bb_perror_msg_and_die("%s", outfile);
 		}
 	}
 
@@ -161,9 +161,9 @@
 		if (n < 0) {
 			if (noerror) {
 				n = bs;
-				perror_msg("%s", infile);
+				bb_perror_msg("%s", infile);
 			} else {
-				perror_msg_and_die("%s", infile);
+				bb_perror_msg_and_die("%s", infile);
 			}
 		}
 		if (n == 0) {
@@ -178,9 +178,9 @@
 			memset(buf + n, '\0', bs - n);
 			n = bs;
 		}
-		n = full_write(ofd, buf, n);
+		n = bb_full_write(ofd, buf, n);
 		if (n < 0) {
-			perror_msg_and_die("%s", outfile);
+			bb_perror_msg_and_die("%s", outfile);
 		}
 		if (n == bs) {
 			out_full++;
@@ -190,15 +190,16 @@
 	}
 
 	if (close (ifd) < 0) {
-		perror_msg_and_die("%s", infile);
+		bb_perror_msg_and_die("%s", infile);
 	}
 
 	if (close (ofd) < 0) {
-		perror_msg_and_die("%s", outfile);
+		bb_perror_msg_and_die("%s", outfile);
 	}
 
-	fprintf(stderr, "%ld+%ld records in\n", (long)in_full, (long)in_part);
-	fprintf(stderr, "%ld+%ld records out\n", (long)out_full, (long)out_part);
+	fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n",
+			(long)in_full, (long)in_part,
+			(long)out_full, (long)out_part);
 
 	return EXIT_SUCCESS;
 }

Index: df.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/df.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- df.c	24 Oct 2001 04:59:27 -0000	1.49
+++ df.c	19 Mar 2003 09:11:33 -0000	1.50
@@ -22,74 +22,45 @@
  *
  */
 
+/* BB_AUDIT SUSv3 _NOT_ compliant -- options -P and -t missing.  Also blocksize. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/df.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Size reduction.  Removed floating point dependency.  Added error checking
+ * on output.  Output stats on 0-sized filesystems if specificly listed on
+ * the command line.  Properly round *-blocks, Used, and Available quantities.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <mntent.h>
 #include <sys/vfs.h>
-#include <getopt.h>
 #include "busybox.h"
 
-extern const char mtab_file[];	/* Defined in utility.c */
-#ifdef CONFIG_FEATURE_HUMAN_READABLE
-static unsigned long df_disp_hr = KILOBYTE; 
+#ifndef CONFIG_FEATURE_HUMAN_READABLE
+static long kscale(long b, long bs)
+{
+	return ( b * (long long) bs + KILOBYTE/2 ) / KILOBYTE;
+}
 #endif
 
-static int do_df(char *device, const char *mount_point)
+extern int df_main(int argc, char **argv)
 {
-	struct statfs s;
 	long blocks_used;
 	long blocks_percent_used;
-
-	if (statfs(mount_point, &s) != 0) {
-		perror_msg("%s", mount_point);
-		return FALSE;
-	}
-
-	if (s.f_blocks > 0) {
-		blocks_used = s.f_blocks - s.f_bfree;
-		if(blocks_used == 0)
-			blocks_percent_used = 0;
-		else {
-			blocks_percent_used = (long)
-			  (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5);
-		}
-		if (strcmp(device, "/dev/root") == 0) {
-			/* Adjusts device to be the real root device,
-			 * or leaves device alone if it can't find it */
-			device = find_real_root_device_name(device);
-			if(device==NULL)
-				return FALSE;
-		}
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
-		printf("%-20s %9s ", device,
-				make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr));
-
-		printf("%9s ",
-				make_human_readable_str( (s.f_blocks - s.f_bfree), s.f_bsize, df_disp_hr));
-
-		printf("%9s %3ld%% %s\n",
-				make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr),
-				blocks_percent_used, mount_point);
-#else
-		printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
-				device,
-				(long) (s.f_blocks * (s.f_bsize / (double)KILOBYTE)),
-				(long) ((s.f_blocks - s.f_bfree)*(s.f_bsize/(double)KILOBYTE)),
-				(long) (s.f_bavail * (s.f_bsize / (double)KILOBYTE)),
-				blocks_percent_used, mount_point);
+	unsigned long df_disp_hr = KILOBYTE; 
 #endif
-	}
-
-	return TRUE;
-}
-
-extern int df_main(int argc, char **argv)
-{
 	int status = EXIT_SUCCESS;
-	int opt = 0;
-	int i = 0;
-	char disp_units_hdr[80] = "1k-blocks"; /* default display is kilobytes */
+	int opt;
+	FILE *mount_table;
+	struct mntent *mount_entry;
+	struct statfs s;
+	static const char hdr_1k[] = "1k-blocks"; /* default display is kilobytes */;
+	const char *disp_units_hdr = hdr_1k;
 
 	while ((opt = getopt(argc, argv, "k"
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
@@ -101,52 +72,106 @@
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
 			case 'h':
 				df_disp_hr = 0;
-				strcpy(disp_units_hdr, "     Size");
+				disp_units_hdr = "     Size";
 				break;
 			case 'm':
 				df_disp_hr = MEGABYTE;
-				strcpy(disp_units_hdr, "1M-blocks");
+				disp_units_hdr = "1M-blocks";
 				break;
 #endif
 			case 'k':
 				/* default display is kilobytes */
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+				df_disp_hr = KILOBYTE;
+				disp_units_hdr =  hdr_1k;
+#endif
 				break;
 			default:
-					  show_usage();
+					  bb_show_usage();
 		}
 	}
 
-	printf("%-20s %-14s %s %s %s %s\n", "Filesystem", disp_units_hdr,
-	       "Used", "Available", "Use%", "Mounted on");
+	bb_printf("Filesystem%11s%-15sUsed Available Use%% Mounted on\n",
+			  "", disp_units_hdr);
 
-	if(optind < argc) {
-		struct mntent *mount_entry;
-		for(i = optind; i < argc; i++)
-		{
-			if ((mount_entry = find_mount_point(argv[i], mtab_file)) == 0) {
-				error_msg("%s: can't find mount point.", argv[i]);
-				status = EXIT_FAILURE;
-			} else if (!do_df(mount_entry->mnt_fsname, mount_entry->mnt_dir))
-				status = EXIT_FAILURE;
+	mount_table = NULL;
+	argv += optind;
+	if (optind >= argc) {
+		if (!(mount_table = setmntent(bb_path_mtab_file, "r"))) {
+			bb_perror_msg_and_die(bb_path_mtab_file);
 		}
-	} else {
-		FILE *mount_table;
-		struct mntent *mount_entry;
+	}
 
-		mount_table = setmntent(mtab_file, "r");
-		if (mount_table == 0) {
-			perror_msg("%s", mtab_file);
-			return EXIT_FAILURE;
-		}
+	do {
+		const char *device;
+		const char *mount_point;
 
-		while ((mount_entry = getmntent(mount_table))) {
-			if (!do_df(mount_entry->mnt_fsname, mount_entry->mnt_dir))
+		if (mount_table) {
+			if (!(mount_entry = getmntent(mount_table))) {
+				endmntent(mount_table);
+				break;
+			}
+		} else {
+			if (!(mount_point = *argv++)) {
+				break;
+			}
+			if (!(mount_entry = find_mount_point(mount_point, bb_path_mtab_file))) {
+				bb_error_msg("%s: can't find mount point.", mount_point);
+			SET_ERROR:
 				status = EXIT_FAILURE;
+				continue;
+			}
 		}
-		endmntent(mount_table);
-	}
 
-	return status;
+		device = mount_entry->mnt_fsname;
+		mount_point = mount_entry->mnt_dir;
+
+		if (statfs(mount_point, &s) != 0) {
+			bb_perror_msg("%s", mount_point);
+			goto SET_ERROR;
+		}
+		
+		if ((s.f_blocks > 0) || !mount_table){
+			blocks_used = s.f_blocks - s.f_bfree;
+			blocks_percent_used = 0;
+			if (blocks_used + s.f_bavail) {
+				blocks_percent_used = (((long long) blocks_used) * 100
+									   + (blocks_used + s.f_bavail)/2
+									   ) / (blocks_used + s.f_bavail);
+			}
+			
+			if (strcmp(device, "/dev/root") == 0) {
+				/* Adjusts device to be the real root device,
+				* or leaves device alone if it can't find it */
+				if ((device = find_real_root_device_name(device)) != NULL) {
+					goto SET_ERROR;
+				}
+			}
+			
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+			bb_printf("%-21s%9s ", device,
+					  make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr));
+			
+			bb_printf("%9s ",
+					  make_human_readable_str( (s.f_blocks - s.f_bfree),
+											  s.f_bsize, df_disp_hr));
+			
+			bb_printf("%9s %3ld%% %s\n",
+					  make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr),
+					  blocks_percent_used, mount_point);
+#else
+			bb_printf("%-21s%9ld %9ld %9ld %3ld%% %s\n",
+					  device,
+					  kscale(s.f_blocks, s.f_bsize),
+					  kscale(s.f_blocks-s.f_bfree, s.f_bsize),
+					  kscale(s.f_bavail, s.f_bsize),
+					  blocks_percent_used, mount_point);
+#endif
+		}
+
+	} while (1);
+
+	bb_fflush_stdout_and_exit(status);
 }
 
 /*

Index: dirname.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/dirname.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- dirname.c	24 Oct 2001 05:00:18 -0000	1.17
+++ dirname.c	19 Mar 2003 09:11:33 -0000	1.18
@@ -21,20 +21,20 @@
  *
  */
 
-/* getopt not needed */
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/dirname.html */
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include "busybox.h"
 
 extern int dirname_main(int argc, char **argv)
 {
-	if ((argc < 2) || (**(argv + 1) == '-'))
-		show_usage();
-	argv++;
+	if (argc != 2) {
+		bb_show_usage();
+	}
 
-	puts (dirname (argv[0]));
+	puts(dirname(argv[1]));
 
-	return EXIT_SUCCESS;
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 }

Index: dos2unix.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/dos2unix.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- dos2unix.c	3 Jul 2002 04:24:08 -0000	1.16
+++ dos2unix.c	19 Mar 2003 09:11:33 -0000	1.17
@@ -35,6 +35,10 @@
 #include <sys/time.h>
 #include "busybox.h"
 
+#define CT_AUTO         0
+#define CT_UNIX2DOS     1
+#define CT_DOS2UNIX     2
+
 /* We are making a lame pseudo-random string generator here.  in
  * convert(), each pass through the while loop will add more and more
  * stuff into value, which is _supposed_ to wrap.  We don't care about
@@ -55,15 +59,13 @@
 	FILE *in = stdin, *out = stdout;
 
 	if (fn != NULL) {
-		if ((in = wfopen(fn, "rw")) == NULL) {
-			return -1;
-		}
+		in = bb_xfopen(fn, "rw");
 		safe_strncpy(tempFn, fn, sizeof(tempFn));
 		c = strlen(tempFn);
 		tempFn[c] = '.';
 		while(1) {
 		    if (c >=BUFSIZ)
-			error_msg_and_die("unique name not found");
+			bb_error_msg_and_die("unique name not found");
 		    /* Get some semi random stuff to try and make a
 		     * random filename based (and in the same dir as)
 		     * the input file... */
@@ -92,7 +94,7 @@
 				// file is alredy in DOS format so it is not necessery to touch it
 				remove(tempFn);
 				if (fclose(in) < 0 || fclose(out) < 0) {
-					perror_msg(NULL);
+					bb_perror_nomsg();
 					return -2;
 				}
 				return 0;
@@ -106,7 +108,7 @@
 				// file is alredy in UNIX format so it is not necessery to touch it
 				remove(tempFn);
 				if ((fclose(in) < 0) || (fclose(out) < 0)) {
-					perror_msg(NULL);
+					bb_perror_nomsg();
 					return -2;
 				}
 				return 0;
@@ -137,7 +139,7 @@
 
 	if (fn != NULL) {
 	    if (fclose(in) < 0 || fclose(out) < 0) {
-		perror_msg(NULL);
+		bb_perror_nomsg();
 		remove(tempFn);
 		return -2;
 	    }
@@ -146,7 +148,7 @@
 	     * should be true since we put them into the same directory
 	     * so we _should_ be ok, but you never know... */
 	    if (rename(tempFn, fn) < 0) {
-		perror_msg("unable to rename '%s' as '%s'", tempFn, fn);
+		bb_perror_msg("unable to rename '%s' as '%s'", tempFn, fn);
 		return -1;
 	    }
 	}
@@ -177,7 +179,7 @@
 			ConvType = CT_DOS2UNIX;
 			break;
 		default:
-			show_usage();
+			bb_show_usage();
 		}
 	}
 

Index: du.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/du.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -d -r1.55 -r1.56
--- du.c	23 Aug 2002 07:28:45 -0000	1.55
+++ du.c	19 Mar 2003 09:11:33 -0000	1.56
@@ -22,45 +22,65 @@
  *
  */
 
-#include <sys/types.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <stdio.h>
+/* BB_AUDIT SUSv3 compliant (unless default blocksize set to 1k) */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/du.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Mostly rewritten for SUSv3 compliance and to fix bugs/defects.
+ * 1) Added support for SUSv3 -a, -H, -L, gnu -c, and (busybox) -d options.
+ *    The -d option allows setting of max depth (similar to gnu --max-depth).
+ * 2) Fixed incorrect size calculations for links and directories, especially
+ *    when errors occurred.  Calculates sizes should now match gnu du output.
+ * 3) Added error checking of output.
+ * 4) Fixed busybox bug #1284 involving long overflow with human_readable.
+ */
+
 #include <stdlib.h>
-#include <getopt.h>
-#include <string.h>
-#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
 #include "busybox.h"
 
-
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
+# ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
 static unsigned long disp_hr = KILOBYTE;
+# else
+static unsigned long disp_hr = 512;
+# endif
+#elif defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
+static unsigned int disp_k = 1;
+#else
+static unsigned int disp_k;	/* bss inits to 0 */
 #endif
 
-static int du_depth /*= 0*/;
-static int count_hardlinks /*= 0*/;
-static int one_file_system /*= 0*/;
+static int max_print_depth = INT_MAX;
+static int count_hardlinks = INT_MAX;
+
+static int status
+#if EXIT_SUCCESS == 0
+	= EXIT_SUCCESS
+#endif
+	;
+static int print_files;
+static int slink_depth;
+static int du_depth;
+static int one_file_system;
 static dev_t dir_dev;
 
-static void (*print) (long, char *);
 
-static void print_normal(long size, char *filename)
+static void print(long size, char *filename)
 {
+	/* TODO - May not want to defer error checking here. */
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
-	printf("%s\t%s\n", make_human_readable_str(size << 10, 1, disp_hr),
+	bb_printf("%s\t%s\n", make_human_readable_str(size, 512, disp_hr),
 		   filename);
 #else
-	printf("%ld\t%s\n", size, filename);
+	bb_printf("%ld\t%s\n", size >> disp_k, filename);
 #endif
 }
 
-static void print_summary(long size, char *filename)
-{
-	if (du_depth == 1) {
-		print_normal(size, filename);
-	}
-}
-
 /* tiny recursive du */
 static long du(char *filename)
 {
@@ -68,23 +88,43 @@
 	long sum;
 
 	if ((lstat(filename, &statbuf)) != 0) {
-		perror_msg("%s", filename);
+		bb_perror_msg("%s", filename);
+		status = EXIT_FAILURE;
 		return 0;
 	}
-	if (du_depth == 0)
-		dir_dev = statbuf.st_dev;
-	else if (one_file_system && dir_dev != statbuf.st_dev)
-		return 0;
 
-	du_depth++;
-	sum = (statbuf.st_blocks >> 1);
+	if (one_file_system) {
+		if (du_depth == 0) {
+			dir_dev = statbuf.st_dev;
+		} else if (dir_dev != statbuf.st_dev) {
+			return 0;
+		}
+	}
+
+	sum = statbuf.st_blocks;
 
-	/* Don't add in stuff pointed to by symbolic links */
 	if (S_ISLNK(statbuf.st_mode)) {
-		sum = 0L;
-		if (du_depth == 1) {
+		if (slink_depth > du_depth) {	/* -H or -L */
+			if ((stat(filename, &statbuf)) != 0) {
+				bb_perror_msg("%s", filename);
+				status = EXIT_FAILURE;
+				return 0;
+			}
+			sum = statbuf.st_blocks;
+			if (slink_depth == 1) {
+				slink_depth = INT_MAX;	/* Convert -H to -L. */
+			}
+		}
+	}
+
+	if (statbuf.st_nlink > count_hardlinks) {
+		/* Add files/directories with links only once */
+		if (is_in_ino_dev_hashtable(&statbuf, NULL)) {
+			return 0;
 		}
+		add_to_ino_dev_hashtable(&statbuf, NULL);
 	}
+
 	if (S_ISDIR(statbuf.st_mode)) {
 		DIR *dir;
 		struct dirent *entry;
@@ -92,8 +132,9 @@
 
 		dir = opendir(filename);
 		if (!dir) {
-			du_depth--;
-			return 0;
+			bb_perror_msg("%s", filename);
+			status = EXIT_FAILURE;
+			return sum;
 		}
 
 		newfile = last_char_is(filename, '/');
@@ -103,54 +144,86 @@
 		while ((entry = readdir(dir))) {
 			char *name = entry->d_name;
 
-			if ((strcmp(name, "..") == 0)
-				|| (strcmp(name, ".") == 0)) {
+			if ((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2]))) {
 				continue;
 			}
 			newfile = concat_path_file(filename, name);
+			++du_depth;
 			sum += du(newfile);
+			--du_depth;
 			free(newfile);
 		}
 		closedir(dir);
+	} else if (du_depth > print_files) {
+		return sum;
+	}
+	if (du_depth <= max_print_depth) {
 		print(sum, filename);
-	} else if (statbuf.st_nlink > 1 && !count_hardlinks) {
-		/* Add files with hard links only once */
-		if (is_in_ino_dev_hashtable(&statbuf, NULL)) {
-			sum = 0L;
-			if (du_depth == 1)
-				print(sum, filename);
-		} else {
-			add_to_ino_dev_hashtable(&statbuf, NULL);
-		}
 	}
-	du_depth--;
 	return sum;
 }
 
 int du_main(int argc, char **argv)
 {
-	int status = EXIT_SUCCESS;
-	int i;
+	long total;
+	int slink_depth_save;
+	int print_final_total = 0;
 	int c;
 
-	/* default behaviour */
-	print = print_normal;
+#ifdef CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
+	if (getenv("POSIXLY_CORRECT")) {	/* TODO - a new libbb function? */
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+		disp_hr = 512;
+#else
+		disp_k = 0;
+#endif
+	} 
+#endif
 
-	/* parse argv[] */
-	while ((c = getopt(argc, argv, "slx"
+	/* Note: SUSv3 specifies that -a and -s options can not be used together
+	 * in strictly conforming applications.  However, it also says that some
+	 * du implementations may produce output when -a and -s are used together.
+	 * gnu du exits with an error code in this case.  We choose to simply
+	 * ignore -a.  This is consistent with -s being equivalent to -d 0.
+	 */
+
+	while ((c = getopt(argc, argv, "aHkLsx" "d:" "lc"
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
 					   "hm"
 #endif
-					   "k")) != EOF) {
+					   )) > 0) {
 		switch (c) {
+		case 'a':
+			print_files = INT_MAX;
+			break;
+		case 'H':
+			slink_depth = 1;
+			break;
+		case 'k':
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+			disp_hr = KILOBYTE;
+#elif !defined CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K
+			disp_k = 1;
+#endif
+			break;
+		case 'L':
+			slink_depth = INT_MAX;
+			break;
 		case 's':
-			print = print_summary;
+			max_print_depth = 0;
+			break;
+		case 'x':
+			one_file_system = 1;
+			break;
+
+		case 'd':
+			max_print_depth = bb_xgetularg10_bnd(optarg, 0, INT_MAX);
 			break;
 		case 'l':
 			count_hardlinks = 1;
 			break;
-		case 'x':
-			one_file_system = 1;
+		case 'c':
+			print_final_total = 1;
 			break;
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
 		case 'h':
@@ -160,37 +233,31 @@
 			disp_hr = MEGABYTE;
 			break;
 #endif
-		case 'k':
-			break;
 		default:
-			show_usage();
+			bb_show_usage();
 		}
 	}
 
 	/* go through remaining args (if any) */
+	argv += optind;
 	if (optind >= argc) {
-		if (du(".") == 0)
-			status = EXIT_FAILURE;
-	} else {
-		long sum;
-
-		for (i = optind; i < argc; i++) {
-			sum = du(argv[i]);
-			if (is_directory(argv[i], FALSE, NULL) == FALSE) {
-				print_normal(sum, argv[i]);
-			}
-			reset_ino_dev_hashtable();
+		*--argv = ".";
+		if (slink_depth == 1) {
+			slink_depth = 0;
 		}
 	}
 
-	return status;
-}
+	slink_depth_save = slink_depth;
+	total = 0;
+	do {
+		total += du(*argv);
+		slink_depth = slink_depth_save;
+	} while (*++argv);
+	reset_ino_dev_hashtable();
 
-/* $Id$ */
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
+	if (print_final_total) {
+		print(total, "total");
+	}
+
+	bb_fflush_stdout_and_exit(status);
+}

Index: echo.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/echo.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- echo.c	9 Apr 2001 22:48:11 -0000	1.16
+++ echo.c	19 Mar 2003 09:11:33 -0000	1.17
@@ -22,94 +22,107 @@
  * Original copyright notice is retained at the end of this file.
  */
 
+/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Because of behavioral differences, implemented configureable SUSv3
+ * or 'fancy' gnu-ish behaviors.  Also, reduced size and fixed bugs.
+ * 1) In handling '\c' escape, the previous version only suppressed the
+ *     trailing newline.  SUSv3 specifies _no_ output after '\c'.
+ * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}.
+ *    The previous version version did not allow 4-digit octals.
+ */
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include "busybox.h"
 
-extern int 
-echo_main(int argc, char** argv)
+extern int echo_main(int argc, char** argv)
 {
-	int nflag = 0;
+#ifndef CONFIG_FEATURE_FANCY_ECHO
+#define eflag '\\'
+	++argv;
+#else
+	const char *p;
+	int nflag = 1;
 	int eflag = 0;
 
-	/* Skip argv[0]. */
-	argc--;
-	argv++;
-
-	while (argc > 0 && *argv[0] == '-')
-	{
-		register char *temp;
-		register int ix;
-
-		/*
-		 * If it appears that we are handling options, then make sure
+	while (*++argv && (**argv == '-')) {
+		/* If it appears that we are handling options, then make sure
 		 * that all of the options specified are actually valid.
 		 * Otherwise, the string should just be echoed.
 		 */
-		temp = argv[0] + 1;
-
-		for (ix = 0; temp[ix]; ix++)
-		{
-			if (strrchr("neE", temp[ix]) == 0)
-				goto just_echo;
-		}
-
-		if (!*temp)
+		
+		if (!*(p = *argv + 1)) {	/* A single '-', so echo it. */
 			goto just_echo;
+		}
 
-		/*
-		 * All of the options in temp are valid options to echo.
-		 * Handle them.
-		 */
-		while (*temp)
-		{
-			if (*temp == 'n')
-				nflag = 1;
-			else if (*temp == 'e')
-				eflag = 1;
-			else if (*temp == 'E')
-				eflag = 0;
-			else
+		do {
+			if (strrchr("neE", *p) == 0) {
 				goto just_echo;
+			}
+		} while (*++p);
 
-			temp++;
-		}
-		argc--;
-		argv++;
+		/* All of the options in this arg are valid, so handle them. */
+		p = *argv + 1;
+		do {
+			if (*p == 'n') {
+				nflag = 0;
+			} else if (*p == 'e') {
+				eflag = '\\';
+			} else {
+				eflag = 0;
+			}
+		} while (*++p);
 	}
 
 just_echo:
-	while (argc > 0) {
-		const char *arg = argv[0];
+#endif
+	while (*argv) {
 		register int c;
 
-		while ((c = *arg++)) {
-
-			/* Check for escape sequence. */
-			if (c == '\\' && eflag && *arg) {
-				if (*arg == 'c') {
-					/* '\c' means cancel newline. */
-					nflag = 1;
-					arg++;
-					continue;
-				} else {
-					c = process_escape_sequence(&arg);
+		while ((c = *(*argv)++)) {
+			if (c == eflag) {	/* Check for escape seq. */
+				if (**argv == 'c') {
+					/* '\c' means cancel newline and 
+					 * ignore all subsequent chars. */
+					goto DONE;
+				}
+#ifndef CONFIG_FEATURE_FANCY_ECHO
+				/* SUSv3 specifies that octal escapes must begin with '0'. */
+				if (((unsigned int)(**argv - '1')) >= 7)
+#endif
+				{
+					/* Since SUSv3 mandates a first digit of 0, 4-digit octals
+					* of the form \0### are accepted. */
+					if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) {
+						(*argv)++;
+					}
+					/* bb_process_escape_sequence can handle nul correctly */
+					c = bb_process_escape_sequence((const char **) argv);
 				}
 			}
-
 			putchar(c);
 		}
-		argc--;
-		argv++;
-		if (argc > 0)
+
+		if (*++argv) {
 			putchar(' ');
+		}
 	}
-	if (!nflag)
+
+#ifdef CONFIG_FEATURE_FANCY_ECHO
+	if (nflag) {
 		putchar('\n');
-	fflush(stdout);
+	}
+#else
+	putchar('\n');
+#endif
 
-	return EXIT_SUCCESS;
+DONE:
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 }
 
 /*-

Index: env.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/env.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- env.c	16 May 2001 14:21:09 -0000	1.4
+++ env.c	19 Mar 2003 09:11:33 -0000	1.5
@@ -24,50 +24,66 @@
  * Modified for BusyBox by Erik Andersen <andersen at lineo.com>, <andersee at debian.org>
  */
 
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/env.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Fixed bug involving exit return codes if execvp fails.  Also added
+ * output error checking.
+ */
+
 #include <stdio.h>
 #include <string.h>
-#include <getopt.h>
 #include <stdlib.h>
+#include <errno.h>
 #include <unistd.h>
 #include "busybox.h"
 
 extern int env_main(int argc, char** argv)
 {
 	char **ep, *p;
-	char *cleanenv[1];
-	int ignore_environment = 0;
+	char *cleanenv[1] = { NULL };
 	int ch;
 
-	while ((ch = getopt(argc, argv, "+iu:")) != -1) {
+	while ((ch = getopt(argc, argv, "iu:")) > 0) {
 		switch(ch) {
 		case 'i':
-			ignore_environment = 1;
+			environ = cleanenv;
 			break;
 		case 'u':
 			unsetenv(optarg);
 			break;
 		default:
-			show_usage();
+			bb_show_usage();
 		}
 	}
-	if (optind != argc && !strcmp(argv[optind], "-")) {
-		ignore_environment = 1;
-		argv++;
-	}
-	if (ignore_environment) {
+
+	argv += optind;
+
+	if (*argv && (argv[0][0] == '-') && !argv[0][1]) {
 		environ = cleanenv;
-		cleanenv[0] = NULL;
+		++argv;
 	}
-	for (argv += optind; *argv && (p = strchr(*argv, '=')); ++argv)
-		if (putenv(*argv) < 0)
-			perror_msg_and_die("%s", *argv);
+
+	while (*argv && ((p = strchr(*argv, '=')) != NULL)) {
+		if (putenv(*argv) < 0) {
+			bb_perror_msg_and_die("putenv");
+		}
+		++argv;
+	}
+
 	if (*argv) {
 		execvp(*argv, argv);
-		perror_msg_and_die("%s", *argv);
+		bb_perror_msg("%s", *argv);	/* Avoid multibyte problems. */
+		return (errno == ENOENT) ? 127 : 126;	/* SUSv3-mandated exit codes. */
 	}
-	for (ep = environ; *ep; ep++)
+
+	for (ep = environ; *ep; ep++) {
 		puts(*ep);
-	return 0;
+	}
+
+	bb_fflush_stdout_and_exit(0);
 }
 
 /*

Index: expr.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/expr.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- expr.c	19 Jul 2002 00:05:52 -0000	1.11
+++ expr.c	19 Mar 2003 09:11:33 -0000	1.12
@@ -78,14 +78,14 @@
 	VALUE *v;
 
 	if (argc == 1) {
-		error_msg_and_die("too few arguments");
+		bb_error_msg_and_die("too few arguments");
 	}
 
 	args = argv + 1;
 
 	v = eval ();
 	if (*args)
-		error_msg_and_die ("syntax error");
+		bb_error_msg_and_die ("syntax error");
 
 	if (v->type == integer)
 		printf ("%d\n", v->u.i);
@@ -147,7 +147,7 @@
 static void tostring (VALUE *v)
 {
 	if (v->type == integer) {
-               bb_asprintf (&(v->u.s), "%d", v->u.i);
+               bb_xasprintf (&(v->u.s), "%d", v->u.i);
 		v->type = string;
 	}
 }
@@ -216,7 +216,7 @@
 int name (VALUE *l, VALUE *r)		\
 {						\
   if (!toarith (l) || !toarith (r))		\
-    error_msg_and_die ("non-numeric argument");	\
+    bb_error_msg_and_die ("non-numeric argument");	\
   return l->u.i op r->u.i;			\
 }
 
@@ -224,9 +224,9 @@
 static int name (VALUE *l, VALUE *r)		\
 {						\
   if (!toarith (l) || !toarith (r))		\
-    error_msg_and_die ( "non-numeric argument");	\
+    bb_error_msg_and_die ( "non-numeric argument");	\
   if (r->u.i == 0)				\
-    error_msg_and_die ( "division by zero");		\
+    bb_error_msg_and_die ( "division by zero");		\
   return l->u.i op r->u.i;			\
 }
 
@@ -270,7 +270,7 @@
 	re_syntax_options = RE_SYNTAX_POSIX_BASIC;
 	errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
 	if (errmsg) {
-		error_msg_and_die("%s", errmsg);
+		bb_error_msg_and_die("%s", errmsg);
 	}
 
 	len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
@@ -301,19 +301,19 @@
 	VALUE *v;
 
 	if (!*args)
-		error_msg_and_die ( "syntax error");
+		bb_error_msg_and_die ( "syntax error");
 
 	if (nextarg ("(")) {
 		args++;
 		v = eval ();
 		if (!nextarg (")"))
-			error_msg_and_die ( "syntax error");
+			bb_error_msg_and_die ( "syntax error");
 			args++;
 			return v;
 		}
 
 	if (nextarg (")"))
-		error_msg_and_die ( "syntax error");
+		bb_error_msg_and_die ( "syntax error");
 
 	return str_value (*args++);
 }
@@ -327,7 +327,7 @@
 	if (nextarg ("quote")) {
 		args++;
 		if (!*args)
-			error_msg_and_die ( "syntax error");
+			bb_error_msg_and_die ( "syntax error");
 		return str_value (*args++);
 	}
 	else if (nextarg ("length")) {
@@ -373,7 +373,7 @@
 		else {
 			v = xmalloc (sizeof(VALUE));
 			v->type = string;
-                       v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
+                       v->u.s = bb_xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
 		}
 		freev (l);
 		freev (i1);

Index: false.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/false.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- false.c	24 Oct 2001 19:00:20 -0000	1.1
+++ false.c	19 Mar 2003 09:11:33 -0000	1.2
@@ -21,7 +21,8 @@
  *
  */
 
-/* getopt not needed */
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/false.html */
 
 #include <stdlib.h>
 #include "busybox.h"

Index: head.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/head.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- head.c	27 May 2002 22:24:53 -0000	1.28
+++ head.c	19 Mar 2003 09:11:33 -0000	1.29
@@ -1,9 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini head implementation for busybox
+ * head implementation for busybox
  *
- * Copyright (C) 1999 by Lineo, inc. and John Beppu
- * Copyright (C) 1999,2000,2001 by John Beppu <beppu at codepoet.org>
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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,82 +20,119 @@
  *
  */
 
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */
+
 #include <stdio.h>
-#include <getopt.h>
 #include <stdlib.h>
-#include <string.h>
+#include <limits.h>
 #include <ctype.h>
+#include <unistd.h>
 #include "busybox.h"
 
-static int head(int len, FILE *fp)
-{
-	int i;
-	char *input;
+static const char head_opts[] =
+	"n:"
+#ifdef CONFIG_FEATURE_FANCY_HEAD
+	"c:qv"
+#endif
+	;
 
-	for (i = 0; i < len; i++) {
-		if ((input = get_line_from_file(fp)) == NULL)
-			break;
-		fputs(input, stdout);
-		free(input);
-	}
-	return 0;
-}
+static const char header_fmt_str[] = "\n==> %s <==\n";
 
-/* BusyBoxed head(1) */
 int head_main(int argc, char **argv)
 {
+	unsigned long count = 10;
+	unsigned long i;
+#ifdef CONFIG_FEATURE_FANCY_HEAD
+	int count_bytes = 0;
+	int header_threshhold = 1;
+#endif
+
 	FILE *fp;
-	int need_headers, opt, len = 10, status = EXIT_SUCCESS;
+	const char *fmt;
+	char *p;
+	int opt;
+	int c;
+	int retval = EXIT_SUCCESS;
 
-	if (( argc >= 2 ) && ( argv [1][0] == '-' ) && isdigit ( argv [1][1] )) {
-		len = atoi ( &argv [1][1] );
-		optind = 2;
+	/* Allow legacy syntax of an initial numeric option without -n. */
+	if ((argc > 1) && (argv[1][0] == '-')
+		/* && (isdigit)(argv[1][1]) */
+		&& (((unsigned int)(argv[1][1] - '0')) <= 9)
+	) {
+		--argc;
+		++argv;
+		p = (*argv) + 1;
+		goto GET_COUNT;
 	}
 
-	/* parse argv[] */
-	while ((opt = getopt(argc, argv, "n:")) > 0) {
-		switch (opt) {
-		case 'n':
-			len = atoi(optarg);
-			if (len >= 0)
+	while ((opt = getopt(argc, argv, head_opts)) > 0) {
+		switch(opt) {
+#ifdef CONFIG_FEATURE_FANCY_HEAD
+			case 'q':
+				header_threshhold = INT_MAX;
 				break;
-			/* fallthrough */
-		default:
-			show_usage();
+			case 'v':
+				header_threshhold = -1;
+				break;
+			case 'c':
+				count_bytes = 1;
+				/* fall through */
+#endif
+			case 'n':
+				p = optarg;
+			GET_COUNT:
+				count = bb_xgetularg10(p);
+				break;
+			default:
+				bb_show_usage();
 		}
 	}
 
-	/* get rest of argv[] or stdin if nothing's left */
-	if (argv[optind] == NULL) {
-		head(len, stdin);
-		return status;
-	} 
+	argv += optind;
+	if (!*argv) {
+		*--argv = "-";
+	}
 
-	need_headers = optind != (argc - 1);
-	while (argv[optind]) {
-		if (strcmp(argv[optind], "-") == 0) {
-			fp = stdin;
-			argv[optind] = "standard input";
-		} else {
-			if ((fp = wfopen(argv[optind], "r")) == NULL)
-				status = EXIT_FAILURE;
-		}
-		if (fp) {
-			if (need_headers) {
-				printf("==> %s <==\n", argv[optind]);
+	fmt = header_fmt_str + 1;
+#ifdef CONFIG_FEATURE_FANCY_HEAD
+	if (argc - optind <= header_threshhold) {
+		header_threshhold = 0;
+	}
+#else
+	if (argc <= optind + 1) {
+		fmt += 11;
+	}
+	/* Now define some things here to avoid #ifdefs in the code below.
+	 * These should optimize out of the if conditions below. */
+#define header_threshhold   1
+#define count_bytes         0
+#endif
+
+	do {
+		if ((fp = bb_wfopen_input(*argv)) != NULL) {
+			if (fp == stdin) {
+				*argv = (char *) bb_msg_standard_input;
 			}
-			head(len, fp);
-			if (ferror(fp)) {
-				perror_msg("%s", argv[optind]);
-				status = EXIT_FAILURE;
+			if (header_threshhold) {
+				bb_printf(fmt, *argv);
 			}
-			if (optind < argc - 1)
-				putchar('\n');
-			if (fp != stdin)
-				fclose(fp);
+			i = count;
+			while (i && ((c = getc(fp)) != EOF)) {
+				if (count_bytes || (c == '\n')) {
+					--i;
+				}
+				putchar(c);
+			}
+			if (bb_fclose_nonstdin(fp)) {
+				bb_perror_msg("%s", *argv);	/* Avoid multibyte problems. */
+				retval = EXIT_FAILURE;
+			}
+			bb_xferror_stdout();
 		}
-		optind++;
-	}
+		fmt = header_fmt_str;
+	} while (*++argv);
 
-	return status;
+	bb_fflush_stdout_and_exit(retval);
 }

Index: hostid.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/hostid.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- hostid.c	20 Feb 2001 06:14:07 -0000	1.12
+++ hostid.c	19 Mar 2003 09:11:33 -0000	1.13
@@ -20,13 +20,19 @@
  *
  */
 
-#include <stdio.h>
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
 #include <stdlib.h>
 #include <unistd.h>
 #include "busybox.h"
 
 extern int hostid_main(int argc, char **argv)
 {
-	printf("%lx\n", gethostid());
-	return EXIT_SUCCESS;
+	if (argc > 1) {
+		bb_show_usage();
+	}
+
+	bb_printf("%lx\n", gethostid());
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 }

Index: id.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/id.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- id.c	30 Sep 2002 20:39:55 -0000	1.21
+++ id.c	19 Mar 2003 09:11:33 -0000	1.22
@@ -20,6 +20,8 @@
  *
  */
 
+/* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */
+
 #include "busybox.h"
 #include <stdio.h>
 #include <unistd.h>
@@ -27,70 +29,58 @@
 #include <string.h>
 #include <sys/types.h>
 
+#define NO_GROUP          1
+#define NO_USER           2
+#define PRINT_REAL        4
+#define NAME_NOT_NUMBER   8
+
 extern int id_main(int argc, char **argv)
 {
-	int no_user = 0, no_group = 0, print_real = 0;
-	int name_not_number = 0;
 	char user[9], group[9];
-	long gid;
 	long pwnam, grnam;
-	int opt;
+	int uid, gid;
+	int flags;
 	
-	gid = 0;
+	flags = bb_getopt_ulflags(argc, argv, "ugrn");
 
-	while ((opt = getopt(argc, argv, "ugrn")) > 0) {
-		switch (opt) {
-			case 'u':
-				no_group++;
-				break;
-			case 'g':
-				no_user++;
-				break;
-			case 'r':
-				print_real++;
-				break;
-			case 'n':
-				name_not_number++;
-				break;
-			default:
-				show_usage();
-		}
+	if (((flags & (NO_USER | NO_GROUP)) == (NO_USER | NO_GROUP))
+		|| (argc > optind + 1)
+	) {
+		bb_show_usage();
 	}
 
-	if (no_user && no_group) show_usage();
-
 	if (argv[optind] == NULL) {
-		if (print_real) {
-			my_getpwuid(user, getuid());
-			my_getgrgid(group, getgid());
+		if (flags & PRINT_REAL) {
+			uid = getuid();
+			gid = getgid();
 		} else {
-			my_getpwuid(user, geteuid());
-			my_getgrgid(group, getegid());
+			uid = geteuid();
+			gid = getegid();
 		}
+		my_getpwuid(user, uid);
 	} else {
 		safe_strncpy(user, argv[optind], sizeof(user));
 	    gid = my_getpwnamegid(user);
-		my_getgrgid(group, gid);
 	}
+	my_getgrgid(group, gid);
 
 	pwnam=my_getpwnam(user);
 	grnam=my_getgrnam(group);
 
-	if (no_group) {
-		if(name_not_number)
-			puts(user);
-		else
-			printf("%ld\n", pwnam);
-	} else if (no_user) {
-		if(name_not_number)
-			puts(group);
-		else
+	if (flags & (NO_GROUP | NO_USER)) {
+		char *s = group;
+		if (flags & NO_GROUP) {
+			s = user;
+			grnam = pwnam;
+		}
+		if (flags & NAME_NOT_NUMBER) {
+			puts(s);
+		} else {
 			printf("%ld\n", grnam);
+		}
 	} else {
 		printf("uid=%ld(%s) gid=%ld(%s)\n", pwnam, user, grnam, group);
 	}
-	return(0);
-}
 
-
-/* END CODE */
+	bb_fflush_stdout_and_exit(0);
+}

Index: length.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/length.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- length.c	20 Feb 2001 06:14:07 -0000	1.13
+++ length.c	19 Mar 2003 09:11:33 -0000	1.14
@@ -1,4 +1,7 @@
 /* vi: set sw=4 ts=4: */
+
+/* BB_AUDIT SUSv3 N/A -- Apparently a busybox (obsolete?) extension. */
+
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -6,8 +9,11 @@
 
 extern int length_main(int argc, char **argv)
 {
-	if (argc != 2 || **(argv + 1) == '-')
-		show_usage();
-	printf("%lu\n", (long)strlen(argv[1]));
-	return EXIT_SUCCESS;
+	if ((argc != 2) ||  (**(++argv) == '-')) {
+	    bb_show_usage();
+	}
+
+	bb_printf("%lu\n", (unsigned long)strlen(*argv));
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 }

Index: ln.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/ln.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- ln.c	19 Jul 2002 00:05:41 -0000	1.40
+++ ln.c	19 Mar 2003 09:11:33 -0000	1.41
@@ -21,113 +21,86 @@
  *
  */
 
-#include <stdio.h>
-#include <dirent.h>
-#include <string.h>
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU options missing: -b, -d, -F, -i, -S, and -v. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Fixed bug involving -n option.  Essentially, -n was always in effect.
+ */
+
 #include <stdlib.h>
-#include <errno.h>
 #include <unistd.h>
 #include "busybox.h"
 
+#define LN_SYMLINK          1
+#define LN_FORCE            2
+#define LN_NODEREFERENCE    4
 
-static const int LN_SYMLINK = 1;
-static const int LN_FORCE = 2;
-static const int LN_NODEREFERENCE = 4;
-
-/*
- * linkDestName is where the link points to,
- * linkSrcName is the name of the link to be created.
- */
-static int fs_link(const char *link_destname, const char *link_srcname, 
-		const int flag)
+extern int ln_main(int argc, char **argv)
 {
-	int status;
-	int src_is_dir;
-	char *src_name = 0;
+	int status = EXIT_SUCCESS;
+	int flag;
+	char *last;
+	char *src_name;
 	const char *src;
+	int (*link_func)(const char *, const char *);
 
-	if (link_destname==NULL)
-		return(FALSE);
+	flag = bb_getopt_ulflags(argc, argv, "sfn");
 
-	if (link_srcname==NULL)
-		src = link_destname;
-	else
-		src = link_srcname;
+	if (argc == optind) {
+		bb_show_usage();
+	}
 
-	if (flag&LN_NODEREFERENCE)
-		src_is_dir = is_directory(src, TRUE, NULL);
-	else
-		src_is_dir = is_directory(src, FALSE, NULL);
-	
-	if ((src_is_dir==TRUE)&&((flag&LN_NODEREFERENCE)==0)) {
-		char* srcdir_name;
+	last = argv[argc - 1];
+	argv += optind;
 
-		srcdir_name = xstrdup(link_destname);
-		src_name = concat_path_file(src, get_last_path_component(srcdir_name));
-		src = src_name;
-		free(srcdir_name);
+	if (argc == optind + 1) {
+		*--argv = last;
+		last = bb_get_last_path_component(bb_xstrdup(last));
 	}
-	
-	if (flag&LN_FORCE)
-		unlink(src);
-		
-	if (flag&LN_SYMLINK)
-		status = symlink(link_destname, src);
-	else
-		status = link(link_destname, src);
 
-	if (status != 0) {
-		perror_msg(src);
-		status = FALSE;
-	} else {
-		status = TRUE;
-	}
-	free(src_name);
-	return status;
-}
+	do {
+		src_name = 0;
+		src = last;
 
-extern int ln_main(int argc, char **argv)
-{
-	int status = EXIT_SUCCESS;
-	int flag = 0;
-	int opt;
-	
-	/* Parse any options */
-	while ((opt=getopt(argc, argv, "sfn")) != -1) {
-		switch(opt) {
-			case 's':
-				flag |= LN_SYMLINK;
-				break;
-			case 'f':
-				flag |= LN_FORCE;
-				break;
-			case 'n':
-				flag |= LN_NODEREFERENCE;
-				break;
-			default:
-				show_usage();
+		if (is_directory(src,
+						 (flag & LN_NODEREFERENCE) ^ LN_NODEREFERENCE,
+						 NULL)) {
+			src_name = bb_xstrdup(*argv);
+			src = concat_path_file(src, bb_get_last_path_component(src_name));
+			free(src_name);
+			src_name = (char *)src;
 		}
-	}
-	if (optind > (argc-1)) {
-		show_usage();
-	} 
-	if (optind == (argc-1)) {
-		if (fs_link(argv[optind], 
-					get_last_path_component(argv[optind]), flag)==FALSE)
-			status = EXIT_FAILURE;
-	}
-	while(optind<(argc-1)) {
-		if (fs_link(argv[optind], argv[argc-1], flag)==FALSE)
-			status = EXIT_FAILURE;
-		optind++;
-	}
+
+		if (flag & LN_FORCE) {
+			unlink(src);
+		}
+
+		link_func = link;
+		if (flag & LN_SYMLINK) {
+			link_func = symlink;
+		}
+		
+		if (link_func(*argv, src) != 0) {
+			bb_perror_msg(src);
+			status = EXIT_FAILURE;;
+		}
+
+		free(src_name);
+		
+	} while ((++argv)[1]);
+
 	return status;
 }
 
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
+
+
+
+
+
+
+
+
+

Index: logname.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/logname.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- logname.c	30 Sep 2002 20:39:55 -0000	1.16
+++ logname.c	19 Mar 2003 09:11:33 -0000	1.17
@@ -20,6 +20,19 @@
  *
  */
 
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/logname.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * SUSv3 specifies the string used is that returned from getlogin().
+ * The previous implementation used getpwuid() for geteuid(), which
+ * is _not_ the same.  Erik apparently made this change almost 3 years
+ * ago to avoid failing when no utmp was available.  However, the
+ * correct course of action wrt SUSv3 for a failing getlogin() is
+ * a dianostic message and an error return.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -27,14 +40,16 @@
 
 extern int logname_main(int argc, char **argv)
 {
-	char user[9];
+	const char *p;
 
-	if (argc > 1)
-		show_usage();
+	if (argc > 1) {
+		bb_show_usage();
+	}
 
-	if (my_getpwuid(user, geteuid())) {
-		puts(user);
-		return EXIT_SUCCESS;
+	if ((p = getlogin()) != NULL) {
+		puts(p);
+		bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 	}
-	error_msg_and_die("no login name");
+
+	bb_perror_msg_and_die("getlogin");
 }

Index: ls.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/ls.c,v
retrieving revision 1.96
retrieving revision 1.97
diff -u -d -r1.96 -r1.97
--- ls.c	14 Jan 2003 18:13:13 -0000	1.96
+++ ls.c	19 Mar 2003 09:11:33 -0000	1.97
@@ -73,58 +73,76 @@
 #endif
 
 /* what is the overall style of the listing */
-enum {
-	STYLE_AUTO = 0,
-	STYLE_LONG = 1,		/* one record per line, extended info */
-	STYLE_SINGLE = 2,	/* one record per line */
-	STYLE_COLUMNS = 3	/* fill columns */
-};
+#define STYLE_AUTO      (0)
+#define STYLE_COLUMNS   (1U<<21)	/* fill columns */
+#define STYLE_LONG      (2U<<21)	/* one record per line, extended info */
+#define STYLE_SINGLE    (3U<<21)	/* one record per line */
+
+#define STYLE_MASK                 STYLE_SINGLE
+#define STYLE_ONE_RECORD_FLAG      STYLE_LONG
 
 /* 51306 lrwxrwxrwx  1 root     root         2 May 11 01:43 /bin/view -> vi* */
 /* what file information will be listed */
-#define LIST_INO		(1<<0)
-#define LIST_BLOCKS		(1<<1)
-#define LIST_MODEBITS	(1<<2)
-#define LIST_NLINKS		(1<<3)
-#define LIST_ID_NAME	(1<<4)
-#define LIST_ID_NUMERIC	(1<<5)
-#define LIST_SIZE		(1<<6)
-#define LIST_DEV		(1<<7)
-#define LIST_DATE_TIME	(1<<8)
-#define LIST_FULLTIME	(1<<9)
-#define LIST_FILENAME	(1<<10)
-#define LIST_SYMLINK	(1<<11)
-#define LIST_FILETYPE	(1<<12)
-#define LIST_EXEC		(1<<13)
+#define LIST_INO		(1U<<0)
+#define LIST_BLOCKS		(1U<<1)
+#define LIST_MODEBITS	(1U<<2)
+#define LIST_NLINKS		(1U<<3)
+#define LIST_ID_NAME	(1U<<4)
+#define LIST_ID_NUMERIC	(1U<<5)
+#define LIST_SIZE		(1U<<6)
+#define LIST_DEV		(1U<<7)
+#define LIST_DATE_TIME	(1U<<8)
+#define LIST_FULLTIME	(1U<<9)
+#define LIST_FILENAME	(1U<<10)
+#define LIST_SYMLINK	(1U<<11)
+#define LIST_FILETYPE	(1U<<12)
+#define LIST_EXEC		(1U<<13)
+
+#define LIST_MASK       ((LIST_EXEC << 1) - 1)
 
 /* what files will be displayed */
-#define DISP_NORMAL		(0)	/* show normal filenames */
-#define DISP_DIRNAME	(1<<0)	/* 2 or more items? label directories */
-#define DISP_HIDDEN		(1<<1)	/* show filenames starting with .  */
-#define DISP_DOT		(1<<2)	/* show . and .. */
-#define DISP_NOLIST		(1<<3)	/* show directory as itself, not contents */
-#define DISP_RECURSIVE	(1<<4)	/* show directory and everything below it */
-#define DISP_ROWS		(1<<5)	/* print across rows */
+/* TODO -- We may be able to make DISP_NORMAL 0 to save a bit slot. */
+#define DISP_NORMAL		(1U<<14)	/* show normal filenames */
+#define DISP_DIRNAME	(1U<<15)	/* 2 or more items? label directories */
+#define DISP_HIDDEN		(1U<<16)	/* show filenames starting with .  */
+#define DISP_DOT		(1U<<17)	/* show . and .. */
+#define DISP_NOLIST		(1U<<18)	/* show directory as itself, not contents */
+#define DISP_RECURSIVE	(1U<<19)	/* show directory and everything below it */
+#define DISP_ROWS		(1U<<20)	/* print across rows */
+
+#define DISP_MASK       (((DISP_ROWS << 1) - 1) & ~(DISP_NORMAL - 1))
 
 #ifdef CONFIG_FEATURE_LS_SORTFILES
 /* how will the files be sorted */
-static const int SORT_FORWARD = 0;	/* sort in reverse order */
-static const int SORT_REVERSE = 1;	/* sort in reverse order */
-static const int SORT_NAME = 2;	/* sort by file name */
-static const int SORT_SIZE = 3;	/* sort by file size */
-static const int SORT_ATIME = 4;	/* sort by last access time */
-static const int SORT_CTIME = 5;	/* sort by last change time */
-static const int SORT_MTIME = 6;	/* sort by last modification time */
-static const int SORT_VERSION = 7;	/* sort by version */
-static const int SORT_EXT = 8;	/* sort by file name extension */
-static const int SORT_DIR = 9;	/* sort by file or directory */
+#define SORT_ORDER_FORWARD   0			/* sort in reverse order */
+#define SORT_ORDER_REVERSE   (1U<<27)	/* sort in reverse order */
+
+#define SORT_NAME      0			/* sort by file name */
+#define SORT_SIZE      (1U<<28)		/* sort by file size */
+#define SORT_ATIME     (2U<<28)		/* sort by last access time */
+#define SORT_CTIME     (3U<<28)		/* sort by last change time */
+#define SORT_MTIME     (4U<<28)		/* sort by last modification time */
+#define SORT_VERSION   (5U<<28)		/* sort by version */
+#define SORT_EXT       (6U<<28)		/* sort by file name extension */
+#define SORT_DIR       (7U<<28)		/* sort by file or directory */
+
+#define SORT_MASK      (7U<<28)
 #endif
 
 #ifdef CONFIG_FEATURE_LS_TIMESTAMPS
 /* which of the three times will be used */
-static const int TIME_MOD = 0;
-static const int TIME_CHANGE = 1;
-static const int TIME_ACCESS = 2;
+#define TIME_MOD       0
+#define TIME_CHANGE    (1U<<23)
+#define TIME_ACCESS    (1U<<24)
+
+#define TIME_MASK      (3U<<23)
+#endif
+
+#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
+#define FOLLOW_LINKS   (1U<<25)
+#endif
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+#define LS_DISP_HR     (1U<<26)
 #endif
 
 #define LIST_SHORT	(LIST_FILENAME)
@@ -133,9 +151,9 @@
 						LIST_DATE_TIME | LIST_FILENAME | LIST_SYMLINK)
 #define LIST_ILONG	(LIST_INO | LIST_LONG)
 
-static const int SPLIT_DIR = 0;
-static const int SPLIT_FILE = 1;
-static const int SPLIT_SUBDIR = 2;
+#define SPLIT_DIR      1
+#define SPLIT_FILE     0
+#define SPLIT_SUBDIR   2
 
 #define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
 #define TYPECHAR(mode)  ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
@@ -169,20 +187,7 @@
 static struct dnode **dnalloc(int);
 static int list_single(struct dnode *);
 
-static unsigned int disp_opts;
-static unsigned int style_fmt;
-static unsigned int list_fmt;
-
-#ifdef CONFIG_FEATURE_LS_SORTFILES
-static unsigned int sort_opts;
-static unsigned int sort_order;
-#endif
-#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
-static unsigned int time_fmt;
-#endif
-#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
-static unsigned int follow_links = FALSE;
-#endif
+static unsigned int all_fmt;
 
 #ifdef CONFIG_FEATURE_AUTOWIDTH
 static unsigned short terminal_width = TERMINAL_WIDTH;
@@ -194,26 +199,22 @@
 
 static int status = EXIT_SUCCESS;
 
-#ifdef CONFIG_FEATURE_HUMAN_READABLE
-static unsigned long ls_disp_hr = 0;
-#endif
-
 static struct dnode *my_stat(char *fullname, char *name)
 {
 	struct stat dstat;
 	struct dnode *cur;
 
 #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
-	if (follow_links) {
+	if (all_fmt & FOLLOW_LINKS) {
 		if (stat(fullname, &dstat)) {
-			perror_msg("%s", fullname);
+			bb_perror_msg("%s", fullname);
 			status = EXIT_FAILURE;
 			return 0;
 		}
 	} else
 #endif
 	if (lstat(fullname, &dstat)) {
-		perror_msg("%s", fullname);
+		bb_perror_msg("%s", fullname);
 		status = EXIT_FAILURE;
 	return 0;
 	}
@@ -253,9 +254,9 @@
 #if defined(CONFIG_FEATURE_LS_FILETYPES) || defined(CONFIG_FEATURE_LS_COLOR)
 static char append_char(mode_t mode)
 {
-	if (!(list_fmt & LIST_FILETYPE))
+	if (!(all_fmt & LIST_FILETYPE))
 		return '\0';
-	if ((list_fmt & LIST_EXEC) && S_ISREG(mode)
+	if ((all_fmt & LIST_EXEC) && S_ISREG(mode)
 		&& (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
 		return '*';
 	return APPCHAR(mode);
@@ -263,13 +264,11 @@
 #endif
 
 /*----------------------------------------------------------------------*/
-static int is_subdir(struct dnode *dn)
-{
-	return (S_ISDIR(dn->dstat.st_mode) && strcmp(dn->name, ".") != 0 &&
-			strcmp(dn->name, "..") != 0);
-}
 
-static int countdirs(struct dnode **dn, int nfiles)
+#define countdirs(A,B) count_dirs((A), (B), 1)
+#define countsubdirs(A,B) count_dirs((A), (B), 0)
+
+static int count_dirs(struct dnode **dn, int nfiles, int notsubdirs)
 {
 	int i, dirs;
 
@@ -277,25 +276,17 @@
 		return (0);
 	dirs = 0;
 	for (i = 0; i < nfiles; i++) {
-		if (S_ISDIR(dn[i]->dstat.st_mode))
+		if (S_ISDIR(dn[i]->dstat.st_mode)
+			&& (notsubdirs
+				|| ((dn[i]->name[0] != '.')
+					|| (dn[i]->name[1] 
+						&& ((dn[i]->name[1] != '.')
+							|| dn[i]->name[2])))))
 			dirs++;
 	}
 	return (dirs);
 }
 
-static int countsubdirs(struct dnode **dn, int nfiles)
-{
-	int i, subdirs;
-
-	if (dn == NULL || nfiles < 1)
-		return 0;
-	subdirs = 0;
-	for (i = 0; i < nfiles; i++)
-		if (is_subdir(dn[i]))
-			subdirs++;
-	return subdirs;
-}
-
 static int countfiles(struct dnode **dnp)
 {
 	int nfiles;
@@ -364,18 +355,18 @@
 
 	/* copy the entrys into the file or dir array */
 	for (d = i = 0; i < nfiles; i++) {
-		if (which == SPLIT_DIR) {
-			if (S_ISDIR(dn[i]->dstat.st_mode)) {
-				dnp[d++] = dn[i];
-			}			/* else skip the file */
-		} else if (which == SPLIT_SUBDIR) {
-			if (is_subdir(dn[i])) {
-				dnp[d++] = dn[i];
-			}			/* else skip the file or dir */
-		} else {
-			if (!(S_ISDIR(dn[i]->dstat.st_mode))) {
-				dnp[d++] = dn[i];
-			}			/* else skip the dir */
+		if (S_ISDIR(dn[i]->dstat.st_mode)) {
+			if (which & (SPLIT_DIR|SPLIT_SUBDIR)) {
+				if ((which & SPLIT_DIR)
+					|| ((dn[i]->name[0] != '.')
+						|| (dn[i]->name[1]
+							&& ((dn[i]->name[1] != '.')
+								|| dn[i]->name[2])))) {
+									dnp[d++] = dn[i];
+								}
+			}
+		} else if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) {
+			dnp[d++] = dn[i];
 		}
 	}
 	return (dnp);
@@ -385,29 +376,24 @@
 #ifdef CONFIG_FEATURE_LS_SORTFILES
 static int sortcmp(struct dnode *d1, struct dnode *d2)
 {
-	int cmp, dif;
+	unsigned int sort_opts = all_fmt & SORT_MASK;
+	int dif;
 
-	cmp = 0;
+	dif = 0;			/* assume SORT_NAME */
 	if (sort_opts == SORT_SIZE) {
-		dif = (int) (d1->dstat.st_size - d2->dstat.st_size);
+		dif = (int) (d2->dstat.st_size - d1->dstat.st_size);
 	} else if (sort_opts == SORT_ATIME) {
-		dif = (int) (d1->dstat.st_atime - d2->dstat.st_atime);
+		dif = (int) (d2->dstat.st_atime - d1->dstat.st_atime);
 	} else if (sort_opts == SORT_CTIME) {
-		dif = (int) (d1->dstat.st_ctime - d2->dstat.st_ctime);
+		dif = (int) (d2->dstat.st_ctime - d1->dstat.st_ctime);
 	} else if (sort_opts == SORT_MTIME) {
-		dif = (int) (d1->dstat.st_mtime - d2->dstat.st_mtime);
+		dif = (int) (d2->dstat.st_mtime - d1->dstat.st_mtime);
 	} else if (sort_opts == SORT_DIR) {
-		dif = S_ISDIR(d1->dstat.st_mode) - S_ISDIR(d2->dstat.st_mode);
+		dif = S_ISDIR(d2->dstat.st_mode) - S_ISDIR(d1->dstat.st_mode);
 		/* } else if (sort_opts == SORT_VERSION) { */
 		/* } else if (sort_opts == SORT_EXT) { */
-	} else {			/* assume SORT_NAME */
-		dif = 0;
 	}
 
-	if (dif > 0)
-		cmp = -1;
-	if (dif < 0)
-		cmp = 1;
 	if (dif == 0) {
 		/* sort by name- may be a tie_breaker for time or size cmp */
 #ifdef CONFIG_LOCALE_SUPPORT
@@ -415,16 +401,12 @@
 #else
 		dif = strcmp(d1->name, d2->name);
 #endif
-		if (dif > 0)
-			cmp = 1;
-		if (dif < 0)
-			cmp = -1;
 	}
 
-	if (sort_order == SORT_REVERSE) {
-		cmp = -1 * cmp;
+	if (all_fmt & SORT_ORDER_REVERSE) {
+		dif = -dif;
 	}
-	return (cmp);
+	return (dif);
 }
 
 /*----------------------------------------------------------------------*/
@@ -463,20 +445,17 @@
 	if (dn == NULL || nfiles < 1)
 		return;
 
-	switch (style_fmt) {
-	case STYLE_LONG:        /* one record per line, extended info */
-	case STYLE_SINGLE:      /* one record per line */
+	if (all_fmt & STYLE_ONE_RECORD_FLAG) {
 		ncols = 1;
-		break;
-	default:
-	/* find the longest file name-  use that as the column width */
-	for (i = 0; i < nfiles; i++) {
+	} else {
+		/* find the longest file name-  use that as the column width */
+		for (i = 0; i < nfiles; i++) {
 			int len = strlen(dn[i]->name) +
-			((list_fmt & LIST_INO) ? 8 : 0) +
-			((list_fmt & LIST_BLOCKS) ? 5 : 0);
-		if (column_width < len)
-			column_width = len;
-	}
+			((all_fmt & LIST_INO) ? 8 : 0) +
+			((all_fmt & LIST_BLOCKS) ? 5 : 0);
+			if (column_width < len)
+				column_width = len;
+		}
 		column_width += tabstops;
 		ncols = (int) (terminal_width / column_width);
 	}
@@ -494,7 +473,7 @@
 		for (nc = 0; nc < ncols; nc++) {
 			/* reach into the array based on the column and row */
 			i = (nc * nrows) + row;	/* assume display by column */
-			if (disp_opts & DISP_ROWS)
+			if (all_fmt & DISP_ROWS)
 				i = (row * ncols) + nc;	/* display across row */
 			if (i < nfiles) {
 				if (column > 0) {
@@ -528,7 +507,7 @@
 		return;
 
 	for (i = 0; i < ndirs; i++) {
-		if (disp_opts & (DISP_DIRNAME | DISP_RECURSIVE)) {
+		if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) {
 			printf("\n%s:\n", dn[i]->fullname);
 		}
 		subdnp = list_dir(dn[i]->fullname);
@@ -540,7 +519,7 @@
 #endif
 			showfiles(subdnp, nfiles);
 #ifdef CONFIG_FEATURE_LS_RECURSIVE
-			if (disp_opts & DISP_RECURSIVE) {
+			if (all_fmt & DISP_RECURSIVE) {
 				/* recursive- list the sub-dirs */
 				dnd = splitdnarray(subdnp, nfiles, SPLIT_SUBDIR);
 				dndirs = countsubdirs(subdnp, nfiles);
@@ -573,7 +552,7 @@
 	nfiles = 0;
 	dir = opendir(path);
 	if (dir == NULL) {
-		perror_msg("%s", path);
+		bb_perror_msg("%s", path);
 		status = EXIT_FAILURE;
 		return (NULL);	/* could not open the dir */
 	}
@@ -585,9 +564,9 @@
 			if ((entry->d_name[1] == 0 || (
 				entry->d_name[1] == '.'
 				&& entry->d_name[2] == 0))
-					&& !(disp_opts & DISP_DOT))
+					&& !(all_fmt & DISP_DOT))
 			continue;
-			if (!(disp_opts & DISP_HIDDEN))
+			if (!(all_fmt & DISP_HIDDEN))
 			continue;
 		}
 		fullname = concat_path_file(path, entry->d_name);
@@ -636,9 +615,9 @@
 
 #ifdef CONFIG_FEATURE_LS_TIMESTAMPS
 	ttime = dn->dstat.st_mtime;	/* the default time */
-	if (time_fmt & TIME_ACCESS)
+	if (all_fmt & TIME_ACCESS)
 		ttime = dn->dstat.st_atime;
-	if (time_fmt & TIME_CHANGE)
+	if (all_fmt & TIME_CHANGE)
 		ttime = dn->dstat.st_ctime;
 	filetime = ctime(&ttime);
 #endif
@@ -647,7 +626,7 @@
 #endif
 
 	for (i = 0; i <= 31; i++) {
-		switch (list_fmt & (1 << i)) {
+		switch (all_fmt & (1 << i)) {
 		case LIST_INO:
 			column += printf("%7ld ", (long int) dn->dstat.st_ino);
 			break;
@@ -659,7 +638,7 @@
 #endif
 			break;
 		case LIST_MODEBITS:
-			column += printf("%-10s ", (char *) mode_string(dn->dstat.st_mode));
+			column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
 			break;
 		case LIST_NLINKS:
 			column += printf("%4ld ", (long) dn->dstat.st_nlink);
@@ -683,7 +662,7 @@
 					   (int) MINOR(dn->dstat.st_rdev));
 			} else {
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
-				if (ls_disp_hr == TRUE) {
+				if (all_fmt & LS_DISP_HR) {
 					column += printf("%9s ",
 							make_human_readable_str(dn->dstat.st_size, 1, 0));
 				} else
@@ -700,7 +679,7 @@
 #ifdef CONFIG_FEATURE_LS_TIMESTAMPS
 		case LIST_FULLTIME:
 		case LIST_DATE_TIME:
-			if (list_fmt & LIST_FULLTIME) {
+			if (all_fmt & LIST_FULLTIME) {
 				printf("%24.24s ", filetime);
 				column += 25;
 				break;
@@ -774,47 +753,8 @@
 }
 
 /*----------------------------------------------------------------------*/
-extern int ls_main(int argc, char **argv)
-{
-	struct dnode **dnf, **dnd;
-	int dnfiles, dndirs;
-	struct dnode *dn, *cur, **dnp;
-	int i, nfiles;
-	int opt;
-	int oi, ac;
-	char **av;
-
-#ifdef CONFIG_FEATURE_AUTOWIDTH
-	struct winsize win = { 0, 0, 0, 0 };
-#endif
 
-	disp_opts = DISP_NORMAL;
-	style_fmt = STYLE_AUTO;
-	list_fmt = LIST_SHORT;
-#ifdef CONFIG_FEATURE_LS_SORTFILES
-	sort_opts = SORT_NAME;
-	sort_order = SORT_FORWARD;
-#endif
-#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
-	time_fmt = TIME_MOD;
-#endif
-#ifdef CONFIG_FEATURE_AUTOWIDTH
-	ioctl(fileno(stdout), TIOCGWINSZ, &win);
-	if (win.ws_col > 0)
-		terminal_width = win.ws_col - 1;
-#endif
-	nfiles = 0;
-
-#ifdef CONFIG_FEATURE_LS_COLOR
-	if (isatty(fileno(stdout)))
-		show_color = 1;
-#endif
-
-	/* process options */
-	while ((opt = getopt(argc, argv, "1AaCdgilnsx"
-#ifdef CONFIG_FEATURE_AUTOWIDTH
-						 "T:w:"
-#endif
+static const char ls_opts[] = "1AaCdgilnsx"
 #ifdef CONFIG_FEATURE_LS_FILETYPES
 						 "Fp"
 #endif
@@ -825,7 +765,7 @@
 						 "rSvX"
 #endif
 #ifdef CONFIG_FEATURE_LS_TIMESTAMPS
-						 "cetu"
+						 "ecut"
 #endif
 #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
 						 "L"
@@ -833,141 +773,180 @@
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
 						 "h"
 #endif
-						 "k")) > 0) {
-		switch (opt) {
-		case '1':
-			style_fmt = STYLE_SINGLE;
-			list_fmt = LIST_SHORT;
-			break;
-		case 'A':
-			disp_opts |= DISP_HIDDEN;
-			break;
-		case 'a':
-			disp_opts |= DISP_HIDDEN | DISP_DOT;
-			break;
-		case 'C':
-			style_fmt = STYLE_COLUMNS;
-			list_fmt = LIST_SHORT;
-			break;
-		case 'd':
-			disp_opts |= DISP_NOLIST;
-			break;
-		case 'g':		/* ignore -- for ftp servers */
-			break;
-		case 'i':
-			list_fmt |= LIST_INO;
-			break;
-		case 'l':
-			style_fmt = STYLE_LONG;
-			list_fmt |= LIST_LONG;
-#ifdef CONFIG_FEATURE_HUMAN_READABLE
-			ls_disp_hr = FALSE;
+						 "k"
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+						 "T:w:"
 #endif
-			break;
-		case 'n':
-			list_fmt |= LIST_ID_NUMERIC;
-			break;
-		case 's':
-			list_fmt |= LIST_BLOCKS;
-			break;
-		case 'x':
-			disp_opts = DISP_ROWS;
-			break;
+	;
+
+#define LIST_MASK_TRIGGER   LIST_SHORT
+#define STYLE_MASK_TRIGGER  STYLE_MASK
+#define SORT_MASK_TRIGGER   SORT_MASK
+#define DISP_MASK_TRIGGER   DISP_ROWS
+#define TIME_MASK_TRIGGER   TIME_MASK
+
+static const unsigned opt_flags[] = {
+	LIST_SHORT | STYLE_SINGLE,	/* 1 */
+	DISP_HIDDEN,				/* A */
+	DISP_HIDDEN | DISP_DOT,		/* a */
+	LIST_SHORT | STYLE_COLUMNS,	/* C */
+	DISP_NOLIST,				/* d */
+	0,							/* g - ingored */
+	LIST_INO,					/* i */
+	LIST_LONG | STYLE_LONG,		/* l - remember LS_DISP_HR in mask! */
+	LIST_ID_NUMERIC,			/* n */
+	LIST_BLOCKS,				/* s */
+	DISP_ROWS,					/* x */
 #ifdef CONFIG_FEATURE_LS_FILETYPES
-		case 'F':
-			list_fmt |= LIST_FILETYPE | LIST_EXEC;
-			break;
-		case 'p':
-			list_fmt |= LIST_FILETYPE;
-			break;
+	LIST_FILETYPE | LIST_EXEC,	/* F */
+	LIST_FILETYPE,				/* p */
 #endif
 #ifdef CONFIG_FEATURE_LS_RECURSIVE
-		case 'R':
-			disp_opts |= DISP_RECURSIVE;
-			break;
+	DISP_RECURSIVE,				/* R */
 #endif
 #ifdef CONFIG_FEATURE_LS_SORTFILES
-		case 'r':
-			sort_order |= SORT_REVERSE;
-			break;
-		case 'S':
-			sort_opts = SORT_SIZE;
-			break;
-		case 'v':
-			sort_opts = SORT_VERSION;
-			break;
-		case 'X':
-			sort_opts = SORT_EXT;
-			break;
+	SORT_ORDER_REVERSE,			/* r */
+	SORT_SIZE,					/* S */
+	SORT_VERSION,				/* v */
+	SORT_EXT,					/* v */
 #endif
 #ifdef CONFIG_FEATURE_LS_TIMESTAMPS
-		case 'e':
-			list_fmt |= LIST_FULLTIME;
-			break;
-		case 'c':
-			time_fmt = TIME_CHANGE;
+	LIST_FULLTIME,				/* e */
 #ifdef CONFIG_FEATURE_LS_SORTFILES
-			sort_opts = SORT_CTIME;
+	TIME_CHANGE | SORT_CTIME,	/* c */
+#else
+	TIME_CHANGE,				/* c */
 #endif
-			break;
-		case 'u':
-			time_fmt = TIME_ACCESS;
 #ifdef CONFIG_FEATURE_LS_SORTFILES
-			sort_opts = SORT_ATIME;
+	TIME_ACCESS | SORT_ATIME,	/* u */
+#else
+	TIME_ACCESS,				/* u */
 #endif
-			break;
-		case 't':
 #ifdef CONFIG_FEATURE_LS_SORTFILES
-			sort_opts = SORT_MTIME;
+	SORT_MTIME,					/* t */
+#else
+	0,							/* t - ignored -- is this correct? */
 #endif
-			break;
 #endif
 #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
-		case 'L':
-			follow_links = TRUE;
-			break;
+	FOLLOW_LINKS,				/* L */
+#endif
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+LS_DISP_HR,						/* h */
 #endif
+	0,							/* k - ingored */
+};
+
+
+/*----------------------------------------------------------------------*/
+
+extern int ls_main(int argc, char **argv)
+{
+	struct dnode **dnf, **dnd;
+	int dnfiles, dndirs;
+	struct dnode *dn, *cur, **dnp;
+	int i, nfiles;
+	int opt;
+	int oi, ac;
+	char **av;
+
 #ifdef CONFIG_FEATURE_AUTOWIDTH
-		case 'T':
+	struct winsize win = { 0, 0, 0, 0 };
+#endif
+
+	all_fmt = LIST_SHORT | DISP_NORMAL | STYLE_AUTO
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+		| TIME_MOD
+#endif
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+		| SORT_NAME | SORT_ORDER_FORWARD
+#endif
+		;
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+	ioctl(fileno(stdout), TIOCGWINSZ, &win);
+	if (win.ws_col > 0)
+		terminal_width = win.ws_col - 1;
+#endif
+	nfiles = 0;
+
+#ifdef CONFIG_FEATURE_LS_COLOR
+	if (isatty(fileno(stdout)))
+		show_color = 1;
+#endif
+
+	/* process options */
+	while ((opt = getopt(argc, argv, ls_opts)) > 0) {
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+		if (opt == 'T') {
 			tabstops = atoi(optarg);
-			break;
-		case 'w':
+			continue;
+		}
+		if (opt == 'w') {
 			terminal_width = atoi(optarg);
-			break;
+			continue;
+		}
+		if (opt == ':') {
+			goto print_usage_message;
+		}
 #endif
+		{
+			unsigned int flags;
+			const char *p = strchr(ls_opts, opt);
+			if (!p) {	/* shouldn't be necessary */
+				goto print_usage_message;
+			}
+			flags = opt_flags[(int)(p - ls_opts)];
+			if (flags & LIST_MASK_TRIGGER) {
+				all_fmt &= ~LIST_MASK;
+			}
+			if (flags & STYLE_MASK_TRIGGER) {
+				all_fmt &= ~STYLE_MASK;
+			}
+			if (flags & SORT_MASK_TRIGGER) {
+				all_fmt &= ~SORT_MASK;
+			}
+			if (flags & DISP_MASK_TRIGGER) {
+				all_fmt &= ~DISP_MASK;
+			}
+			if (flags & TIME_MASK_TRIGGER) {
+				all_fmt &= ~TIME_MASK;
+			}
 #ifdef CONFIG_FEATURE_HUMAN_READABLE
-		case 'h':
-			ls_disp_hr = TRUE;
-			break;
+			if (opt == 'l') {
+				all_fmt &= ~LS_DISP_HR;
+			}
 #endif
-		case 'k':
-			break;
-		default:
-			goto print_usage_message;
+			all_fmt |= flags;
 		}
 	}
 
+
 	/* sort out which command line options take precedence */
 #ifdef CONFIG_FEATURE_LS_RECURSIVE
-	if (disp_opts & DISP_NOLIST)
-		disp_opts &= ~DISP_RECURSIVE;	/* no recurse if listing only dir */
+	if (all_fmt & DISP_NOLIST)
+		all_fmt &= ~DISP_RECURSIVE;	/* no recurse if listing only dir */
 #endif
 #if defined (CONFIG_FEATURE_LS_TIMESTAMPS) && defined (CONFIG_FEATURE_LS_SORTFILES)
-	if (time_fmt & TIME_CHANGE)
-		sort_opts = SORT_CTIME;
-	if (time_fmt & TIME_ACCESS)
-		sort_opts = SORT_ATIME;
+	if (all_fmt & TIME_CHANGE)
+		all_fmt = (all_fmt & ~SORT_MASK) | SORT_CTIME;
+	if (all_fmt & TIME_ACCESS)
+		all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME;
 #endif
-	if (style_fmt != STYLE_LONG) /* only for long list */
-		list_fmt &= ~(LIST_ID_NUMERIC|LIST_FULLTIME|LIST_ID_NAME|LIST_ID_NUMERIC);
+	if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* only for long list */
+		all_fmt &= ~(LIST_ID_NUMERIC|LIST_FULLTIME|LIST_ID_NAME|LIST_ID_NUMERIC);
 #ifdef CONFIG_FEATURE_LS_USERNAME
-	if (style_fmt == STYLE_LONG && (list_fmt & LIST_ID_NUMERIC))
-		list_fmt &= ~LIST_ID_NAME;	/* don't list names if numeric uid */
+	if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC))
+		all_fmt &= ~LIST_ID_NAME;	/* don't list names if numeric uid */
 #endif
-
+			
 	/* choose a display format */
-	if (style_fmt == STYLE_AUTO)
-		style_fmt = isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE;
+	if ((all_fmt & STYLE_MASK) == STYLE_AUTO)
+#if STYLE_AUTO != 0
+		all_fmt = (all_fmt & ~STYLE_MASK)
+				| (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE);
+#else
+		all_fmt |= (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE);
+#endif
 
 	/*
 	 * when there are no cmd line args we have to supply a default "." arg.
@@ -979,7 +958,7 @@
 	ac = argc - optind;	/* how many cmd line args are left */
 	if (ac < 1) {
 		av = (char **) xcalloc((size_t) 1, (size_t) (sizeof(char *)));
-		av[0] = xstrdup(".");
+		av[0] = bb_xstrdup(".");
 		ac = 1;
 	} else {
 		av = (char **) xcalloc((size_t) ac, (size_t) (sizeof(char *)));
@@ -990,12 +969,12 @@
 
 	/* now, everything is in the av array */
 	if (ac > 1)
-		disp_opts |= DISP_DIRNAME;	/* 2 or more items? label directories */
+		all_fmt |= DISP_DIRNAME;	/* 2 or more items? label directories */
 
 	/* stuff the command line file names into an dnode array */
 	dn = NULL;
 	for (oi = 0; oi < ac; oi++) {
-		char *fullname = xstrdup(av[oi]);
+		char *fullname = bb_xstrdup(av[oi]);
 
 		cur = my_stat(fullname, fullname);
 		if (!cur)
@@ -1015,7 +994,7 @@
 	}
 
 
-	if (disp_opts & DISP_NOLIST) {
+	if (all_fmt & DISP_NOLIST) {
 #ifdef CONFIG_FEATURE_LS_SORTFILES
 		shellsort(dnp, nfiles);
 #endif
@@ -1042,5 +1021,5 @@
 	return (status);
 
   print_usage_message:
-	show_usage();
+	bb_show_usage();
 }

Index: md5sum.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/md5sum.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- md5sum.c	11 Jul 2002 11:11:49 -0000	1.27
+++ md5sum.c	19 Mar 2003 09:11:33 -0000	1.28
@@ -770,13 +770,13 @@
     have_read_stdin = 1;
     fp = stdin;
   } else {
-    fp = wfopen(filename, "r");
+    fp = bb_wfopen(filename, "r");
     if (fp == NULL)
       return FALSE;
     }
 
   if (md5_stream(fp, md5_result)) {
-    perror_msg("%s", filename);
+    bb_perror_msg("%s", filename);
 
     if (fp != stdin)
       fclose(fp);
@@ -784,7 +784,7 @@
   }
 
   if (fp != stdin && fclose(fp) == EOF) {
-    perror_msg("%s", filename);
+    bb_perror_msg("%s", filename);
     return FALSE;
   }
 
@@ -805,7 +805,7 @@
     have_read_stdin = 1;
     checkfile_stream = stdin;
   } else {
-    checkfile_stream = wfopen(checkfile_name, "r");
+    checkfile_stream = bb_wfopen(checkfile_name, "r");
     if (checkfile_stream == NULL)
       return FALSE;
     }
@@ -836,7 +836,7 @@
     if (split_3(line, line_length, &md5num, &filename)
         || !hex_digits(md5num)) {
       if (warn) {
-        error_msg("%s: %lu: improperly formatted MD5 checksum line",
+        bb_error_msg("%s: %lu: improperly formatted MD5 checksum line",
                  checkfile_name, (unsigned long) line_number);
       }
     } else {
@@ -881,18 +881,18 @@
   while (!feof(checkfile_stream) && !ferror(checkfile_stream));
 
   if (ferror(checkfile_stream)) {
-    error_msg("%s: read error", checkfile_name);
+    bb_error_msg("%s: read error", checkfile_name);
     return FALSE;
   }
 
   if (checkfile_stream != stdin && fclose(checkfile_stream) == EOF) {
-    perror_msg("md5sum: %s", checkfile_name);
+    bb_perror_msg("md5sum: %s", checkfile_name);
     return FALSE;
   }
 
   if (n_properly_formated_lines == 0) {
     /* Warn if no tests are found.  */
-    error_msg("%s: no properly formatted MD5 checksum lines found",
+    bb_error_msg("%s: no properly formatted MD5 checksum lines found",
              checkfile_name);
     return FALSE;
   } else {
@@ -901,13 +901,13 @@
                                  - n_open_or_read_failures);
 
       if (n_open_or_read_failures > 0) {
-        error_msg("WARNING: %d of %d listed files could not be read",
+        bb_error_msg("WARNING: %d of %d listed files could not be read",
                  n_open_or_read_failures, n_properly_formated_lines);
         return FALSE;
       }
 
       if (n_mismatched_checksums > 0) {
-        error_msg("WARNING: %d of %d computed checksums did NOT match",
+        bb_error_msg("WARNING: %d of %d computed checksums did NOT match",
                  n_mismatched_checksums, n_computed_checkums);
         return FALSE;
       }
@@ -965,31 +965,31 @@
       break;
 
      default:
-      show_usage();
+      bb_show_usage();
     }
   }
 
   if (file_type_specified && do_check) {
-    error_msg_and_die("the -b and -t options are meaningless when verifying checksums");
+    bb_error_msg_and_die("the -b and -t options are meaningless when verifying checksums");
   }
 
   if (n_strings > 0 && do_check) {
-    error_msg_and_die("the -g and -c options are mutually exclusive");
+    bb_error_msg_and_die("the -g and -c options are mutually exclusive");
   }
 
   if (status_only && !do_check) {
-    error_msg_and_die("the -s option is meaningful only when verifying checksums");
+    bb_error_msg_and_die("the -s option is meaningful only when verifying checksums");
   }
 
   if (warn && !do_check) {
-    error_msg_and_die("the -w option is meaningful only when verifying checksums");
+    bb_error_msg_and_die("the -w option is meaningful only when verifying checksums");
   }
 
   if (n_strings > 0) {
     size_t i;
 
     if (optind < argc) {
-      error_msg_and_die("no files may be specified when using -g");
+      bb_error_msg_and_die("no files may be specified when using -g");
     }
     for (i = 0; i < n_strings; ++i) {
       size_t cnt;
@@ -1002,7 +1002,7 @@
     }
   } else if (do_check) {
     if (optind + 1 < argc) {
-      error_msg("only one argument may be specified when using -c");
+      bb_error_msg("only one argument may be specified when using -c");
     }
 
     err = md5_check ((optind == argc) ? "-" : argv[optind]);
@@ -1060,11 +1060,11 @@
   }
 
   if (fclose (stdout) == EOF) {
-    error_msg_and_die("write error");
+    bb_error_msg_and_die("write error");
   }
 
   if (have_read_stdin && fclose (stdin) == EOF) {
-    error_msg_and_die("standard input");
+    bb_error_msg_and_die(bb_msg_standard_input);
   }
 
   if (err == 0)

Index: mkdir.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/mkdir.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- mkdir.c	24 Nov 2002 22:48:20 -0000	1.33
+++ mkdir.c	19 Mar 2003 09:11:33 -0000	1.34
@@ -20,46 +20,50 @@
  *
  */
 
-#include <errno.h>
-#include <getopt.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/mkdir.html */
 
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Fixed broken permission setting when -p was used; especially in
+ * conjunction with -m.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
 #include "busybox.h"
 
 extern int mkdir_main (int argc, char **argv)
 {
-	mode_t mode = -1;
+	mode_t mode = (mode_t)(-1);
+	int status = EXIT_SUCCESS;
 	int flags = 0;
-	int i, opt;
+	int opt;
 
-	while ((opt = getopt (argc, argv, "m:p")) != -1) {
-		switch (opt) {
-		case 'm':
+	while ((opt = getopt (argc, argv, "m:p")) > 0) {
+		if (opt == 'm') {
 			mode = 0777;
-			if (!parse_mode (optarg, &mode)) {
-				error_msg_and_die ("invalid mode `%s'", optarg);
+			if (!bb_parse_mode (optarg, &mode)) {
+				bb_error_msg_and_die ("invalid mode `%s'", optarg);
 			}
-			umask(0);
-			break;
-		case 'p':
+		} else if (opt == 'p') {
 			flags |= FILEUTILS_RECUR;
-			break;
-		default:
-			show_usage ();
+		} else {
+			bb_show_usage();
 		}
 	}
 
-	if (optind == argc)
-		show_usage ();
-
-	for (i = optind; i < argc; i++) {
-		make_directory (argv[i], mode, flags);
+	if (optind == argc) {
+		bb_show_usage();
 	}
 
-	return(EXIT_SUCCESS);
+	argv += optind;
+
+	do {
+		if (bb_make_directory(*argv, mode, flags)) {
+			status = EXIT_FAILURE;
+		}
+	} while (*++argv);
+
+	return status;
 }

Index: mkfifo.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/mkfifo.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- mkfifo.c	20 Feb 2001 06:14:07 -0000	1.14
+++ mkfifo.c	19 Mar 2003 09:11:33 -0000	1.15
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini mkfifo implementation for busybox
+ * mkfifo implementation for busybox
  *
- * Copyright (C) 1999 by Randolph Chung <tausq at debian.org>
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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
@@ -20,41 +20,32 @@
  *
  */
 
-#include <stdio.h>
-#include <sys/types.h>
-#include <errno.h>
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/mkfifo.html */
+
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
 #include "busybox.h"
+#include "libcoreutils/coreutils.h"
 
 extern int mkfifo_main(int argc, char **argv)
 {
-	char *thisarg;
-	mode_t mode = 0666;
+	mode_t mode;
+	int retval = EXIT_SUCCESS;
 
-	argc--;
-	argv++;
+	mode = getopt_mk_fifo_nod(argc, argv);
 
-	/* Parse any options */
-	while (argc > 1) {
-		if (**argv != '-')
-			show_usage();
-		thisarg = *argv;
-		thisarg++;
-		switch (*thisarg) {
-		case 'm':
-			argc--;
-			argv++;
-			parse_mode(*argv, &mode);
-			break;
-		default:
-			show_usage();
-		}
-		argc--;
-		argv++;
+	if (!*(argv += optind)) {
+		bb_show_usage();
 	}
-	if (argc < 1 || *argv[0] == '-')
-		show_usage();
-	if (mkfifo(*argv, mode) < 0)
-		perror_msg_and_die("mkfifo");
-	return EXIT_SUCCESS;
+
+	do {
+		if (mkfifo(*argv, mode) < 0) {
+			bb_perror_msg("%s", *argv);	/* Avoid multibyte problems. */
+			retval = EXIT_FAILURE;
+		}
+	} while (*++argv);
+
+	return retval;
 }

Index: mknod.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/mknod.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- mknod.c	23 Aug 2002 03:37:07 -0000	1.23
+++ mknod.c	19 Mar 2003 09:11:33 -0000	1.24
@@ -1,9 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini mknod implementation for busybox
+ * mknod implementation for busybox
  *
- * Copyright (C) 1995, 1996 by Bruce Perens <bruce at pixar.com>.
- * Copyright (C) 1999-2002 by Erik Andersen <andersee at debian.org>
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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,73 +20,44 @@
  *
  */
 
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
 #include <stdlib.h>
-#include <sys/types.h>
+#include <string.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include "busybox.h"
+#include "libcoreutils/coreutils.h"
 
-int mknod_main(int argc, char **argv)
+static const char modes_chars[] = { 'p', 'c', 'u', 'b', 0, 1, 1, 2 };
+static const mode_t modes_cubp[] = { S_IFIFO, S_IFCHR, S_IFBLK };
+
+extern int mknod_main(int argc, char **argv)
 {
-	char *thisarg;
-	mode_t mode = 0;
-	mode_t perm = 0666;
-	dev_t dev = (dev_t) 0;
+	mode_t mode;
+	dev_t dev;
+	const char *name;
 
-	argc--;
-	argv++;
+	mode = getopt_mk_fifo_nod(argc, argv);
+	argv += optind;
+	argc -= optind;
 
-	/* Parse any options */
-	while (argc > 1) {
-		if (**argv != '-')
-			break;
-		thisarg = *argv;
-		thisarg++;
-		switch (*thisarg) {
-		case 'm':
-			argc--;
-			argv++;
-			parse_mode(*argv, &perm);
-			umask(0);
-			break;
-		default:
-			show_usage();
+	if ((argc >= 2) && ((name = strchr(modes_chars, argv[1][0])) != NULL)) {
+		mode |= modes_cubp[(int)(name[4])];
+
+		dev = 0;
+		if ((*name != 'p') && ((argc -= 2) == 0)) {
+			dev = (bb_xgetularg10_bnd(argv[2], 0, 255) << 8)
+				+ bb_xgetularg10_bnd(argv[3], 0, 255);
 		}
-		argc--;
-		argv++;
-	}
-	if (argc != 4 && argc != 2) {
-		show_usage();
-	}
-	switch (argv[1][0]) {
-	case 'c':
-	case 'u':
-		mode = S_IFCHR;
-		break;
-	case 'b':
-		mode = S_IFBLK;
-		break;
-	case 'p':
-		mode = S_IFIFO;
-		if (argc != 2) {
-			show_usage();
+	
+		if (argc == 2) {
+			name = *argv;
+			if (mknod(name, mode, dev) == 0) {
+				return EXIT_SUCCESS;
+			}
+			bb_perror_msg_and_die("%s", name);
 		}
-		break;
-	default:
-		show_usage();
 	}
-
-	if (mode == S_IFCHR || mode == S_IFBLK) {
-		dev = (dev_t) ((atoi(argv[2]) << 8) | atoi(argv[3]));
-	}
-
-	mode |= perm;
-
-	if (mknod(argv[0], mode, dev) != 0)
-		perror_msg_and_die("%s", argv[0]);
-	return EXIT_SUCCESS;
+	bb_show_usage();
 }

Index: mv.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/mv.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- mv.c	5 Oct 2001 01:35:08 -0000	1.17
+++ mv.c	19 Mar 2003 09:11:33 -0000	1.18
@@ -2,7 +2,6 @@
 /*
  * Mini mv implementation for busybox
  *
- *
  * Copyright (C) 2000 by Matt Kraai <kraai at alumni.carnegiemellon.edu>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,148 +20,122 @@
  *
  */
 
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Size reduction and improved error checking.
+ */
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <dirent.h>
 #include <errno.h>
 #include <stdlib.h>
-
 #include "busybox.h"
+#include "libcoreutils/coreutils.h"
 
-static int flags;
+static const char *fmt = "cannot overwrite %sdirectory with %sdirectory";
 
-static int manual_rename(const char *source, const char *dest)
+extern int mv_main(int argc, char **argv)
 {
 	struct stat source_stat;
 	struct stat dest_stat;
-	int source_exists = 1;
-	int dest_exists = 1;
+	const char *last;
+	const char *dest;
+	int dest_exists;
+	int source_exists;
+	int opt;
+	int flags = 0;
+	int status = 0;
 
-	if (stat(source, &source_stat) < 0) {
-		if (errno != ENOENT) {
-			perror_msg("unable to stat `%s'", source);
-			return -1;
+	while ((opt = getopt(argc, argv, "fi")) > 0) {
+		flags &= ~(FILEUTILS_INTERACTIVE | FILEUTILS_FORCE);
+		if (opt == 'i') {
+			flags |= FILEUTILS_INTERACTIVE;
+		} else if (opt == 'f') {
+			flags |= FILEUTILS_FORCE;
+		} else {
+			bb_show_usage();
 		}
-		source_exists = 0;
 	}
 
-	if (stat(dest, &dest_stat) < 0) {
-		if (errno != ENOENT) {
-			perror_msg("unable to stat `%s'", dest);
-			return -1;
-		}
-		dest_exists = 0;
-	}
+	if (optind + 2 > argc)
+		bb_show_usage();
 
-	if (dest_exists) {
-		if (S_ISDIR(dest_stat.st_mode) &&
-			  (!source_exists || !S_ISDIR(source_stat.st_mode))) {
-			error_msg("cannot overwrite directory with non-directory");
-			return -1;
-		}
+	last = argv[argc - 1];
+	argv += optind;
 
-		if (!S_ISDIR(dest_stat.st_mode) && source_exists &&
-				S_ISDIR(source_stat.st_mode)) {
-			error_msg("cannot overwrite non-directory with directory");
-			return -1;
+	if (optind + 2 == argc) {
+		if ((dest_exists = cp_mv_stat(last, &dest_stat)) < 0) {
+			return 1;
 		}
 
-		if (unlink(dest) < 0) {
-			perror_msg("cannot remove `%s'", dest);
-			return -1;
+		if (!(dest_exists & 2)) {
+			dest = last;
+			goto DO_MOVE;
 		}
 	}
+	
+	do {
+		dest = concat_path_file(last,
+								bb_get_last_path_component(*argv));
 
-	if (copy_file(source, dest,
-			FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) < 0)
-		return -1;
-
-	if (remove_file(source, FILEUTILS_RECUR | FILEUTILS_FORCE) < 0)
-		return -1;
-
-	return 0;
-}
-
-static int move_file(const char *source, const char *dest)
-{
-	struct stat dest_stat;
-	int dest_exists = 1;
-
-	if (stat(dest, &dest_stat) < 0) {
-		if (errno != ENOENT) {
-			perror_msg("unable to stat `%s'", dest);
-			return -1;
+		if ((dest_exists = cp_mv_stat(dest, &dest_stat)) < 0) {
+			goto RET_1;
 		}
-		dest_exists = 0;
-	}
 
-	if (dest_exists && !(flags & FILEUTILS_FORCE) &&
+	DO_MOVE:
+		
+		if (dest_exists && !(flags & FILEUTILS_FORCE) &&
 			((access(dest, W_OK) < 0 && isatty(0)) ||
 			 (flags & FILEUTILS_INTERACTIVE))) {
-		fprintf(stderr, "mv: overwrite `%s'? ", dest);
-		if (!ask_confirmation())
-			return 0;
-	}
-
-	if (rename(source, dest) < 0) {
-		if (errno == EXDEV)
-			return manual_rename(source, dest);
-
-		perror_msg("unable to rename `%s'", source);
-		return -1;
-	}
-	
-	return 0;
-}
-
-extern int mv_main(int argc, char **argv)
-{
-	int status = 0;
-	int opt;
-	int i;
-
-	while ((opt = getopt(argc, argv, "fi")) != -1)
-		switch (opt) {
-		case 'f':
-			flags &= ~FILEUTILS_INTERACTIVE;
-			flags |= FILEUTILS_FORCE;
-			break;
-		case 'i':
-			flags &= ~FILEUTILS_FORCE;
-			flags |= FILEUTILS_INTERACTIVE;
-			break;
-		default:
-			show_usage();
-		}
-
-	if (optind + 2 > argc)
-		show_usage();
-
-	if (optind + 2 == argc) {
-		struct stat dest_stat;
-		int dest_exists = 1;
-
-		if (stat(argv[optind + 1], &dest_stat) < 0) {
-			if (errno != ENOENT)
-				perror_msg_and_die("unable to stat `%s'", argv[optind + 1]);
-			dest_exists = 0;
+				 if (fprintf(stderr, "mv: overwrite `%s'? ", dest) < 0) {
+					 goto RET_1;	/* Ouch! fprintf failed! */
+				 }
+				 if (!bb_ask_confirmation())
+					 goto RET_0;
+		 }
+		
+		if (rename(*argv, dest) < 0) {
+			if (errno != EXDEV) {
+				bb_perror_msg("unable to rename `%s'", *argv);
+			} else if ((source_exists = cp_mv_stat(*argv, &source_stat)) >= 0) {
+				if (dest_exists) {
+					if (dest_exists & 2) {
+						if (!(source_exists & 2)) {
+							bb_error_msg(fmt, "", "non-");
+							goto RET_1;
+						}
+					} else {
+						if (source_exists & 2) {
+							bb_error_msg(fmt, "non-", "");
+							goto RET_1;
+						}
+					}
+					if (unlink(dest) < 0) {
+						bb_perror_msg("cannot remove `%s'", dest);
+						goto RET_1;
+					}
+				}
+				
+				if ((copy_file(*argv, dest,
+							   FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0)
+					&& (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)
+					) {
+					goto RET_0;
+				}
+				
+			}
+		RET_1:
+			status = 1;
 		}
 
-		if (!dest_exists || !S_ISDIR(dest_stat.st_mode)) {
-			if (move_file(argv[optind], argv[optind + 1]) < 0)
-				status = 1;
-			return status;
+	RET_0:
+		if (dest != last) {
+			free((void *) dest);
 		}
-	}
-
-	for (i = optind; i < argc - 1; i++) {
-		char *dest = concat_path_file(argv[argc - 1],
-				get_last_path_component(argv[i]));
-		if (move_file(argv[i], dest) < 0)
-			status = 1;
-		free(dest);
-	}
-
-	return status;
+		
+	} while (*++argv != last);
+	
+	exit(status);
 }

Index: od.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/od.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- od.c	10 Nov 2002 22:16:09 -0000	1.4
+++ od.c	19 Mar 2003 09:11:33 -0000	1.5
@@ -23,22 +23,18 @@
  */
 
 #include <ctype.h>
+#include <string.h>
 #include <getopt.h>
 #include <stdlib.h>
-#include "dump.h"
 #include "busybox.h"
+#include "dump.h"
 
-extern FS *fshead;				/* head of format strings */
-extern int blocksize;				/* data block size */
-extern int length;			/* max bytes to read */
-
-#define	ishexdigit(c) \
-	((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
+#define isdecdigit(c) (isdigit)(c)
+#define ishexdigit(c) (isxdigit)(c)
 
 static void
 odoffset(int argc, char ***argvp)
 {
-	extern off_t skip;
 	register char *num, *p;
 	int base;
 	char *end;
@@ -62,13 +58,15 @@
 		return;
 	}
 
-	if (*p != '+' && (argc < 2 ||
-	    (!isdigit(p[0]) && (p[0] != 'x' || !ishexdigit(p[1])))))
+	if ((*p != '+')
+		&& (argc < 2
+			|| (!isdecdigit(p[0])
+				&& ((p[0] != 'x') || !ishexdigit(p[1])))))
 		return;
 
 	base = 0;
 	/*
-	 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
+	 * bb_dump_skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
 	 * set base.
 	 */
 	if (p[0] == '+')
@@ -81,11 +79,11 @@
 		base = 16;
 	}
 
-	/* skip over the number */
+	/* bb_dump_skip over the number */
 	if (base == 16)
 		for (num = p; ishexdigit(*p); ++p);
 	else
-		for (num = p; isdigit(*p); ++p);
+		for (num = p; isdecdigit(*p); ++p);
 
 	/* check for no number */
 	if (num == p)
@@ -98,21 +96,23 @@
 		base = 10;
 	}
 
-	skip = strtol(num, &end, base ? base : 8);
+	bb_dump_skip = strtol(num, &end, base ? base : 8);
 
 	/* if end isn't the same as p, we got a non-octal digit */
 	if (end != p)
-		skip = 0;
+		bb_dump_skip = 0;
 	else {
 		if (*p) {
-			if (*p == 'b')
-				skip *= 512;
-			else if (*p == 'B')
-				skip *= 1024;
-			++p;
+			if (*p == 'b') {
+				bb_dump_skip *= 512;
+				++p;
+			} else if (*p == 'B') {
+				bb_dump_skip *= 1024;
+				++p;
+			}
 		}
 		if (*p)
-			skip = 0;
+			bb_dump_skip = 0;
 		else {
 			++*argvp;
 			/*
@@ -121,117 +121,76 @@
 			 * but it's easy.
 			 */
 #define	TYPE_OFFSET	7
-			if (base == 16) {
-				fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
-				fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
-			} else if (base == 10) {
-				fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
-				fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
+			{
+				char x_or_d;
+				if (base == 16) {
+					x_or_d = 'x';
+					goto DO_X_OR_D;
+				}
+				if (base == 10) {
+					x_or_d = 'd';
+				DO_X_OR_D:
+					bb_dump_fshead->nextfu->fmt[TYPE_OFFSET]
+						= bb_dump_fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
+						= x_or_d;
+				}
 			}
 		}
 	}
 }
 
-static void odprecede(void)
-{
-	static int first = 1;
+static const char * const add_strings[] = {
+	"16/1 \"%3_u \" \"\\n\"",				/* a */
+	"8/2 \" %06o \" \"\\n\"",				/* B, o */
+	"16/1 \"%03o \" \"\\n\"",				/* b */
+	"16/1 \"%3_c \" \"\\n\"",				/* c */
+	"8/2 \"  %05u \" \"\\n\"",				/* d */
+	"4/4 \"     %010u \" \"\\n\"",			/* D */
+	"2/8 \"          %21.14e \" \"\\n\"",	/* e (undocumented in od), F */
+	"4/4 \" %14.7e \" \"\\n\"",				/* f */
+	"4/4 \"       %08x \" \"\\n\"",			/* H, X */
+	"8/2 \"   %04x \" \"\\n\"",				/* h, x */
+	"4/4 \"    %11d \" \"\\n\"",			/* I, L, l */
+	"8/2 \" %6d \" \"\\n\"",				/* i */
+	"4/4 \"    %011o \" \"\\n\"",			/* O */
+};
 
-	if (first) {
-		first = 0;
-		add("\"%07.7_Ao\n\"");
-		add("\"%07.7_ao  \"");
-	} else
-		add("\"         \"");
-}
+static const signed char od_opts[] = "aBbcDdeFfHhIiLlOovXx";
+
+static const signed char od_o2si[] = {
+	0, 1, 2, 3, 5,
+	4, 6, 6, 7, 8,
+	9, 0xa, 0xb, 0xa, 0xa,
+	0xb, 1, -1, 8, 9,
+};
 
 int od_main(int argc, char **argv)
 {
 	int ch;
-	extern enum _vflag vflag;
-	vflag = FIRST;
-	length = -1;
+	bb_dump_vflag = FIRST;
+	bb_dump_length = -1;
+	int first = 1;
+	signed char *p;
 
-	while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != EOF)
-		switch (ch) {
-		case 'a':
-			odprecede();
-			add("16/1 \"%3_u \" \"\\n\"");
-			break;
-		case 'B':
-		case 'o':
-			odprecede();
-			add("8/2 \" %06o \" \"\\n\"");
-			break;
-		case 'b':
-			odprecede();
-			add("16/1 \"%03o \" \"\\n\"");
-			break;
-		case 'c':
-			odprecede();
-			add("16/1 \"%3_c \" \"\\n\"");
-			break;
-		case 'd':
-			odprecede();
-			add("8/2 \"  %05u \" \"\\n\"");
-			break;
-		case 'D':
-			odprecede();
-			add("4/4 \"     %010u \" \"\\n\"");
-			break;
-		case 'e':		/* undocumented in od */
-		case 'F':
-			odprecede();
-			add("2/8 \"          %21.14e \" \"\\n\"");
-			break;
-			
-		case 'f':
-			odprecede();
-			add("4/4 \" %14.7e \" \"\\n\"");
-			break;
-		case 'H':
-		case 'X':
-			odprecede();
-			add("4/4 \"       %08x \" \"\\n\"");
-			break;
-		case 'h':
-		case 'x':
-			odprecede();
-			add("8/2 \"   %04x \" \"\\n\"");
-			break;
-		case 'I':
-		case 'L':
-		case 'l':
-			odprecede();
-			add("4/4 \"    %11d \" \"\\n\"");
-			break;
-		case 'i':
-			odprecede();
-			add("8/2 \" %6d \" \"\\n\"");
-			break;
-		case 'O':
-			odprecede();
-			add("4/4 \"    %011o \" \"\\n\"");
-			break;
-		case 'v':
-			vflag = ALL;
-			break;
-		case 'P':
-		case 'p':
-		case 's':
-		case 'w':
-		case '?':
-		default:
-			error_msg("od: od(1) has been deprecated for hexdump(1).\n");
-			if (ch != '?') {
-				error_msg("od: hexdump(1) compatibility doesn't support the -%c option%s\n",
-				    ch, ch == 's' ? "; see strings(1)." : ".");
+	while ((ch = getopt(argc, argv, od_opts)) > 0) {
+		if (((p = strchr(od_opts, ch)) != NULL) && (*p >= 0)) {
+			if (first) {
+				first = 0;
+				bb_dump_add("\"%07.7_Ao\n\"");
+				bb_dump_add("\"%07.7_ao  \"");
+			} else {
+				bb_dump_add("\"         \"");
 			}
-			show_usage();
+			bb_dump_add(add_strings[od_o2si[(int)(p-od_opts)]]);
+		} else if (ch == 'v') {
+			bb_dump_vflag = ALL;
+		} else {	/* P, p, s, w, or other unhandled */
+			bb_show_usage();
 		}
-
-	if (!fshead) {
-		add("\"%07.7_Ao\n\"");
-		add("\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
+	}
+	if (!bb_dump_fshead) {
+		bb_dump_add("\"%07.7_Ao\n\"");
+		bb_dump_add("\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
 	}
 
 	argc -= optind;
@@ -239,7 +198,7 @@
 
 	odoffset(argc, &argv);
 
-	return(dump(argv));
+	return(bb_dump_dump(argv));
 }
 
 /*-

Index: printf.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/printf.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- printf.c	19 Mar 2001 19:25:49 -0000	1.17
+++ printf.c	19 Mar 2003 09:11:33 -0000	1.18
@@ -124,7 +124,7 @@
 
 	exit_status = 0;
 	if (argc <= 1 || **(argv + 1) == '-') {
-		show_usage();
+		bb_show_usage();
 	}
 
 	format = argv[1];

Index: pwd.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/pwd.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- pwd.c	13 Apr 2002 08:31:58 -0000	1.22
+++ pwd.c	19 Mar 2003 09:11:33 -0000	1.23
@@ -20,24 +20,18 @@
  *
  */
 
-/* getopt not needed */
-
 #include <stdio.h>
-#include <dirent.h>
-#include <errno.h>
-#include <unistd.h>
 #include <stdlib.h>
 #include "busybox.h"
 
 extern int pwd_main(int argc, char **argv)
 {
-	static char *buf; 
-	
-	buf = xgetcwd(buf);
-	
-	if (buf != NULL) {
+	char *buf;
+
+	if ((buf = xgetcwd(NULL)) != NULL) {
 		puts(buf);
-		return EXIT_SUCCESS;
+		bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 	}
+
 	return EXIT_FAILURE;
 }

Index: realpath.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/realpath.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- realpath.c	10 Dec 2002 03:16:37 -0000	1.2
+++ realpath.c	19 Mar 2003 09:11:33 -0000	1.3
@@ -14,17 +14,26 @@
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+/* BB_AUDIT SUSv3 N/A -- Apparently a busybox extension. */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Now does proper error checking on output and returns a failure exit code
+ * if one or more paths can not be resolved.
+ */
+
 #include <limits.h>
 #include <stdlib.h>
-
 #include "busybox.h"
 
 int realpath_main(int argc, char **argv)
 {
+	int retval = EXIT_SUCCESS;
+
 	RESERVE_CONFIG_BUFFER(resolved_path, PATH_MAX);
 
 	if (--argc == 0) {
-		show_usage();
+		bb_show_usage();
 	}
 
 	do {
@@ -32,11 +41,14 @@
 		if (realpath(*argv, resolved_path) != NULL) {
 			puts(resolved_path);
 		} else {
-			perror_msg("%s", *argv);
+			retval = EXIT_FAILURE;
+			bb_perror_msg("%s", *argv);
 		}
 	} while (--argc);
 
+#ifdef CONFIG_FEATURE_CLEAN_UP
 	RELEASE_CONFIG_BUFFER(resolved_path);
+#endif
 
-	return(EXIT_SUCCESS);
+	bb_fflush_stdout_and_exit(retval);
 }

Index: rm.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/rm.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- rm.c	29 Jun 2001 18:59:31 -0000	1.35
+++ rm.c	19 Mar 2003 09:11:33 -0000	1.36
@@ -2,7 +2,6 @@
 /*
  * Mini rm implementation for busybox
  *
- *
  * Copyright (C) 2001 Matt Kraai <kraai at alumni.carnegiemellon.edu>
  *
  *
@@ -22,55 +21,51 @@
  *
  */
 
-#include <stdio.h>
-#include <time.h>
-#include <utime.h>
-#include <dirent.h>
-#include <errno.h>
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/rm.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Size reduction.
+ */
+
 #include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
 #include "busybox.h"
 
 extern int rm_main(int argc, char **argv)
 {
 	int status = 0;
-	int opt;
 	int flags = 0;
-	int i;
+	int opt;
 
-	while ((opt = getopt(argc, argv, "fiRr")) != -1) {
-		switch (opt) {
-		case 'f':
-			flags &= ~FILEUTILS_INTERACTIVE;
-			flags |= FILEUTILS_FORCE;
-			break;
-		case 'i':
-			flags &= ~FILEUTILS_FORCE;
-			flags |= FILEUTILS_INTERACTIVE;
-			break;
-		case 'R':
-		case 'r':
+	while ((opt = getopt(argc, argv, "fiRr")) > 0) {
+		if ((opt == 'r') || (opt == 'R')) {
 			flags |= FILEUTILS_RECUR;
-			break;
+		} else {
+			flags &= ~(FILEUTILS_INTERACTIVE | FILEUTILS_FORCE);
+			if (opt == 'i') {
+				flags |= FILEUTILS_INTERACTIVE;
+			} else if (opt == 'f') {
+				flags |= FILEUTILS_FORCE;
+			} else {
+				bb_show_usage();
+			}
 		}
 	}
 
-	if (!(flags & FILEUTILS_FORCE) && optind == argc)
-		show_usage();
-
-	for (i = optind; i < argc; i++) {
-		char *base = get_last_path_component(argv[i]);
-
-		if (strcmp(base, ".") == 0 || strcmp(base, "..") == 0) {
-			error_msg("cannot remove `.' or `..'");
-			status = 1;
-			continue;
-		}
+	if (*(argv += optind) != NULL) {
+		do {
+			const char *base = bb_get_last_path_component(*argv);
 
-		if (remove_file(argv[i], flags) < 0)
+			if ((base[0] == '.') && (!base[1] || ((base[1] == '.') && !base[2]))) {
+				bb_error_msg("cannot remove `.' or `..'");
+			} else if (remove_file(*argv, flags) >= 0) {
+				continue;
+			}
 			status = 1;
+		} while (*++argv);
+	} else if (!(flags & FILEUTILS_FORCE)) {
+		bb_show_usage();
 	}
 
 	return status;

Index: rmdir.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/rmdir.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- rmdir.c	24 Oct 2001 04:59:27 -0000	1.22
+++ rmdir.c	19 Mar 2003 09:11:33 -0000	1.23
@@ -1,9 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini rmdir implementation for busybox
+ * rmdir implementation for busybox
  *
- * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
- * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee at debian.org>
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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,76 +20,54 @@
  *
  */
 
-#include <getopt.h>
-#include <unistd.h>
-#include <stdlib.h>
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */
 
+#include <stdlib.h>
+#include <unistd.h>
+#include <libgen.h>
 #include "busybox.h"
 
-
-/* Return true if a path is composed of multiple components.  */
-
-static int
-multiple_components_p (const char *path)
+extern int rmdir_main(int argc, char **argv)
 {
-	const char *s = path;
-
-	while (s[0] != '\0' && s[0] != '/')
-		s++;
-
-	while (s[0] == '/')
-		s++;
-
-	return (s[0] != '\0');
-}
-
+	int status = EXIT_SUCCESS;
+	int flags;
+	int do_dot;
+	char *path;
 
-/* Remove a directory.  Returns 0 if successful, -1 on error.  */
+	flags = bb_getopt_ulflags(argc, argv, "p");
 
-static int
-remove_directory (char *path, int flags)
-{
-	if (!(flags & FILEUTILS_RECUR)) {
-		if (rmdir (path) < 0) {
-			perror_msg ("unable to remove `%s'", path);
-			return -1;
-		}
-	} else {
-		if (remove_directory (path, 0) < 0)
-			return -1;
+	argv += optind;
 
-		if (multiple_components_p (path))
-			if (remove_directory (dirname (path), flags) < 0)
-				return -1;
+	if (!*argv) {
+		bb_show_usage();
 	}
 
-	return 0;
-}
-
-
-extern int
-rmdir_main (int argc, char **argv)
-{
-	int status = EXIT_SUCCESS;
-	int flags = 0;
-	int i, opt;
-
-	while ((opt = getopt (argc, argv, "p")) != -1)
-		switch (opt) {
-			case 'p':
-				flags |= FILEUTILS_RECUR;
-				break;
-
-			default:
-				show_usage ();
-		}
+	do {
+		path = *argv;
 
-	if (optind == argc)
-		show_usage();
+		/* Record if the first char was a '.' so we can use dirname later. */
+		do_dot = (*path == '.');
 
-	for (i = optind; i < argc; i++)
-		if (remove_directory (argv[i], flags) < 0)
-			status = EXIT_FAILURE;
+		do {
+			if (rmdir(path) < 0) {
+				bb_perror_msg("`%s'", path);	/* Match gnu rmdir msg. */
+				status = EXIT_FAILURE;
+			} else if (flags) {
+				/* Note: path was not empty or null since rmdir succeeded. */
+				path = dirname(path);
+				/* Path is now just the parent component.  Note that dirname
+				 * returns "." if there are no parents.  We must distinguish
+				 * this from the case of the original path starting with '.'.
+                 */
+				if (do_dot || (*path != '.') || path[1]) {
+					continue;
+				}
+			}
+			break;
+		} while (1);
+		
+	} while (*++argv);
 
 	return status;
 }

Index: sha1sum.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/sha1sum.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- sha1sum.c	17 Feb 2003 12:18:16 -0000	1.2
+++ sha1sum.c	19 Mar 2003 09:11:33 -0000	1.3
@@ -187,7 +187,7 @@
 			break;
 #endif
 		default:
-			show_usage();
+			bb_show_usage();
 		}
 	}
 
@@ -204,7 +204,7 @@
 				hash_ptr(stdin, hashval);
 				print_hash(hash_length, hashval, NULL);
 			} else {
-				FILE *stream = xfopen(argv[i], "r");
+				FILE *stream = bb_xfopen(argv[i], "r");
 				hash_ptr(stream, hashval);
 				fclose(stream);
 				print_hash(hash_length, hashval, argv[i]);

Index: sleep.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/sleep.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- sleep.c	13 Apr 2002 08:31:58 -0000	1.16
+++ sleep.c	19 Mar 2003 09:11:34 -0000	1.17
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini sleep implementation for busybox
+ * sleep implementation for busybox
  *
- * Copyright (C) 1995, 1996 by Bruce Perens <bruce at pixar.com>.
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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
@@ -20,18 +20,67 @@
  *
  */
 
-#include <stdio.h>
-#include <unistd.h>
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/sleep.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Rewritten to do proper arg and error checking.
+ * Also, added a 'fancy' configuration to accept multiple args with
+ * time suffixes for seconds, minutes, hours, and days.
+ */
+
 #include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
 #include "busybox.h"
 
+#ifdef CONFIG_FEATURE_FANCY_SLEEP
+static const struct suffix_mult sleep_suffixes[] = {
+	{ "s", 1 },
+	{ "m", 60 },
+	{ "h", 60*60 },
+	{ "d", 24*60*60 },
+	{ NULL, 0 }
+};
+#endif
+
 extern int sleep_main(int argc, char **argv)
 {
-	if ((argc < 2) || (**(argv + 1) == '-')) {
-		show_usage();
+	unsigned int duration;
+
+#ifdef CONFIG_FEATURE_FANCY_SLEEP
+
+	if (argc < 2) {
+		bb_show_usage();
+	}
+
+	++argv;
+	duration = 0;
+	do {
+		duration += bb_xgetularg_bnd_sfx(*argv, 10,
+										 0, UINT_MAX-duration,
+										 sleep_suffixes);
+	} while (*++argv);
+
+#else  /* CONFIG_FEATURE_FANCY_SLEEP */
+
+	if (argc != 2) {
+		bb_show_usage();
+	}
+
+#if UINT_MAX == ULONG_MAX
+	duration = bb_xgetularg10(argv[1]);
+#else
+	duration = bb_xgetularg10_bnd(argv[1], 0, UINT_MAX);
+#endif
+
+#endif /* CONFIG_FEATURE_FANCY_SLEEP */
+
+	if (sleep(duration)) {
+		bb_perror_nomsg_and_die();
 	}
 
-	if (sleep(atoi(*(++argv))) != 0)
-		perror_msg_and_die("sleep");
 	return EXIT_SUCCESS;
 }

Index: sort.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/sort.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- sort.c	24 Oct 2001 05:00:27 -0000	1.34
+++ sort.c	19 Mar 2003 09:11:34 -0000	1.35
@@ -2,7 +2,6 @@
 /*
  * Mini sort implementation for busybox
  *
- *
  * Copyright (C) 2000 by Matt Kraai <kraai at alumni.carnegiemellon.edu>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,10 +20,20 @@
  *
  */
 
-#include <getopt.h>
-#include <string.h>
+/* BB_AUDIT SUSv3 _NOT_ compliant -- a number of options are not supported. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Now does proper error checking on i/o.  Plus some space savings.
+ */
+
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include "busybox.h"
+#include "libcoreutils/coreutils.h"
 
 static int compare_ascii(const void *x, const void *y)
 {
@@ -41,66 +50,51 @@
 {
 	FILE *fp;
 	char *line, **lines = NULL;
-	int i, opt, nlines = 0;
+	int i, nlines = 0, inc;
 	int (*compare)(const void *, const void *) = compare_ascii;
-#ifdef CONFIG_FEATURE_SORT_REVERSE
-	int reverse = FALSE;
-#endif
-#ifdef CONFIG_FEATURE_SORT_UNIQUE
-	int unique = FALSE;
-#endif
 
-	while ((opt = getopt(argc, argv, "nru")) != -1) {
-		switch (opt) {
-			case 'n':
-				compare = compare_numeric;
-				break;
-#ifdef CONFIG_FEATURE_SORT_REVERSE
-			case 'r':
-				reverse = TRUE;
-				break;
-#endif
-#ifdef CONFIG_FEATURE_SORT_UNIQUE
-			case 'u':
-				unique = TRUE;
-				break;
-#endif
-			default:
-				show_usage();
-		}
+	int flags;
+
+	bb_default_error_retval = 2;
+
+	flags = bb_getopt_ulflags(argc, argv, "nru");
+	if (flags & 1) {
+		compare = compare_numeric;
 	}
 
-	/* read the input */
-	for (i = optind; i == optind || i < argc; i++) {
-		if (argv[i] == NULL)
-			fp = stdin;
-		else
-			fp = xfopen(argv[i], "r");
+	argv += optind;
+	if (!*argv) {
+		*--argv = "-";
+	}
 
-		while ((line = get_line_from_file(fp)) != NULL) {
+	do {
+		fp = xgetoptfile_sort_uniq(argv, "r");
+		while ((line = bb_get_chomped_line_from_file(fp)) != NULL) {
 			lines = xrealloc(lines, sizeof(char *) * (nlines + 1));
-			chomp(line);
 			lines[nlines++] = line;
 		}
-	}
+		bb_xferror(fp, *argv);
+		bb_fclose_nonstdin(fp);
+	} while (*++argv);
 
 	/* sort it */
 	qsort(lines, nlines, sizeof(char *), compare);
 
 	/* print it */
-#ifdef CONFIG_FEATURE_SORT_REVERSE
-	if (reverse) {
-		for (i = --nlines; 0 <= i; i--)
-#ifdef CONFIG_FEATURE_SORT_UNIQUE
-			if((!unique) || (i == nlines) || (strcmp(lines[i + 1], lines[i])))
-#endif
-				puts(lines[i]);
-	} else
-#endif
-		for (i = 0; i < nlines; i++)
-#ifdef CONFIG_FEATURE_SORT_UNIQUE
-			if((!unique) || (!i) || (strcmp(lines[i - 1], lines[i])))
-#endif
-				puts(lines[i]);
-	return EXIT_SUCCESS;
+	i = 0;
+	--nlines;
+	if ((inc = 1 - (flags & 2)) < 0) {	/* reverse */
+		i = nlines;
+	}
+	flags &= 4;
+
+	while (nlines >= 0) {
+		if (!flags || !nlines || strcmp(lines[i+inc], lines[i])) {
+			puts(lines[i]);
+		}
+		i += inc;
+		--nlines;
+	}
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 }

Index: stty.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/stty.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- stty.c	6 Jun 2002 11:35:29 -0000	1.7
+++ stty.c	19 Mar 2003 09:11:34 -0000	1.8
@@ -30,9 +30,9 @@
 
 //#define TEST
 
+#include <stddef.h>
 #include <termios.h>
 #include <sys/ioctl.h>
-#include <getopt.h>
 
 #include <sys/param.h>
 #include <unistd.h>
@@ -155,13 +155,10 @@
 	input_speed, output_speed, both_speeds
 };
 
-/* What to output and how.  */
-enum output_type {
-	changed, all, recoverable       /* Default, -a, -g.  */
-};
-
 /* Which member(s) of `struct termios' a mode uses.  */
 enum mode_type {
+	/* Do NOT change the order or values, as mode_type_flag()
+	 * depends on them. */
 	control, input, output, local, combination
 };
 
@@ -199,156 +196,159 @@
 /* Each mode.  */
 struct mode_info {
 	const char *name;       /* Name given on command line.           */
-	enum mode_type type;    /* Which structure element to change.    */
+	/* enum mode_type type; */
+	char type;              /* Which structure element to change.    */
 	char flags;             /* Setting and display options.          */
+	unsigned short mask;     /* Other bits to turn off for this mode. */
 	unsigned long bits;     /* Bits to set for this mode.            */
-	unsigned long mask;     /* Other bits to turn off for this mode. */
 };
 
+#define MI_ENTRY(N,T,F,B,M) { N, T, F, M, B }
+
 static const struct  mode_info mode_info[] = {
-	{"parenb",   control,     REV,               PARENB,     0 },
-	{"parodd",   control,     REV,               PARODD,     0 },
-	{"cs5",      control,     0,                 CS5,     CSIZE},
-	{"cs6",      control,     0,                 CS6,     CSIZE},
-	{"cs7",      control,     0,                 CS7,     CSIZE},
-	{"cs8",      control,     0,                 CS8,     CSIZE},
-	{"hupcl",    control,     REV,               HUPCL,      0 },
-	{"hup",      control,     REV        | OMIT, HUPCL,      0 },
-	{"cstopb",   control,     REV,               CSTOPB,     0 },
-	{"cread",    control,     SANE_SET   | REV,  CREAD,      0 },
-	{"clocal",   control,     REV,               CLOCAL,     0 },
+	MI_ENTRY("parenb",   control,     REV,               PARENB,     0 ),
+	MI_ENTRY("parodd",   control,     REV,               PARODD,     0 ),
+	MI_ENTRY("cs5",      control,     0,                 CS5,     CSIZE),
+	MI_ENTRY("cs6",      control,     0,                 CS6,     CSIZE),
+	MI_ENTRY("cs7",      control,     0,                 CS7,     CSIZE),
+	MI_ENTRY("cs8",      control,     0,                 CS8,     CSIZE),
+	MI_ENTRY("hupcl",    control,     REV,               HUPCL,      0 ),
+	MI_ENTRY("hup",      control,     REV        | OMIT, HUPCL,      0 ),
+	MI_ENTRY("cstopb",   control,     REV,               CSTOPB,     0 ),
+	MI_ENTRY("cread",    control,     SANE_SET   | REV,  CREAD,      0 ),
+	MI_ENTRY("clocal",   control,     REV,               CLOCAL,     0 ),
 #ifdef CRTSCTS
-	{"crtscts",  control,     REV,               CRTSCTS,    0 },
+	MI_ENTRY("crtscts",  control,     REV,               CRTSCTS,    0 ),
 #endif
-	{"ignbrk",   input,       SANE_UNSET | REV,  IGNBRK,     0 },
-	{"brkint",   input,       SANE_SET   | REV,  BRKINT,     0 },
-	{"ignpar",   input,       REV,               IGNPAR,     0 },
-	{"parmrk",   input,       REV,               PARMRK,     0 },
-	{"inpck",    input,       REV,               INPCK,      0 },
-	{"istrip",   input,       REV,               ISTRIP,     0 },
-	{"inlcr",    input,       SANE_UNSET | REV,  INLCR,      0 },
-	{"igncr",    input,       SANE_UNSET | REV,  IGNCR,      0 },
-	{"icrnl",    input,       SANE_SET   | REV,  ICRNL,      0 },
-	{"ixon",     input,       REV,               IXON,       0 },
-	{"ixoff",    input,       SANE_UNSET | REV,  IXOFF,      0 },
-	{"tandem",   input,       REV        | OMIT, IXOFF,      0 },
+	MI_ENTRY("ignbrk",   input,       SANE_UNSET | REV,  IGNBRK,     0 ),
+	MI_ENTRY("brkint",   input,       SANE_SET   | REV,  BRKINT,     0 ),
+	MI_ENTRY("ignpar",   input,       REV,               IGNPAR,     0 ),
+	MI_ENTRY("parmrk",   input,       REV,               PARMRK,     0 ),
+	MI_ENTRY("inpck",    input,       REV,               INPCK,      0 ),
+	MI_ENTRY("istrip",   input,       REV,               ISTRIP,     0 ),
+	MI_ENTRY("inlcr",    input,       SANE_UNSET | REV,  INLCR,      0 ),
+	MI_ENTRY("igncr",    input,       SANE_UNSET | REV,  IGNCR,      0 ),
+	MI_ENTRY("icrnl",    input,       SANE_SET   | REV,  ICRNL,      0 ),
+	MI_ENTRY("ixon",     input,       REV,               IXON,       0 ),
+	MI_ENTRY("ixoff",    input,       SANE_UNSET | REV,  IXOFF,      0 ),
+	MI_ENTRY("tandem",   input,       REV        | OMIT, IXOFF,      0 ),
 #ifdef IUCLC
-	{"iuclc",    input,       SANE_UNSET | REV,  IUCLC,      0 },
+	MI_ENTRY("iuclc",    input,       SANE_UNSET | REV,  IUCLC,      0 ),
 #endif
 #ifdef IXANY
-	{"ixany",    input,       SANE_UNSET | REV,  IXANY,      0 },
+	MI_ENTRY("ixany",    input,       SANE_UNSET | REV,  IXANY,      0 ),
 #endif
 #ifdef IMAXBEL
-	{"imaxbel",  input,       SANE_SET   | REV,  IMAXBEL,    0 },
+	MI_ENTRY("imaxbel",  input,       SANE_SET   | REV,  IMAXBEL,    0 ),
 #endif
-	{"opost",    output,      SANE_SET   | REV,  OPOST,      0 },
+	MI_ENTRY("opost",    output,      SANE_SET   | REV,  OPOST,      0 ),
 #ifdef OLCUC
-	{"olcuc",    output,      SANE_UNSET | REV,  OLCUC,      0 },
+	MI_ENTRY("olcuc",    output,      SANE_UNSET | REV,  OLCUC,      0 ),
 #endif
 #ifdef OCRNL
-	{"ocrnl",    output,      SANE_UNSET | REV,  OCRNL,      0 },
+	MI_ENTRY("ocrnl",    output,      SANE_UNSET | REV,  OCRNL,      0 ),
 #endif
 #ifdef ONLCR
-	{"onlcr",    output,      SANE_SET   | REV,  ONLCR,      0 },
+	MI_ENTRY("onlcr",    output,      SANE_SET   | REV,  ONLCR,      0 ),
 #endif
 #ifdef ONOCR
-	{"onocr",    output,      SANE_UNSET | REV,  ONOCR,      0 },
+	MI_ENTRY("onocr",    output,      SANE_UNSET | REV,  ONOCR,      0 ),
 #endif
 #ifdef ONLRET
-	{"onlret",   output,      SANE_UNSET | REV,  ONLRET,     0 },
+	MI_ENTRY("onlret",   output,      SANE_UNSET | REV,  ONLRET,     0 ),
 #endif
 #ifdef OFILL
-	{"ofill",    output,      SANE_UNSET | REV,  OFILL,      0 },
+	MI_ENTRY("ofill",    output,      SANE_UNSET | REV,  OFILL,      0 ),
 #endif
 #ifdef OFDEL
-	{"ofdel",    output,      SANE_UNSET | REV,  OFDEL,      0 },
+	MI_ENTRY("ofdel",    output,      SANE_UNSET | REV,  OFDEL,      0 ),
 #endif
 #ifdef NLDLY
-	{"nl1",      output,      SANE_UNSET,        NL1,     NLDLY},
-	{"nl0",      output,      SANE_SET,          NL0,     NLDLY},
+	MI_ENTRY("nl1",      output,      SANE_UNSET,        NL1,     NLDLY),
+	MI_ENTRY("nl0",      output,      SANE_SET,          NL0,     NLDLY),
 #endif
 #ifdef CRDLY
-	{"cr3",      output,      SANE_UNSET,        CR3,     CRDLY},
-	{"cr2",      output,      SANE_UNSET,        CR2,     CRDLY},
-	{"cr1",      output,      SANE_UNSET,        CR1,     CRDLY},
-	{"cr0",      output,      SANE_SET,          CR0,     CRDLY},
+	MI_ENTRY("cr3",      output,      SANE_UNSET,        CR3,     CRDLY),
+	MI_ENTRY("cr2",      output,      SANE_UNSET,        CR2,     CRDLY),
+	MI_ENTRY("cr1",      output,      SANE_UNSET,        CR1,     CRDLY),
+	MI_ENTRY("cr0",      output,      SANE_SET,          CR0,     CRDLY),
 #endif
 
 #ifdef TABDLY
-	{"tab3",     output,      SANE_UNSET,        TAB3,   TABDLY},
-	{"tab2",     output,      SANE_UNSET,        TAB2,   TABDLY},
-	{"tab1",     output,      SANE_UNSET,        TAB1,   TABDLY},
-	{"tab0",     output,      SANE_SET,          TAB0,   TABDLY},
+	MI_ENTRY("tab3",     output,      SANE_UNSET,        TAB3,   TABDLY),
+	MI_ENTRY("tab2",     output,      SANE_UNSET,        TAB2,   TABDLY),
+	MI_ENTRY("tab1",     output,      SANE_UNSET,        TAB1,   TABDLY),
+	MI_ENTRY("tab0",     output,      SANE_SET,          TAB0,   TABDLY),
 #else
 # ifdef OXTABS
-	{"tab3",     output,      SANE_UNSET,        OXTABS,     0 },
+	MI_ENTRY("tab3",     output,      SANE_UNSET,        OXTABS,     0 ),
 # endif
 #endif
 
 #ifdef BSDLY
-	{"bs1",      output,      SANE_UNSET,        BS1,     BSDLY},
-	{"bs0",      output,      SANE_SET,          BS0,     BSDLY},
+	MI_ENTRY("bs1",      output,      SANE_UNSET,        BS1,     BSDLY),
+	MI_ENTRY("bs0",      output,      SANE_SET,          BS0,     BSDLY),
 #endif
 #ifdef VTDLY
-	{"vt1",      output,      SANE_UNSET,        VT1,     VTDLY},
-	{"vt0",      output,      SANE_SET,          VT0,     VTDLY},
+	MI_ENTRY("vt1",      output,      SANE_UNSET,        VT1,     VTDLY),
+	MI_ENTRY("vt0",      output,      SANE_SET,          VT0,     VTDLY),
 #endif
 #ifdef FFDLY
-	{"ff1",      output,      SANE_UNSET,        FF1,     FFDLY},
-	{"ff0",      output,      SANE_SET,          FF0,     FFDLY},
+	MI_ENTRY("ff1",      output,      SANE_UNSET,        FF1,     FFDLY),
+	MI_ENTRY("ff0",      output,      SANE_SET,          FF0,     FFDLY),
 #endif
-	{"isig",     local,       SANE_SET   | REV,  ISIG,       0 },
-	{"icanon",   local,       SANE_SET   | REV,  ICANON,     0 },
+	MI_ENTRY("isig",     local,       SANE_SET   | REV,  ISIG,       0 ),
+	MI_ENTRY("icanon",   local,       SANE_SET   | REV,  ICANON,     0 ),
 #ifdef IEXTEN
-	{"iexten",   local,       SANE_SET   | REV,  IEXTEN,     0 },
+	MI_ENTRY("iexten",   local,       SANE_SET   | REV,  IEXTEN,     0 ),
 #endif
-	{"echo",     local,       SANE_SET   | REV,  ECHO,       0 },
-	{"echoe",    local,       SANE_SET   | REV,  ECHOE,      0 },
-	{"crterase", local,       REV        | OMIT, ECHOE,      0 },
-	{"echok",    local,       SANE_SET   | REV,  ECHOK,      0 },
-	{"echonl",   local,       SANE_UNSET | REV,  ECHONL,     0 },
-	{"noflsh",   local,       SANE_UNSET | REV,  NOFLSH,     0 },
+	MI_ENTRY("echo",     local,       SANE_SET   | REV,  ECHO,       0 ),
+	MI_ENTRY("echoe",    local,       SANE_SET   | REV,  ECHOE,      0 ),
+	MI_ENTRY("crterase", local,       REV        | OMIT, ECHOE,      0 ),
+	MI_ENTRY("echok",    local,       SANE_SET   | REV,  ECHOK,      0 ),
+	MI_ENTRY("echonl",   local,       SANE_UNSET | REV,  ECHONL,     0 ),
+	MI_ENTRY("noflsh",   local,       SANE_UNSET | REV,  NOFLSH,     0 ),
 #ifdef XCASE
-	{"xcase",    local,       SANE_UNSET | REV,  XCASE,      0 },
+	MI_ENTRY("xcase",    local,       SANE_UNSET | REV,  XCASE,      0 ),
 #endif
 #ifdef TOSTOP
-	{"tostop",   local,       SANE_UNSET | REV,  TOSTOP,     0 },
+	MI_ENTRY("tostop",   local,       SANE_UNSET | REV,  TOSTOP,     0 ),
 #endif
 #ifdef ECHOPRT
-	{"echoprt",  local,       SANE_UNSET | REV,  ECHOPRT,    0 },
-	{"prterase", local,       REV | OMIT,        ECHOPRT,    0 },
+	MI_ENTRY("echoprt",  local,       SANE_UNSET | REV,  ECHOPRT,    0 ),
+	MI_ENTRY("prterase", local,       REV | OMIT,        ECHOPRT,    0 ),
 #endif
 #ifdef ECHOCTL
-	{"echoctl",  local,       SANE_SET   | REV,  ECHOCTL,    0 },
-	{"ctlecho",  local,       REV        | OMIT, ECHOCTL,    0 },
+	MI_ENTRY("echoctl",  local,       SANE_SET   | REV,  ECHOCTL,    0 ),
+	MI_ENTRY("ctlecho",  local,       REV        | OMIT, ECHOCTL,    0 ),
 #endif
 #ifdef ECHOKE
-	{"echoke",   local,       SANE_SET   | REV,  ECHOKE,     0 },
-	{"crtkill",  local,       REV        | OMIT, ECHOKE,     0 },
+	MI_ENTRY("echoke",   local,       SANE_SET   | REV,  ECHOKE,     0 ),
+	MI_ENTRY("crtkill",  local,       REV        | OMIT, ECHOKE,     0 ),
 #endif
-	{evenp,      combination, REV        | OMIT, 0,          0 },
-	{parity,     combination, REV        | OMIT, 0,          0 },
-	{stty_oddp,  combination, REV        | OMIT, 0,          0 },
-	{stty_nl,    combination, REV        | OMIT, 0,          0 },
-	{stty_ek,    combination, OMIT,              0,          0 },
-	{stty_sane,  combination, OMIT,              0,          0 },
-	{cooked,     combination, REV        | OMIT, 0,          0 },
-	{raw,        combination, REV        | OMIT, 0,          0 },
-	{stty_pass8, combination, REV        | OMIT, 0,          0 },
-	{litout,     combination, REV        | OMIT, 0,          0 },
-	{cbreak,     combination, REV        | OMIT, 0,          0 },
+	MI_ENTRY(evenp,      combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(parity,     combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(stty_oddp,  combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(stty_nl,    combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(stty_ek,    combination, OMIT,              0,          0 ),
+	MI_ENTRY(stty_sane,  combination, OMIT,              0,          0 ),
+	MI_ENTRY(cooked,     combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(raw,        combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(stty_pass8, combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(litout,     combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(cbreak,     combination, REV        | OMIT, 0,          0 ),
 #ifdef IXANY
-	{decctlq,    combination, REV        | OMIT, 0,          0 },
+	MI_ENTRY(decctlq,    combination, REV        | OMIT, 0,          0 ),
 #endif
 #if defined (TABDLY) || defined (OXTABS)
-	{stty_tabs,  combination, REV        | OMIT, 0,          0 },
+	MI_ENTRY(stty_tabs,  combination, REV        | OMIT, 0,          0 ),
 #endif
 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
-	{stty_lcase, combination, REV        | OMIT, 0,          0 },
-	{stty_LCASE, combination, REV        | OMIT, 0,          0 },
+	MI_ENTRY(stty_lcase, combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(stty_LCASE, combination, REV        | OMIT, 0,          0 ),
 #endif
-	{stty_crt,   combination, OMIT,              0,          0 },
-	{stty_dec,   combination, OMIT,              0,          0 },
+	MI_ENTRY(stty_crt,   combination, OMIT,              0,          0 ),
+	MI_ENTRY(stty_dec,   combination, OMIT,              0,          0 ),
 };
 
 static const int NUM_mode_info =
@@ -359,7 +359,7 @@
 struct control_info {
 	const char *name;                       /* Name given on command line.  */
 	unsigned char saneval;          /* Value to set for `stty sane'.  */
-	int offset;                                     /* Offset in c_cc.  */
+	unsigned char offset;                           /* Offset in c_cc.  */
 };
 
 /* Control characters. */
@@ -408,7 +408,6 @@
 
 
 static const char *  visible(unsigned int ch);
-static unsigned long baud_to_value(speed_t speed);
 static int           recover_mode(char *arg, struct termios *mode);
 static int           screen_columns(void);
 static int           set_mode(const struct mode_info *info,
@@ -416,12 +415,11 @@
 static speed_t       string_to_baud(const char *arg);
 static tcflag_t*     mode_type_flag(enum mode_type type, struct termios *mode);
 static void          display_all(struct termios *mode, int fd,
-					const char *device_name);
-static void          display_changed(struct termios *mode);
-static void          display_recoverable(struct termios *mode);
-static void          display_settings(enum output_type output_type,
-					struct termios *mode, int fd,
-					const char *device_name);
+								 const char *device_name);
+static void          display_changed(struct termios *mode, int fd,
+									 const char *device_name);
+static void          display_recoverable(struct termios *mode, int fd,
+										 const char *device_name);
 static void          display_speed(struct termios *mode, int fancy);
 static void          display_window_size(int fancy, int fd,
 					const char *device_name);
@@ -479,7 +477,7 @@
 #endif
 {
 	struct termios mode;
-	enum   output_type output_type;
+	void (*output_func)(struct termios *, int, const char *);
 	int    optc;
 	int    require_set_attr;
 	int    speed_was_set;
@@ -491,7 +489,7 @@
 	int    fd;
 	const char *device_name;
 
-	output_type = changed;
+	output_func = display_changed;
 	verbose_output = 0;
 	recoverable_output = 0;
 
@@ -502,17 +500,17 @@
 		switch (optc) {
 		case 'a':
 			verbose_output = 1;
-			output_type = all;
+			output_func = display_all;
 			break;
 
 		case 'g':
 			recoverable_output = 1;
-			output_type = recoverable;
+			output_func = display_recoverable;
 			break;
 
 		case 'F':
 			if (file_name)
-				error_msg_and_die("only one device may be specified");
+				bb_error_msg_and_die("only one device may be specified");
 			file_name = optarg;
 			break;
 
@@ -529,12 +527,12 @@
 		noargs = 0;
 
 	/* Specifying both -a and -g gets an error.  */
-	if (verbose_output && recoverable_output)
-		error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive");
+	if (verbose_output & recoverable_output)
+		bb_error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive");
 
 	/* Specifying any other arguments with -a or -g gets an error.  */
-	if (!noargs && (verbose_output || recoverable_output))
-		error_msg_and_die ("modes may not be set when specifying an output style");
+	if (~noargs & (verbose_output | recoverable_output))
+		bb_error_msg_and_die ("modes may not be set when specifying an output style");
 
 	/* FIXME: it'd be better not to open the file until we've verified
 	   that all arguments are valid.  Otherwise, we could end up doing
@@ -547,26 +545,26 @@
 		device_name = file_name;
 		fd = open(device_name, O_RDONLY | O_NONBLOCK);
 		if (fd < 0)
-			perror_msg_and_die("%s", device_name);
+			bb_perror_msg_and_die("%s", device_name);
 		if ((fdflags = fcntl(fd, F_GETFL)) == -1
 			|| fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
-			perror_msg_and_die("%s: couldn't reset non-blocking mode",
+			bb_perror_msg_and_die("%s: couldn't reset non-blocking mode",
 							   device_name);
 	} else {
 		fd = 0;
-		device_name = "standard input";
+		device_name = bb_msg_standard_input;
 	}
 
 	/* Initialize to all zeroes so there is no risk memcmp will report a
 	   spurious difference in an uninitialized portion of the structure.  */
 	memset(&mode, 0, sizeof(mode));
 	if (tcgetattr(fd, &mode))
-		perror_msg_and_die("%s", device_name);
+		bb_perror_msg_and_die("%s", device_name);
 
-	if (verbose_output || recoverable_output || noargs) {
+	if (verbose_output | recoverable_output | noargs) {
 		max_col = screen_columns();
 		current_col = 0;
-		display_settings(output_type, &mode, fd, device_name);
+		output_func(&mode, fd, device_name);
 		return EXIT_SUCCESS;
 	}
 
@@ -610,13 +608,13 @@
 			}
 
 		if (match_found == 0 && reversed)
-			error_msg_and_die("invalid argument `%s'", --argv[k]);
+			bb_error_msg_and_die("invalid argument `%s'", --argv[k]);
 
 		if (match_found == 0)
 			for (i = 0; i < NUM_control_info; ++i)
 				if (STREQ(argv[k], control_info[i].name)) {
 					if (k == argc - 1)
-					    error_msg_and_die("missing argument to `%s'", argv[k]);
+					    bb_error_msg_and_die("missing argument to `%s'", argv[k]);
 					match_found = 1;
 					++k;
 					set_control_char(&control_info[i], argv[k], &mode);
@@ -627,14 +625,14 @@
 		if (match_found == 0) {
 			if (STREQ(argv[k], "ispeed")) {
 				if (k == argc - 1)
-				    error_msg_and_die("missing argument to `%s'", argv[k]);
+				    bb_error_msg_and_die("missing argument to `%s'", argv[k]);
 				++k;
 				set_speed(input_speed, argv[k], &mode);
 				speed_was_set = 1;
 				require_set_attr = 1;
 			} else if (STREQ(argv[k], "ospeed")) {
 				if (k == argc - 1)
-				    error_msg_and_die("missing argument to `%s'", argv[k]);
+				    bb_error_msg_and_die("missing argument to `%s'", argv[k]);
 				++k;
 				set_speed(output_speed, argv[k], &mode);
 				speed_was_set = 1;
@@ -643,16 +641,16 @@
 #ifdef TIOCGWINSZ
 			else if (STREQ(argv[k], "rows")) {
 				if (k == argc - 1)
-				    error_msg_and_die("missing argument to `%s'", argv[k]);
+				    bb_error_msg_and_die("missing argument to `%s'", argv[k]);
 				++k;
-				set_window_size((int) parse_number(argv[k], stty_suffixes),
+				set_window_size((int) bb_xparse_number(argv[k], stty_suffixes),
 								-1, fd, device_name);
 			} else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) {
 				if (k == argc - 1)
-				    error_msg_and_die("missing argument to `%s'", argv[k]);
+				    bb_error_msg_and_die("missing argument to `%s'", argv[k]);
 				++k;
 				set_window_size(-1,
-						(int) parse_number(argv[k], stty_suffixes),
+						(int) bb_xparse_number(argv[k], stty_suffixes),
 						fd, device_name);
 			} else if (STREQ(argv[k], "size")) {
 				max_col = screen_columns();
@@ -663,9 +661,9 @@
 #ifdef HAVE_C_LINE
 			else if (STREQ(argv[k], "line")) {
 				if (k == argc - 1)
-					error_msg_and_die("missing argument to `%s'", argv[k]);
+					bb_error_msg_and_die("missing argument to `%s'", argv[k]);
 				++k;
-				mode.c_line = parse_number(argv[k], stty_suffixes);
+				mode.c_line = bb_xparse_number(argv[k], stty_suffixes);
 				require_set_attr = 1;
 			}
 #endif
@@ -679,7 +677,7 @@
 				speed_was_set = 1;
 				require_set_attr = 1;
 			} else
-				error_msg_and_die("invalid argument `%s'", argv[k]);
+				bb_error_msg_and_die("invalid argument `%s'", argv[k]);
 		}
 	}
 
@@ -687,7 +685,7 @@
 		struct termios new_mode;
 
 		if (tcsetattr(fd, TCSADRAIN, &mode))
-			perror_msg_and_die("%s", device_name);
+			bb_perror_msg_and_die("%s", device_name);
 
 		/* POSIX (according to Zlotnick's book) tcsetattr returns zero if
 		   it performs *any* of the requested operations.  This means it
@@ -700,7 +698,7 @@
 		   spurious difference in an uninitialized portion of the structure.  */
 		memset(&new_mode, 0, sizeof(new_mode));
 		if (tcgetattr(fd, &new_mode))
-			perror_msg_and_die("%s", device_name);
+			bb_perror_msg_and_die("%s", device_name);
 
 		/* Normally, one shouldn't use memcmp to compare structures that
 		   may have `holes' containing uninitialized data, but we have been
@@ -723,7 +721,7 @@
 			new_mode.c_cflag &= (~CIBAUD);
 			if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0)
 #endif
-				error_msg_and_die ("%s: unable to perform all requested operations",
+				bb_error_msg_and_die ("%s: unable to perform all requested operations",
 					 device_name);
 		}
 	}
@@ -896,9 +894,9 @@
 #endif
 		}
 	} else if (reversed)
-		*bitsp = *bitsp & ~info->mask & ~info->bits;
+		*bitsp = *bitsp & ~((unsigned long)info->mask) & ~info->bits;
 	else
-		*bitsp = (*bitsp & ~info->mask) | info->bits;
+		*bitsp = (*bitsp & ~((unsigned long)info->mask)) | info->bits;
 
 	return 1;
 }
@@ -910,7 +908,7 @@
 	unsigned char value;
 
 	if (info->name == stty_min || info->name == stty_time)
-		value = parse_number(arg, stty_suffixes);
+		value = bb_xparse_number(arg, stty_suffixes);
 	else if (arg[0] == '\0' || arg[1] == '\0')
 		value = arg[0];
 	else if (STREQ(arg, "^-") || STREQ(arg, "undef"))
@@ -921,7 +919,7 @@
 		else
 			value = arg[1] & ~0140; /* Non-letters get weird results. */
 	} else
-		value = parse_number(arg, stty_suffixes);
+		value = bb_xparse_number(arg, stty_suffixes);
 	mode->c_cc[info->offset] = value;
 }
 
@@ -931,10 +929,13 @@
 	speed_t baud;
 
 	baud = string_to_baud(arg);
-	if (type == input_speed || type == both_speeds)
+
+	if (type != output_speed) {	/* either input or both */
 		cfsetispeed(mode, baud);
-	if (type == output_speed || type == both_speeds)
+	}
+	if (type != input_speed) {	/* either output or both */
 		cfsetospeed(mode, baud);
+	}
 }
 
 #ifdef TIOCGWINSZ
@@ -953,7 +954,7 @@
 
 	if (get_win_size(fd, &win)) {
 		if (errno != EINVAL)
-			perror_msg_and_die("%s", device_name);
+			bb_perror_msg_and_die("%s", device_name);
 		memset(&win, 0, sizeof(win));
 	}
 
@@ -975,32 +976,28 @@
 		ttysz.ts_lines = win.ws_row;
 		ttysz.ts_cols = win.ws_col;
 
-		win.ws_row = 1;
-		win.ws_col = 1;
-
-		if (ioctl(fd, TIOCSWINSZ, (char *) &win))
-			perror_msg_and_die("%s", device_name);
+		win.ws_row = win.ws_col = 1;
 
-		if (ioctl(fd, TIOCSSIZE, (char *) &ttysz))
-			perror_msg_and_die("%s", device_name);
+		if ((ioctl(fd, TIOCSWINSZ, (char *) &win) != 0)
+			|| (ioctl(fd, TIOCSSIZE, (char *) &ttysz) != 0)) {
+			bb_perror_msg_and_die("%s", device_name);
 		return;
 	}
 # endif
 
 	if (ioctl(fd, TIOCSWINSZ, (char *) &win))
-		perror_msg_and_die("%s", device_name);
+		bb_perror_msg_and_die("%s", device_name);
 }
 
 static void display_window_size(int fancy, int fd, const char *device_name)
 {
+	const char *fmt_str = "%s" "\0" "%s: no size information for this device";
 	struct winsize win;
 
 	if (get_win_size(fd, &win)) {
-		if (errno != EINVAL)
-			perror_msg_and_die("%s", device_name);
-		if (!fancy)
-			perror_msg_and_die("%s: no size information for this device",
-							   device_name);
+		if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) {
+			bb_perror_msg_and_die(fmt_str, device_name);
+		}
 	} else {
 		wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n",
 			  win.ws_row, win.ws_col);
@@ -1012,6 +1009,9 @@
 
 static int screen_columns(void)
 {
+	int columns;
+	const char *s;
+
 #ifdef TIOCGWINSZ
 	struct winsize win;
 
@@ -1025,51 +1025,29 @@
 		return win.ws_col;
 #endif
 
-	if (getenv("COLUMNS"))
-		return atoi(getenv("COLUMNS"));
-	return 80;
-}
-
-static tcflag_t *mode_type_flag(enum mode_type type, struct termios *mode)
-{
-	switch (type) {
-	case control:
-		return &mode->c_cflag;
-
-	case input:
-		return &mode->c_iflag;
-
-	case output:
-		return &mode->c_oflag;
-
-	case local:
-		return &mode->c_lflag;
-
-	default:                                        /* combination: */
-		return NULL;
+	columns = 80;
+	if ((s = getenv("COLUMNS"))) {
+		columns = atoi(s);
 	}
+	return columns;
 }
 
-static void
-display_settings(enum output_type output_type, struct termios *mode,
-				 int fd, const char *device_name)
+static tcflag_t *mode_type_flag(enum mode_type type, struct termios *mode)
 {
-	switch (output_type) {
-	case changed:
-		display_changed(mode);
-		break;
-
-	case all:
-		display_all(mode, fd, device_name);
-		break;
+	static const unsigned char tcflag_offsets[] = {
+		offsetof(struct termios, c_cflag), /* control */
+		offsetof(struct termios, c_iflag), /* input */
+		offsetof(struct termios, c_oflag), /* output */
+		offsetof(struct termios, c_lflag) /* local */
+	};
 
-	case recoverable:
-		display_recoverable(mode);
-		break;
+	if (((unsigned int) type) <= local) {
+		return (tcflag_t *)(((char *) mode) + tcflag_offsets[(int)type]);
 	}
+	return NULL;
 }
 
-static void display_changed(struct termios *mode)
+static void display_changed(struct termios *mode, int fd, const char *device_name)
 {
 	int i;
 	int empty_line;
@@ -1206,18 +1184,25 @@
 
 static void display_speed(struct termios *mode, int fancy)
 {
-	if (cfgetispeed(mode) == 0 || cfgetispeed(mode) == cfgetospeed(mode))
-		wrapf(fancy ? "speed %lu baud;" : "%lu\n",
-			  baud_to_value(cfgetospeed(mode)));
-	else
-		wrapf(fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
-			  baud_to_value(cfgetispeed(mode)),
-			  baud_to_value(cfgetospeed(mode)));
+	unsigned long ispeed, ospeed;
+	const char *fmt_str =
+		"%lu %lu\n\0"        "ispeed %lu baud; ospeed %lu baud;\0"
+		"%lu\n\0" "\0\0\0\0" "speed %lu baud;";
+
+	ospeed = ispeed = cfgetispeed(mode);
+	if (ispeed == 0 || ispeed == (ospeed = cfgetospeed(mode))) {
+		ispeed = ospeed;		/* in case ispeed was 0 */
+		fmt_str += 43;
+	}
+	if (fancy) {
+		fmt_str += 9;
+	}
+	wrapf(fmt_str, bb_baud_to_value(ispeed), bb_baud_to_value(ospeed));
 	if (!fancy)
 		current_col = 0;
 }
 
-static void display_recoverable(struct termios *mode)
+static void display_recoverable(struct termios *mode, int fd, const char *device_name)
 {
 	int i;
 
@@ -1259,62 +1244,9 @@
 	return 1;
 }
 
-struct speed_map {
-	speed_t speed;                          /* Internal form. */
-	unsigned long value;            /* Numeric 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},
-	{B19200, 19200},
-	{B38400, 38400},
-#ifdef B57600
-	{B57600, 57600},
-#endif
-#ifdef B115200
-	{B115200, 115200},
-#endif
-#ifdef B230400
-	{B230400, 230400},
-#endif
-#ifdef B460800
-	{B460800, 460800},
-#endif
-};
-
-static const int NUM_SPEEDS = (sizeof(speeds) / sizeof(struct speed_map));
-
 static speed_t string_to_baud(const char *arg)
 {
-	int i;
-
-	for (i = 0; i < NUM_SPEEDS; ++i)
-		if (parse_number(arg, 0) == speeds[i].value)
-			return speeds[i].speed;
-	return (speed_t) - 1;
-}
-
-static unsigned long baud_to_value(speed_t speed)
-{
-	int i;
-
-	for (i = 0; i < NUM_SPEEDS; ++i)
-		if (speed == speeds[i].speed)
-			return speeds[i].value;
-	return 0;
+	return bb_value_to_baud(bb_xparse_number(arg, 0));
 }
 
 static void sane_mode(struct termios *mode)
@@ -1333,10 +1265,12 @@
 	for (i = 0; i < NUM_mode_info; ++i) {
 		if (mode_info[i].flags & SANE_SET) {
 			bitsp = mode_type_flag(mode_info[i].type, mode);
-			*bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
+			*bitsp = (*bitsp & ~((unsigned long)mode_info[i].mask))
+				| mode_info[i].bits;
 		} else if (mode_info[i].flags & SANE_UNSET) {
 			bitsp = mode_type_flag(mode_info[i].type, mode);
-			*bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
+			*bitsp = *bitsp & ~((unsigned long)mode_info[i].mask)
+				& ~mode_info[i].bits;
 		}
 	}
 }
@@ -1349,47 +1283,32 @@
 	static char buf[10];
 	char *bpout = buf;
 
-	if (ch == _POSIX_VDISABLE)
+	if (ch == _POSIX_VDISABLE) {
 		return "<undef>";
+	}
 
-	if (ch >= 32) {
-		if (ch < 127)
-			*bpout++ = ch;
-		else if (ch == 127) {
-			*bpout++ = '^';
-			*bpout++ = '?';
-		} else {
-			*bpout++ = 'M', *bpout++ = '-';
-			if (ch >= 128 + 32) {
-				if (ch < 128 + 127)
-					*bpout++ = ch - 128;
-				else {
-					*bpout++ = '^';
-					*bpout++ = '?';
-				}
-			} else {
-				*bpout++ = '^';
-				*bpout++ = ch - 128 + 64;
-			}
-		}
-	} else {
+	if (ch >= 128) {
+		ch -= 128;
+		*bpout++ = 'M';
+		*bpout++ = '-';
+	}
+
+	if (ch < 32) {
 		*bpout++ = '^';
 		*bpout++ = ch + 64;
+	} else if (ch < 127) {
+		*bpout++ = ch;
+	} else {
+		*bpout++ = '^';
+		*bpout++ = '?';
 	}
+
 	*bpout = '\0';
 	return (const char *) buf;
 }
 
 #ifdef TEST
 
-const char *applet_name = "stty";
+const char *bb_applet_name = "stty";
 
 #endif
-
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/

Index: sync.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/sync.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- sync.c	13 Apr 2002 08:31:53 -0000	1.18
+++ sync.c	19 Mar 2003 09:11:34 -0000	1.19
@@ -20,15 +20,17 @@
  *
  */
 
-#include <stdio.h>
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
 #include <stdlib.h>
 #include <unistd.h>
 #include "busybox.h"
 
 extern int sync_main(int argc, char **argv)
 {
-	if (argc > 1 && **(argv + 1) == '-')
-		show_usage();
+	bb_warn_ignoring_args(argc - 1);
+
 	sync();
+
 	return(EXIT_SUCCESS);
 }

Index: tail.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/tail.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- tail.c	23 Dec 2002 11:54:56 -0000	1.43
+++ tail.c	19 Mar 2003 09:11:34 -0000	1.44
@@ -2,7 +2,6 @@
 /*
  * Mini tail implementation for busybox
  *
- *
  * Copyright (C) 2001 by Matt Kraai <kraai at alumni.carnegiemellon.edu>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,14 +20,30 @@
  *
  */
 
+/* BB_AUDIT SUSv3 compliant (need fancy for -c) */
+/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/tail.html */
 
-#include <fcntl.h>
-#include <getopt.h>
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Pretty much rewritten to fix numerous bugs and reduce realloc() calls.
+ * Bugs fixed (although I may have forgotten one or two... it was pretty bad)
+ * 1) mixing printf/write without fflush()ing stdout
+ * 2) no check that any open files are present
+ * 3) optstring had -q taking an arg
+ * 4) no error checking on write in some cases, and a warning even then
+ * 5) q and s interaction bug
+ * 6) no check for lseek error
+ * 7) lseek attempted when count==0 even if arg was +0 (from top)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <stdlib.h>
 #include <unistd.h>
-#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
 #include "busybox.h"
 
 static const struct suffix_mult tail_suffixes[] = {
@@ -38,234 +53,287 @@
 	{ NULL, 0 }
 };
 
-static const int BYTES = 0;
-static const int LINES = 1;
-
-static char *tailbuf;
-static int taillen;
-static int newline;
+static int status
+#if EXIT_SUCCESS != 0
+	= EXIT_SUCCESS	/* If it is 0 (paranoid check), let bss initialize it. */
+#endif
+	;
 
-static void tailbuf_append(char *buf, int len)
+static void tail_xprint_header(const char *fmt, const char *filename)
 {
-	tailbuf = xrealloc(tailbuf, taillen + len);
-	memcpy(tailbuf + taillen, buf, len);
-	taillen += len;
+	/* If we get an output error, there is really no sense in continuing. */
+	if (dprintf(STDOUT_FILENO, fmt, filename) < 0) {
+		bb_perror_nomsg_and_die();
+	}
 }
 
-static void tailbuf_trunc(void)
+/* len should probably be size_t */
+static void tail_xbb_full_write(const char *buf, size_t len)
 {
-	char *s;
-	s = memchr(tailbuf, '\n', taillen);
-	memmove(tailbuf, s + 1, taillen - ((s + 1) - tailbuf));
-	taillen -= (s + 1) - tailbuf;
-	newline = 0;
+	/* If we get a write error, there is really no sense in continuing. */
+	if (bb_full_write(STDOUT_FILENO, buf, len) < 0) {
+		bb_perror_nomsg_and_die();
+	}
 }
 
-int tail_main(int argc, char **argv)
+static ssize_t tail_read(int fd, char *buf, size_t count)
 {
-	int from_top = 0, units = LINES, count = 10, sleep_period = 1;
-	int show_headers = 0, hide_headers = 0, follow = 0;
-	int *fds, nfiles = 0, status = EXIT_SUCCESS, nread, nwrite, seen = 0;
-	char *s, *start, *end, buf[BUFSIZ];
-	int i, opt;
+	ssize_t r;
 
-	if (argc >= 2) {
-		int line_num;
-		switch (argv[1][0]) {
-			case '+':
-				from_top = 1;
-				/* FALLS THROUGH */
-			case '-':
-				line_num = atoi(&argv[1][1]);
-				if (line_num != 0) {
-					optind = 2;
-					count = line_num;
-				}
-				break;
-		}
+	if ((r = safe_read(fd, buf, count)) < 0) {
+		bb_perror_msg("read");
+		status = EXIT_FAILURE;
 	}
 
+	return r;
+}
+
+static const char tail_opts[] =
+	"fn:"
 #ifdef CONFIG_FEATURE_FANCY_TAIL
-	while ((opt = getopt(argc, argv, "c:fn:q:s:v")) > 0) {
-#else
-	while ((opt = getopt(argc, argv, "fn:")) > 0) {
+	"c:qs:v"
 #endif
+	;
+
+static const char header_fmt[] = "\n==> %s <==\n";
+
+int tail_main(int argc, char **argv)
+{
+	long count = 10;
+	unsigned int sleep_period = 1;
+	int from_top = 0;
+	int follow = 0;
+	int header_threshhold = 1;
+#ifdef CONFIG_FEATURE_FANCY_TAIL
+	int count_bytes = 0;
+#endif
+
+	char *tailbuf;
+	size_t tailbufsize;
+	int taillen = 0;
+	int newline = 0;
+
+	int *fds, nfiles, nread, nwrite, seen, i, opt;
+	char *s, *buf;
+	const char *fmt;
+
+	/* Allow legacy syntax of an initial numeric option without -n. */
+	if ((argv[1][0] == '+')
+		|| ((argv[1][0] == '-')
+			/* && (isdigit)(argv[1][1]) */
+			&& (((unsigned int)(argv[1][1] - '0')) <= 9))
+		) {
+		optind = 2;
+		optarg = argv[1];
+		goto GET_COUNT;
+	}
+
+	while ((opt = getopt(argc, argv, tail_opts)) > 0) {
 		switch (opt) {
 			case 'f':
 				follow = 1;
 				break;
 #ifdef CONFIG_FEATURE_FANCY_TAIL
 			case 'c':
-				units = BYTES;
+				count_bytes = 1;
 				/* FALLS THROUGH */
 #endif
 			case 'n':
-				count = parse_number(optarg, tail_suffixes);
-				if (count < 0)
-					count = -count;
-				if (optarg[0] == '+')
+			GET_COUNT:
+				count = bb_xgetlarg10_sfx(optarg, tail_suffixes);
+				/* Note: Leading whitespace is an error trapped above. */
+				if (*optarg == '+') {
 					from_top = 1;
+				} else {
+					from_top = 0;
+				}
+				if (count < 0) {
+					count = -count;
+				}
 				break;
 #ifdef CONFIG_FEATURE_FANCY_TAIL
 			case 'q':
-				hide_headers = 1;
+				header_threshhold = INT_MAX;
 				break;
 			case 's':
-				sleep_period = parse_number(optarg, 0);
+				sleep_period =bb_xgetularg10_bnd(optarg, 0, UINT_MAX);
 				break;
 			case 'v':
-				show_headers = 1;
+				header_threshhold = 0;
 				break;
 #endif
 			default:
-				show_usage();
+				bb_show_usage();
 		}
 	}
 
 	/* open all the files */
 	fds = (int *)xmalloc(sizeof(int) * (argc - optind + 1));
-	if (argc == optind) {
-		fds[nfiles++] = STDIN_FILENO;
-		argv[optind] = "standard input";
-	} else {
-		for (i = optind; i < argc; i++) {
-			if (strcmp(argv[i], "-") == 0) {
-				fds[nfiles++] = STDIN_FILENO;
-				argv[i] = "standard input";
-			} else if ((fds[nfiles++] = open(argv[i], O_RDONLY)) < 0) {
-				perror_msg("%s", argv[i]);
-				status = EXIT_FAILURE;
-			}
+
+	argv += optind;
+	nfiles = i = 0;
+
+	if ((argc -= optind) == 0) {
+		struct stat statbuf;
+
+		if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) {
+			follow = 0;
 		}
+		/* --argv; */
+		*argv = (char *) bb_msg_standard_input;
+		goto DO_STDIN;
 	}
-	
+
+	do {
+		if ((argv[i][0] == '-') && !argv[i][1]) {
+		DO_STDIN:
+			fds[nfiles] = STDIN_FILENO;
+		} else if ((fds[nfiles] = open(argv[i], O_RDONLY)) < 0) {
+			bb_perror_msg("%s", argv[i]);
+			status = EXIT_FAILURE;
+			continue;
+		}
+		argv[nfiles] = argv[i];
+		++nfiles;
+	} while (++i < argc);
+
+	if (!nfiles) {
+		bb_error_msg_and_die("no files");
+	}
+
+	tailbufsize = BUFSIZ;
 #ifdef CONFIG_FEATURE_FANCY_TAIL
 	/* tail the files */
-	if (!from_top && units == BYTES)
-		tailbuf = xmalloc(count);
+	if (from_top < count_bytes) {	/* Each is 0 or 1, so true iff 0 < 1. */
+		/* Hence, !from_top && count_bytes */
+		if (tailbufsize < count) {
+			tailbufsize = count + BUFSIZ;
+		}
+	}
 #endif
+	buf = tailbuf = xmalloc(tailbufsize);
 
-	for (i = 0; i < nfiles; i++) {
-		if (fds[i] == -1)
-			continue;
-		if (!count) {
-			lseek(fds[i], 0, SEEK_END);
+	fmt = header_fmt + 1;	/* Skip header leading newline on first output. */
+	i = 0;
+	do {
+		/* Be careful.  It would be possible to optimize the count-bytes
+		 * case if the file is seekable.  If you do though, remember that
+		 * starting file position may not be the beginning of the file.
+		 * Beware of backing up too far.  See example in wc.c.
+		 */
+		if ((!(count|from_top)) && (lseek(fds[i], 0, SEEK_END) >= 0)) {
 			continue;
 		}
-		seen = 0;
-		if (show_headers || (!hide_headers && nfiles > 1))
-			printf("%s==> %s <==\n", i == 0 ? "" : "\n", argv[optind + i]);
-		while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) {
+
+		if (nfiles > header_threshhold) {
+			tail_xprint_header(fmt, argv[i]);
+			fmt = header_fmt;
+		}
+
+		buf = tailbuf;
+		taillen = 0;
+		seen = 1;
+
+		while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
 			if (from_top) {
+				nwrite = nread;
+				if (seen < count) {
 #ifdef CONFIG_FEATURE_FANCY_TAIL
-				if (units == BYTES) {
-					if (count - 1 <= seen)
-						nwrite = nread;
-					else if (count - 1 <= seen + nread)
-						nwrite = nread + seen - (count - 1);
-					else
-						nwrite = 0;
-					seen += nread;
-				} else {
-#else
-				{
+					if (count_bytes) {
+						nwrite -= (count - seen);
+						seen = count;
+					} else
 #endif
-					if (count - 1 <= seen)
-						nwrite = nread;
-					else {
-						nwrite = 0;
-						for (s = memchr(buf, '\n', nread); s != NULL;
-								s = memchr(s+1, '\n', nread - (s + 1 - buf))) {
-							if (count - 1 <= ++seen) {
-								nwrite = nread - (s + 1 - buf);
+					{
+						s = buf;
+						do {
+							--nwrite;
+							if ((*s++ == '\n') && (++seen == count)) {
 								break;
 							}
-						}
+						} while (nwrite);
 					}
 				}
-				if (full_write(STDOUT_FILENO, buf + nread - nwrite,
-							nwrite) < 0) {
-					perror_msg("write");
-					status = EXIT_FAILURE;
-					break;
-				}
-			} else {
+				tail_xbb_full_write(buf + nread - nwrite, nwrite);
+			} else if (count) {
 #ifdef CONFIG_FEATURE_FANCY_TAIL
-				if (units == BYTES) {
-					if (nread < count) {
-						memmove(tailbuf, tailbuf + nread, count - nread);
-						memcpy(tailbuf + count - nread, buf, nread);
-					} else {
-						memcpy(tailbuf, buf + nread - count, count);
+				if (count_bytes) {
+					taillen += nread;
+					if (taillen > count) {
+						memmove(tailbuf, tailbuf + taillen - count, count);
+						taillen = count;
 					}
-					seen += nread;
-				} else {
-#else
-				{
+				} else
 #endif
-					for (start = buf, end = memchr(buf, '\n', nread);
-							end != NULL; start = end+1,
-							end = memchr(start, '\n', nread - (start - buf))) {
-						if (newline && count <= seen)
-							tailbuf_trunc();
-						tailbuf_append(start, end - start + 1);
-						seen++;
-						newline = 1;
+				{
+					int k = nread;
+					int nbuf = 0;
+
+					while (k) {
+						--k;
+						if (buf[k] == '\n') {
+							++nbuf;
+						}
 					}
-					if (newline && count <= seen && nread - (start - buf) > 0)
-						tailbuf_trunc();
-					tailbuf_append(start, nread - (start - buf));
-				}
-			}
-		}
 
-		if (nread < 0) {
-			perror_msg("read");
-			status = EXIT_FAILURE;
-		}
+					if (newline + nbuf < count) {
+						newline += nbuf;
+						taillen += nread;
 
-#ifdef CONFIG_FEATURE_FANCY_TAIL
-		if (!from_top && units == BYTES) {
-			if (count < seen)
-				seen = count;
-			if (full_write(STDOUT_FILENO, tailbuf + count - seen, seen) < 0) {
-				perror_msg("write");
-				status = EXIT_FAILURE;
+					} else {
+						int extra = 0;
+						if (buf[nread-1] != '\n') {
+							extra = 1;
+						}
+
+						k = newline + nbuf + extra - count;
+						s = tailbuf;
+						while (k) {
+							if (*s == '\n') {
+								--k;
+							}
+							++s;
+						}
+
+						taillen += nread - (s - tailbuf);
+						memmove(tailbuf, s, taillen);
+						newline = count - extra;
+					}
+					if (tailbufsize < taillen + BUFSIZ) {
+						tailbufsize = taillen + BUFSIZ;
+						tailbuf = xrealloc(tailbuf, tailbufsize);
+					}
+				}
+				buf = tailbuf + taillen;
 			}
 		}
-#endif
 
-		if (!from_top && units == LINES) {
-			if (full_write(STDOUT_FILENO, tailbuf, taillen) < 0) {
-				perror_msg("write");
-				status = EXIT_FAILURE;
-			}
+		if (!from_top) {
+			tail_xbb_full_write(tailbuf, taillen);
 		}
 
 		taillen = 0;
-	}
-
-	while (follow) {
-		sleep(sleep_period);
+	} while (++i < nfiles);
 
-		for (i = 0; i < nfiles; i++) {
-			if (fds[i] == -1)
-				continue;
+	buf = xrealloc(tailbuf, BUFSIZ);
 
-			if ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) {
-				if (show_headers || (!hide_headers && nfiles > 1))
-					printf("\n==> %s <==\n", argv[optind + i]);
+	fmt = NULL;
 
-				do {
-					full_write(STDOUT_FILENO, buf, nread);
-				} while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0);
+	while (follow) {
+		sleep(sleep_period);
+		i = 0;
+		do {
+			if (nfiles > header_threshhold) {
+				fmt = header_fmt;
 			}
-
-			if (nread < 0) {
-				perror_msg("read");
-				status = EXIT_FAILURE;
+			while ((nread = tail_read(fds[i], buf, sizeof(buf))) > 0) {
+				if (fmt) {
+					tail_xprint_header(fmt, argv[i]);
+					fmt = NULL;
+				}
+				tail_xbb_full_write(buf, nread);
 			}
-		}
+		} while (++i < nfiles);
 	}
 
 	return status;

Index: tee.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/tee.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- tee.c	24 Oct 2001 05:00:18 -0000	1.21
+++ tee.c	19 Mar 2003 09:11:34 -0000	1.22
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini tee implementation for busybox
+ * tee implementation for busybox
  *
- * Copyright (C) 2000,2001 by Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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
@@ -20,47 +20,96 @@
  *
  */
 
-#include "busybox.h"
-#include <getopt.h>
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */
+
 #include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include "busybox.h"
 
-int
-tee_main(int argc, char **argv)
+int tee_main(int argc, char **argv)
 {
-	char *mode = "w";
-	int c, i, status = 0, nfiles = 0;
+	const char *mode = "w\0a";
 	FILE **files;
+	FILE **p;
+	char **filenames;
+	int flags;
+	int retval = EXIT_SUCCESS;
+#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO
+	size_t c;
+	RESERVE_CONFIG_BUFFER(buf, BUFSIZ);
+#else
+	int c;
+#endif
 
-	while ((c = getopt(argc, argv, "a")) != EOF) {
-		switch (c) {
-		case 'a': 
-			mode = "a";
-			break;
-		default:
-			show_usage();
+	flags = bb_getopt_ulflags(argc, argv, "ia");	/* 'a' must be 2nd */
+
+	mode += (flags & 2);	/* Since 'a' is the 2nd option... */
+
+	if (flags & 1) {
+		signal(SIGINT, SIG_IGN);	/* TODO - switch to sigaction.*/
+	}
+
+	/* gnu tee ignores SIGPIPE in case one of the output files is a pipe
+	 * that doesn't consume all its input.  Good idea... */
+	signal(SIGPIPE, SIG_IGN);		/* TODO - switch to sigaction.*/
+
+	/* Allocate an array of FILE *'s, with one extra for a sentinal. */
+	p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2));
+	*p = stdout;
+	argv += optind - 1;
+	filenames = argv - 1;
+	*filenames = (char *) bb_msg_standard_input;	/* for later */
+	goto GOT_NEW_FILE;
+
+	do {
+		if ((*p = bb_wfopen(*argv, mode)) == NULL) {
+			retval = EXIT_FAILURE;
+			continue;
+		}
+		filenames[(int)(p - files)] = *argv;
+	GOT_NEW_FILE:
+		setbuf(*p, NULL);	/* tee must not buffer output. */
+		++p;
+	} while (*++argv);
+
+	*p = NULL;				/* Store the sentinal value. */
+
+#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO
+	while ((c = fread(buf, 1, BUFSIZ, stdin)) != 0) {
+		for (p=files ; *p ; p++) {
+			fwrite(buf, 1, c, *p);
 		}
 	}
 
-	files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 1));
-	files[nfiles++] = stdout;
-	while (optind < argc) {
-		if ((files[nfiles++] = wfopen(argv[optind++], mode)) == NULL) {
-			nfiles--;
-			status = 1;
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	RELEASE_CONFIG_BUFFER(buf);
+#endif
+
+#else
+	while ((c = getchar()) != EOF) {
+		for (p=files ; *p ; p++) {
+			putc(c, *p);
 		}
 	}
+#endif
 
-	while ((c = getchar()) != EOF)
-		for (i = 0; i < nfiles; i++)
-			putc(c, files[i]);
+	/* Now we need to check for i/o errors on stdin and the various 
+	 * output files.  Since we know that the first entry in the output
+	 * file table is stdout, we can save one "if ferror" test by
+	 * setting the first entry to stdin and checking stdout error
+	 * status with bb_fflush_stdout_and_exit()... although fflush()ing
+	 * is unnecessary here. */
 
-	return status;
-}
+	p = files;
+	*p = stdin;
+	do {		/* Now check for (input and) output errors. */
+		/* Checking ferror should be sufficient, but we may want to fclose.
+		 * If we do, remember not to close stdin! */
+		bb_xferror(*p, filenames[(int)(p - files)]);
+	} while (*++p);
 
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
+	bb_fflush_stdout_and_exit(retval);
+}

Index: test.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/test.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- test.c	23 Aug 2002 06:05:11 -0000	1.21
+++ test.c	19 Mar 2003 09:11:34 -0000	1.22
@@ -180,9 +180,9 @@
 {
 	int res;
 
-	if (strcmp(applet_name, "[") == 0) {
+	if (strcmp(bb_applet_name, "[") == 0) {
 		if (strcmp(argv[--argc], "]"))
-			error_msg_and_die("missing ]");
+			bb_error_msg_and_die("missing ]");
 		argv[argc] = NULL;
 	}
 	/* Implement special cases from POSIX.2, section 4.62.4 */
@@ -226,9 +226,9 @@
 static void syntax(const char *op, const char *msg)
 {
 	if (op && *op) {
-		error_msg_and_die("%s: %s", op, msg);
+		bb_error_msg_and_die("%s: %s", op, msg);
 	} else {
-		error_msg_and_die("%s", msg);
+		bb_error_msg_and_die("%s", msg);
 	}
 }
 
@@ -450,13 +450,13 @@
 	r = strtol(s, &p, 10);
 
 	if (errno != 0)
-		error_msg_and_die("%s: out of range", s);
+		bb_error_msg_and_die("%s: out of range", s);
 
 	while (isspace(*p))
 		p++;
 
 	if (*p)
-		error_msg_and_die("%s: bad number", s);
+		bb_error_msg_and_die("%s: bad number", s);
 
 	return (int) r;
 }

Index: touch.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/touch.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- touch.c	20 Dec 2001 23:12:51 -0000	1.25
+++ touch.c	19 Mar 2003 09:11:34 -0000	1.26
@@ -21,6 +21,16 @@
  *
  */
 
+/* BB_AUDIT SUSv3 _NOT_ compliant -- options -a, -m, -r, -t not supported. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/touch.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Previous version called open() and then utime().  While this will be
+ * be necessary to implement -r and -t, it currently only makes things bigger.
+ * Also, exiting on a failure was a bug.  All args should be processed.
+ */
+
 #include <stdio.h>
 #include <sys/types.h>
 #include <fcntl.h>
@@ -33,44 +43,35 @@
 extern int touch_main(int argc, char **argv)
 {
 	int fd;
-	int create = TRUE;
+	int flags;
+	int status = EXIT_SUCCESS;
 
-	/* Parse options */
-	while (--argc > 0 && **(++argv) == '-') {
-		while (*(++(*argv))) {
-			switch (**argv) {
-			case 'c':
-				create = FALSE;
-				break;
-			default:
-				show_usage();
-			}
-		}
-	}
+	flags = bb_getopt_ulflags(argc, argv, "c");
 
-	if (argc < 1) {
-		show_usage();
+	argv += optind;
+
+	if (!*argv) {
+		bb_show_usage();
 	}
 
-	while (argc > 0) {
-		fd = open(*argv, create ? O_RDWR | O_CREAT : O_RDWR,
-				S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
-		if (fd < 0) {
-			if (! create && errno == ENOENT) {
-				argc--;
-				argv++;
-				continue;
-			} else {
-				perror_msg_and_die("%s", *argv);
-			}
-		}
-		close(fd);
+	do {
 		if (utime(*argv, NULL)) {
-			perror_msg_and_die("%s", *argv);
+			if (errno == ENOENT) {	/* no such file*/
+				if (flags & 1) {	/* Creation is disabled, so ignore. */
+					continue;
+				}
+				/* Try to create the file. */
+				fd = open(*argv, O_RDWR | O_CREAT,
+						  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
+						  );
+				if ((fd >= 0) && !close(fd)) {
+					continue;
+				}
+			}
+			status = EXIT_FAILURE;
+			bb_perror_msg("%s", *argv);
 		}
-		argc--;
-		argv++;
-	}
+	} while (*++argv);
 
-	return EXIT_SUCCESS;
+	return status;
 }

Index: tr.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/tr.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- tr.c	31 Oct 2001 10:41:30 -0000	1.33
+++ tr.c	19 Mar 2003 09:11:34 -0000	1.34
@@ -54,7 +54,7 @@
 		if (in_index == read_chars) {
 			if ((read_chars = read(0, (char *) pinput, BUFSIZ)) <= 0) {
 				if (write(1, (char *) poutput, out_index) != out_index)
-					error_msg("%s", write_error);
+					bb_error_msg(bb_msg_write_error);
 				exit(0);
 			}
 			in_index = 0;
@@ -68,7 +68,7 @@
 		poutput[out_index++] = last = coded;
 		if (out_index == BUFSIZ) {
 			if (write(1, (char *) poutput, out_index) != out_index)
-				error_msg_and_die("%s", write_error);
+				bb_error_msg_and_die(bb_msg_write_error);
 			out_index = 0;
 		}
 	}
@@ -102,7 +102,7 @@
 	while (*arg) {
 		if (*arg == '\\') {
 			arg++;
-			*buffer++ = process_escape_sequence(&arg);
+			*buffer++ = bb_process_escape_sequence(&arg);
 		} else if (*(arg+1) == '-') {
 			ac = *(arg+2);
 			if(ac == 0) {
@@ -181,7 +181,7 @@
 				sq_fl = TRUE;
 				break;
 			default:
-				show_usage();
+				bb_show_usage();
 			}
 		}
 		idx++;
@@ -197,7 +197,7 @@
 			input_length = complement(input, input_length);
 		if (argv[idx] != NULL) {
 			if (*argv[idx] == '\0')
-				error_msg_and_die("STRING2 cannot be empty");
+				bb_error_msg_and_die("STRING2 cannot be empty");
 			output_length = expand(argv[idx], output);
 			map(input, input_length, output, output_length);
 		}

Index: true.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/true.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- true.c	24 Oct 2001 19:00:20 -0000	1.1
+++ true.c	19 Mar 2003 09:11:34 -0000	1.2
@@ -21,7 +21,8 @@
  *
  */
 
-/* getopt not needed */
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/true.html */
 
 #include <stdlib.h>
 #include "busybox.h"

Index: tty.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/tty.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- tty.c	20 Feb 2001 06:14:08 -0000	1.11
+++ tty.c	19 Mar 2003 09:11:34 -0000	1.12
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini tty implementation for busybox
+ * tty implementation for busybox
  *
- * Copyright (C) 2000  Edward Betts <edward at debian.org>.
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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
@@ -20,25 +20,39 @@
  *
  */
 
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/tty.html */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <sys/types.h>
 #include "busybox.h"
 
 extern int tty_main(int argc, char **argv)
 {
-	char *tty;
+	const char *s;
+	int silent;		/* Note: No longer relevant in SUSv3. */
+	int retval;
 
-	if (argc > 1) {
-		if (argv[1][0] != '-' || argv[1][1] != 's')
-			show_usage();
-	} else {
-		tty = ttyname(0);
-		if (tty)
-			puts(tty);
-		else
-			puts("not a tty");
+	bb_default_error_retval = 2;	/* SUSv3 requires > 1 for error. */
+
+	silent = bb_getopt_ulflags(argc, argv, "s");
+
+	/* gnu tty outputs a warning that it is ignoring all args. */
+	bb_warn_ignoring_args(argc - optind);
+
+	retval = 0;
+
+	if ((s = ttyname(0)) == NULL) {
+	/* According to SUSv3, ttyname can on fail with EBADF or ENOTTY.
+	 * We know the file descriptor is good, so failure means not a tty. */
+		s = "not a tty";
+		retval = 1;
 	}
-	return(isatty(0) ? EXIT_SUCCESS : EXIT_FAILURE);
+
+	if (!silent) {
+		puts(s);
+	}
+
+	bb_fflush_stdout_and_exit(retval);
 }

Index: uname.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/uname.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- uname.c	25 Mar 2002 02:37:20 -0000	1.18
+++ uname.c	19 Mar 2003 09:11:34 -0000	1.19
@@ -16,6 +16,9 @@
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/uname.html */
+
 /* Option		Example
 
    -s, --sysname	SunOS
@@ -33,13 +36,18 @@
 
 /* Further size reductions by Glenn McGrath and Manuel Novoa III. */
 
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Now does proper error checking on i/o.  Plus some further space savings.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <string.h>
+#include <unistd.h>
 #include <sys/types.h>
 #include <sys/utsname.h>
-#include <getopt.h>
 #include "busybox.h"
 
 typedef struct {
@@ -48,7 +56,6 @@
 } uname_info_t;
 
 static const char options[] = "snrvmpa";
-static const char flags[] = "\x01\x02\x04\x08\x10\x20\x3f";
 static const unsigned short int utsname_offset[] = {
 	offsetof(uname_info_t,name.sysname),
 	offsetof(uname_info_t,name.nodename),
@@ -61,29 +68,28 @@
 int uname_main(int argc, char **argv)
 {
 	uname_info_t uname_info;
-
 #if defined(__sparc__) && defined(__linux__)
 	char *fake_sparc = getenv("FAKE_SPARC");
 #endif
-
 	const unsigned short int *delta;
-	int opt;
-	char toprint = 0;
+	char toprint;
 
-	while ((opt = getopt(argc, argv, options)) != -1) {
-		const char *p = strchr(options,opt);
-		if (p == NULL) {
-			show_usage();
-		}
-		toprint |= flags[(int)(p-options)];
+	toprint = bb_getopt_ulflags(argc, argv, options);
+
+	if (argc != optind) {
+		bb_show_usage();
+	}
+
+	if (toprint & (1 << 6)) {
+		toprint = 0x3f;
 	}
 
 	if (toprint == 0) {
-		toprint = flags[0];		/* sysname */
+		toprint = 1;			/* sysname */
 	}
 
 	if (uname(&uname_info.name) == -1) {
-		error_msg_and_die("cannot get system name");
+		bb_error_msg_and_die("cannot get system name");
 	}
 
 #if defined(__sparc__) && defined(__linux__)
@@ -99,7 +105,7 @@
 	delta=utsname_offset;
 	do {
 		if (toprint & 1) {
-			printf(((char *)(&uname_info)) + *delta);
+			bb_printf(((char *)(&uname_info)) + *delta);
 			if (toprint > 1) {
 				putchar(' ');
 			}
@@ -108,5 +114,5 @@
 	} while (toprint >>= 1);
 	putchar('\n');
 
-	return EXIT_SUCCESS;
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 }

Index: uniq.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/uniq.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- uniq.c	24 Oct 2001 05:00:27 -0000	1.20
+++ uniq.c	19 Mar 2003 09:11:34 -0000	1.21
@@ -1,10 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini uniq implementation for busybox
+ * uniq implementation for busybox
  *
- * Copyright (C) 1999 by Lineo, inc. and John Beppu
- * Copyright (C) 1999,2000,2001 by John Beppu <beppu at codepoet.org>
- * Rewritten by Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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
@@ -22,67 +20,93 @@
  *
  */
 
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */
+
 #include <stdio.h>
-#include <string.h>
-#include <getopt.h>
-#include <errno.h>
 #include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
 #include "busybox.h"
+#include "libcoreutils/coreutils.h"
 
-static int print_count;
-static int print_uniq = 1;
-static int print_duplicates = 1;
-
-static void print_line(char *line, int count, FILE *fp)
-{
-	if ((print_duplicates && count > 1) || (print_uniq && count == 1)) {
-		if (print_count)
-			fprintf(fp, "%7d\t%s", count, line);
-		else
-			fputs(line, fp);
-	}
-}
+static const char uniq_opts[] = "f:s:cdu\0\7\3\5\1\2\4";
 
 int uniq_main(int argc, char **argv)
 {
-	FILE *in = stdin, *out = stdout;
-	char *lastline = NULL, *input;
-	int opt, count = 0;
+	FILE *in, *out;
+	/* Note: Ignore the warning about dups and e0 possibly being uninitialized.
+	 * They will be initialized on the fist pass of the loop (since s0 is NULL). */
+	unsigned long dups, skip_fields, skip_chars, i;
+	const char *s0, *e0, *s1, *e1, *input_filename;
+	int opt;
+	int uniq_flags = 6;		/* -u */
 
-	/* parse argv[] */
-	while ((opt = getopt(argc, argv, "cdu")) > 0) {
-		switch (opt) {
-			case 'c':
-				print_count = 1;
-				break;
-			case 'd':
-				print_duplicates = 1;
-				print_uniq = 0;
-				break;
-			case 'u':
-				print_duplicates = 0;
-				print_uniq = 1;
-				break;
+	skip_fields = skip_chars = 0;
+
+	while ((opt = getopt(argc, argv, uniq_opts)) > 0) {
+		if (opt == 'f') {
+			skip_fields = bb_xgetularg10(optarg);
+		} else if (opt == 's') {
+			skip_chars = bb_xgetularg10(optarg);
+		} else if ((s0 = strchr(uniq_opts, opt)) != NULL) {
+			uniq_flags &= s0[4];
+			uniq_flags |= s0[7];
+		} else {
+			bb_show_usage();
 		}
 	}
 
-	if (argv[optind] != NULL) {
-		in = xfopen(argv[optind], "r");
-		if (argv[optind+1] != NULL)
-			out = xfopen(argv[optind+1], "w");
+	input_filename = *(argv += optind);
+
+	in = xgetoptfile_sort_uniq(argv, "r");
+	if (*argv) {
+		++argv;
+	}
+	out = xgetoptfile_sort_uniq(argv, "w");
+	if (*argv && argv[1]) {
+		bb_show_usage();
 	}
 
-	while ((input = get_line_from_file(in)) != NULL) {
-		if (lastline == NULL || strcmp(input, lastline) != 0) {
-			print_line(lastline, count, out);
-			free(lastline);
-			lastline = input;
-			count = 0;
+	s0 = NULL;
+
+	/* gnu uniq ignores newlines */
+	while ((s1 = bb_get_chomped_line_from_file(in)) != NULL) {
+		e1 = s1;
+		for (i=skip_fields ; i ; i--) {
+			e1 = bb_skip_whitespace(e1);
+			while (*e1 && !isspace(*e1)) {
+				++e1;
+			}
 		}
-		count++;
+		for (i = skip_chars ; *e1 && i ; i--) {
+			++e1;
+		}
+		if (s0) {
+			if (strcmp(e0, e1) == 0) {
+				++dups;		/* Note: Testing for overflow seems excessive. */
+				continue;
+			}
+		DO_LAST:
+			if ((dups && (uniq_flags & 2)) || (!dups && (uniq_flags & 4))) {
+				bb_fprintf(out, "\0%7d\t" + (uniq_flags & 1), dups + 1);
+				bb_fprintf(out, "%s\n", s0);
+			}
+			free((void *)s0);
+		}
+
+		s0 = s1;
+		e0 = e1;
+		dups = 0;
 	}
-	print_line(lastline, count, out);
-	free(lastline);
 
-	return EXIT_SUCCESS;
+	if (s0) {
+		e1 = NULL;
+		goto DO_LAST;
+	}
+
+	bb_xferror(in, input_filename);
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 }

Index: usleep.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/usleep.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- usleep.c	13 Apr 2002 08:31:58 -0000	1.10
+++ usleep.c	19 Mar 2003 09:11:34 -0000	1.11
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini usleep implementation for busybox
+ * usleep implementation for busybox
  *
- * Copyright (C) 1995, 1996 by Bruce Perens <bruce at pixar.com>.
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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
@@ -20,18 +20,22 @@
  *
  */
 
-/* getopt not needed */
+/* BB_AUDIT SUSv3 N/A -- Apparently a busybox extension. */
 
 #include <stdlib.h>
+#include <limits.h>
 #include <unistd.h>
 #include "busybox.h"
 
 extern int usleep_main(int argc, char **argv)
 {
-	if ((argc < 2) || (**(argv + 1) == '-')) {
-		show_usage();
+	if (argc != 2) {
+		bb_show_usage();
+	}
+
+	if (usleep(bb_xgetularg10_bnd(argv[1], 0, UINT_MAX))) {
+		bb_perror_nomsg_and_die();
 	}
 
-	usleep(atoi(*(++argv)));	/* return void */
 	return EXIT_SUCCESS;
 }

Index: uudecode.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/uudecode.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- uudecode.c	3 Jul 2002 23:19:26 -0000	1.19
+++ uudecode.c	19 Mar 2003 09:11:34 -0000	1.20
@@ -46,7 +46,7 @@
     char *p;
 
     if (fgets (buf, sizeof(buf), stdin) == NULL) {
-      error_msg("%s: Short file", inname);
+      bb_error_msg("%s: Short file", inname);
       return FALSE;
     }
     p = buf;
@@ -81,7 +81,7 @@
 
   if (fgets (buf, sizeof(buf), stdin) == NULL
       || strcmp (buf, "end\n")) {
-    error_msg("%s: No `end' line", inname);
+    bb_error_msg("%s: No `end' line", inname);
     return FALSE;
   }
 
@@ -131,7 +131,7 @@
     unsigned char *p;
 
     if (fgets (buf, sizeof(buf), stdin) == NULL) {
-      error_msg("%s: Short file", inname);
+      bb_error_msg("%s: Short file", inname);
       return FALSE;
     }
     p = buf;
@@ -139,7 +139,7 @@
     if (memcmp (buf, "====", 4) == 0)
       break;
     if (last_data != 0) {
-      error_msg("%s: data following `=' padding character", inname);
+      bb_error_msg("%s: data following `=' padding character", inname);
       return FALSE;
     }
 
@@ -161,14 +161,14 @@
 
       while ((b64_tab[*p] & '\100') != 0)
         if (*p == '\n' || *p++ == '=') {
-          error_msg("%s: illegal line", inname);
+          bb_error_msg("%s: illegal line", inname);
           return FALSE;
         }
       c2 = b64_tab[*p++];
 
       while (b64_tab[*p] == '\177')
         if (*p++ == '\n') {
-          error_msg("%s: illegal line", inname);
+          bb_error_msg("%s: illegal line", inname);
           return FALSE;
         }
       if (*p == '=') {
@@ -180,7 +180,7 @@
 
       while (b64_tab[*p] == '\177')
         if (*p++ == '\n') {
-          error_msg("%s: illegal line", inname);
+          bb_error_msg("%s: illegal line", inname);
           return FALSE;
         }
       putchar (c1 << 2 | c2 >> 4);
@@ -213,7 +213,7 @@
 
   while (1) {
     if (fgets (buf, sizeof (buf), stdin) == NULL) {
-      error_msg("%s: No `begin' line", inname);
+      bb_error_msg("%s: No `begin' line", inname);
       return FALSE;
     }
 
@@ -239,13 +239,13 @@
       while (*p != '/')
         ++p;
       if (*p == '\0') {
-        error_msg("%s: Illegal ~user", inname);
+        bb_error_msg("%s: Illegal ~user", inname);
         return FALSE;
       }
       *p++ = '\0';
       pw = getpwnam (buf + 1);
       if (pw == NULL) {
-        error_msg("%s: No user `%s'", inname, buf + 1);
+        bb_error_msg("%s: No user `%s'", inname, buf + 1);
         return FALSE;
       }
       outname = concat_path_file(pw->pw_dir, p);
@@ -258,7 +258,7 @@
       && (freopen (outname, "w", stdout) == NULL
 	  || chmod (outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO))
          )) {
-    perror_msg("%s", outname); /* */
+    bb_perror_msg("%s", outname); /* */
     if (dofre)
 	free(outname);
     return FALSE;
@@ -295,7 +295,7 @@
       break;
 
      default:
-      show_usage();
+      bb_show_usage();
     }
   }
 
@@ -308,7 +308,7 @@
         if (decode (argv[optind], outname) != 0)
           exit_status = FALSE;
       } else {
-        perror_msg("%s", argv[optind]);
+        bb_perror_msg("%s", argv[optind]);
         exit_status = EXIT_FAILURE;
       }
       optind++;

Index: uuencode.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/uuencode.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- uuencode.c	6 Dec 2002 21:39:48 -0000	1.24
+++ uuencode.c	19 Mar 2003 09:11:34 -0000	1.25
@@ -29,7 +29,7 @@
 #include "busybox.h"
 
 /* Conversion table.  for base 64 */
-static char tbl_base64[65] = {
+static const char tbl_base64[65] = {
 	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
 	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
 	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
@@ -41,7 +41,7 @@
 	'=' /* termination character */
 };
 
-static char tbl_std[65] = {
+static const char tbl_std[65] = {
 	'`', '!', '"', '#', '$', '%', '&', '\'',
 	'(', ')', '*', '+', ',', '-', '.', '/',
 	'0', '1', '2', '3', '4', '5', '6', '7',
@@ -92,40 +92,36 @@
 	int write_size = dst_buf_size;
 	struct stat stat_buf;
 	FILE *src_stream = stdin;
-	char *tbl = tbl_std;
+	const char *tbl;
 	size_t size;
 	mode_t mode;
-	int opt;
 	RESERVE_CONFIG_BUFFER(src_buf, SRC_BUF_SIZE + 1);
 	RESERVE_CONFIG_BUFFER(dst_buf, DST_BUF_SIZE + 1);
 
-	while ((opt = getopt(argc, argv, "m")) != -1) {
-		switch (opt) {
-		case 'm':
-			tbl = tbl_base64;
-   			break;
-		default:
-			show_usage();
-		}
+	tbl = tbl_std;
+	if (bb_getopt_ulflags(argc, argv, "m") & 1) {
+		tbl = tbl_base64;
 	}
 
 	switch (argc - optind) {
 		case 2:
-			src_stream = xfopen(argv[optind], "r");
-			stat(argv[optind], &stat_buf);
+			src_stream = bb_xfopen(argv[optind], "r");
+			if (stat(argv[optind], &stat_buf) < 0) {
+				bb_perror_msg_and_die("stat");
+			}
 			mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
 			if (src_stream == stdout) {
-				printf("NULL\n");
+				puts("NULL");
 			}
 			break;
 		case 1:
 			mode = 0666 & ~umask(0666);
 			break;
 		default:
-			show_usage();
+			bb_show_usage();
 	}
 
-	printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
+	bb_printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
 
 	while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) {
 		if (size != src_buf_size) {
@@ -142,10 +138,12 @@
 			putchar(tbl[size]);
 		}
 		if (fwrite(dst_buf, 1, write_size, stdout) != write_size) {
-			perror("Couldnt finish writing");
+			bb_perror_msg_and_die(bb_msg_write_error);
 		}
 	}
-	printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
+	bb_printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
 
-	return(EXIT_SUCCESS);
+	bb_xferror(src_stream, "source");	/* TODO - Fix this! */
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 }

Index: watch.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/watch.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- watch.c	11 Dec 2002 04:25:02 -0000	1.3
+++ watch.c	19 Mar 2003 09:11:34 -0000	1.4
@@ -20,67 +20,76 @@
  *
  */
 
-/* getopt not needed */
+/* BB_AUDIT SUSv3 N/A */
+/* BB_AUDIT GNU defects -- only option -n is supported. */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Removed dependency on date_main(), added proper error checking, and
+ * reduced size.
+ */
 
 #include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <assert.h>
+#include <unistd.h>
 #include <sys/wait.h>
 #include "busybox.h"
 
 extern int watch_main(int argc, char **argv)
 {
-	const char date_argv[2][10] = { "date", "" };
 	const int header_len = 40;
-	char header[header_len + 1];
-	int period = 2;
-	char **cargv;
-	int cargc;
+	time_t t;
 	pid_t pid;
+	unsigned period = 2;
 	int old_stdout;
-	int i;
+	int len, len2;
+	char **watched_argv;
+	char header[header_len + 1];
 
 	if (argc < 2) {
-		show_usage();
-	} else {
-		cargv = argv + 1;
-		cargc = argc - 1;
-
-		/* don't use getopt, because it permutes the arguments */
-		if (argc >= 3 && !strcmp(argv[1], "-n")) {
-			period = strtol(argv[2], NULL, 10);
-			if (period < 1)
-				show_usage();
-			cargv += 2;
-			cargc -= 2;
-		}
+		bb_show_usage();
 	}
 
-
-	/* create header */
-	snprintf(header, header_len, "Every %ds: ", period);
-	for (i = 0; i < cargc && (strlen(header) + strlen(cargv[i]) < header_len);
-		 i++) {
-		strcat(header, cargv[i]);
-		strcat(header, " ");
+	/* don't use getopt, because it permutes the arguments */
+	++argv;
+	if ((argc > 3) && !strcmp(*argv, "-n")
+	) {
+		period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX);
+		argv += 2;
 	}
+	watched_argv = argv;
 
-	/* fill with blanks */
-	for (i = strlen(header); i < header_len; i++)
-		header[i] = ' ';
+	/* create header */
 
-	header[header_len - 1] = '\0';
+	len = snprintf(header, header_len, "Every %ds:", period);
+	/* Don't bother checking for len < 0, as it should never happen.
+	 * But, just to be prepared... */
+	assert(len >= 0);
+	do {
+		len2 = strlen(*argv);
+		if (len + len2 >= header_len-1) {
+			break;
+		}
+		header[len] = ' ';
+		memcpy(header+len+1, *argv, len2);
+		len += len2+1;
+	} while (*++argv);
 
+	header[len] = 0;
 
 	/* thanks to lye, who showed me how to redirect stdin/stdout */
 	old_stdout = dup(1);
 
 	while (1) {
-		printf("\033[H\033[J%s", header);
-		date_main(1, (char **) date_argv);
-		printf("\n");
+		time(&t);
+		/* Use dprintf to avoid fflush()ing stdout. */
+		if (dprintf(1, "\033[H\033[J%-*s%s\n", header_len, header, ctime(&t)) < 0) {
+			bb_perror_msg_and_die("printf");
+		}
 
 		pid = vfork();	/* vfork, because of ucLinux */
 		if (pid > 0) {
@@ -91,13 +100,11 @@
 			//child
 			close(1);
 			dup(old_stdout);
-			if (execvp(*cargv, cargv))
-				error_msg_and_die("Couldn't run command\n");
+			if (execvp(*watched_argv, watched_argv)) {
+				bb_error_msg_and_die("Couldn't run command\n");
+			}
 		} else {
-			error_msg_and_die("Couldn't vfork\n");
+			bb_error_msg_and_die("Couldn't vfork\n");
 		}
 	}
-
-
-	return EXIT_SUCCESS;
 }

Index: wc.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/wc.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- wc.c	20 Dec 2001 21:11:59 -0000	1.26
+++ wc.c	19 Mar 2003 09:11:34 -0000	1.27
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini wc implementation for busybox
+ * wc implementation for busybox
  *
- * Copyright (C) 2000  Edward Betts <edward at debian.org>
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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
@@ -20,159 +20,208 @@
  *
  */
 
+/* BB_AUDIT SUSv3 _NOT_ compliant -- option -m is not currently supported. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/wc.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Rewritten to fix a number of problems and do some size optimizations.
+ * Problems in the previous busybox implementation (besides bloat) included: 
+ *  1) broken 'wc -c' optimization (read note below)
+ *  2) broken handling of '-' args
+ *  3) no checking of ferror on EOF returns
+ *  4) isprint() wasn't considered when word counting.
+ *
+ * TODO:
+ *
+ * When locale support is enabled, count multibyte chars in the '-m' case.
+ *
+ * NOTES:
+ *
+ * The previous busybox wc attempted an optimization using stat for the
+ * case of counting chars only.  I omitted that because it was broken.
+ * It didn't take into account the possibility of input coming from a
+ * pipe, or input from a file with file pointer not at the beginning.
+ *
+ * To implement such a speed optimization correctly, not only do you
+ * need the size, but also the file position.  Note also that the
+ * file position may be past the end of file.  Consider the example
+ * (adapted from example in gnu wc.c)
+ *
+ *      echo hello > /tmp/testfile &&
+ *      (dd ibs=1k skip=1 count=0 &> /dev/null ; wc -c) < /tmp/testfile
+ *
+ * for which 'wc -c' should output '0'.
+ */
+
 #include <stdio.h>
-#include <getopt.h>
-#include <string.h>
 #include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include "busybox.h"
 
-enum print_e {
-	print_lines = 1,
-	print_words = 2,
-	print_chars = 4,
-	print_length = 8
+#ifdef CONFIG_LOCALE_SUPPORT
+#include <locale.h>
+#include <ctype.h>
+#define isspace_given_isprint(c) isspace(c)
+#else
+#undef isspace
+#undef isprint
+#define isspace(c) ((((c) == ' ') || (((unsigned int)((c) - 9)) <= (13 - 9))))
+#define isprint(c) (((unsigned int)((c) - 0x20)) <= (0x7e - 0x20))
+#define isspace_given_isprint(c) ((c) == ' ')
+#endif
+
+enum {
+	WC_LINES	= 0,
+	WC_WORDS	= 1,
+	WC_CHARS	= 2,
+	WC_LENGTH	= 3
 };
 
-static unsigned int total_lines = 0;
-static unsigned int total_words = 0;
-static unsigned int total_chars = 0;
-static unsigned int max_length = 0;
-static char print_type = 0;
+/* Note: If this changes, remember to change the initialization of
+ *       'name' in wc_main.  It needs to point to the terminating nul. */
+static const char wc_opts[] = "lwcL";	/* READ THE WARNING ABOVE! */
 
-static void print_counts(const unsigned int lines, const unsigned int words,
-	const unsigned int chars, const unsigned int length, const char *name)
-{
-	int output = 0;
+enum {
+	OP_INC_LINE	= 1, /* OP_INC_LINE must be 1. */
+	OP_SPACE	= 2,
+	OP_NEWLINE	= 4,
+	OP_TAB		= 8,
+	OP_NUL		= 16,
+};
 
-	if (print_type & print_lines) {
-		printf("%7d", lines);
-		output++;
-	}
-	if (print_type & print_words) {
-		if (output++)
-			putchar(' ');
-		printf("%7d", words);
-	}
-	if (print_type & print_chars) {
-		if (output++)
-			putchar(' ');
-		printf("%7d", chars);
-	}
-	if (print_type & print_length) {
-		if (output++)
-			putchar(' ');
-		printf("%7d", length);
-	}
-	if (*name) {
-		printf(" %s", name);
-	}
-	putchar('\n');
-}
+/* Note: If fmt_str changes, the offsets to 's' in the OUTPUT section
+ *       will need to be updated. */
+static const char fmt_str[] = " %7u\0 %s\n";
+static const char total_str[] = "total";
 
-static void wc_file(FILE * file, const char *name)
+int wc_main(int argc, char **argv)
 {
-	unsigned int lines = 0;
-	unsigned int words = 0;
-	unsigned int chars = 0;
-	unsigned int length = 0;
-	unsigned int linepos = 0;
-	char in_word = 0;
+	FILE *fp;
+	const char *s;
+	unsigned int *pcounts;
+	unsigned int counts[4];
+	unsigned int totals[4];
+	unsigned int linepos;
+	unsigned int u;
+	int num_files = 0;
 	int c;
-
-	while ((c = getc(file)) != EOF) {
-		chars++;
-		switch (c) {
-		case '\n':
-			lines++;
-		case '\r':
-		case '\f':
-			if (linepos > length)
-				length = linepos;
-			linepos = 0;
-			goto word_separator;
-		case '\t':
-			linepos += 8 - (linepos % 8);
-			goto word_separator;
-		case ' ':
-			linepos++;
-		case '\v':
-word_separator:
-			if (in_word) {
-				in_word = 0;
-				words++;
-			}
-			break;
-		default:
-			linepos++;
-			in_word = 1;
-			break;
-		}
-	}
-	if (linepos > length) {
-		length = linepos;
-	}
-	if (in_word) {
-		words++;
+	char status = EXIT_SUCCESS;
+	char in_word;
+	char print_type;
+		
+	print_type = bb_getopt_ulflags(argc, argv, wc_opts);
+	
+	if (print_type == 0) {
+		print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS);
 	}
-	print_counts(lines, words, chars, length, name);
-	total_lines += lines;
-	total_words += words;
-	total_chars += chars;
-	if (length > max_length) {
-		max_length = length;
+	
+	argv += optind;
+	if (!*argv) {
+		*--argv = (char *) bb_msg_standard_input;
 	}
-}
-
-int wc_main(int argc, char **argv)
-{
-	int opt;
-
-	while ((opt = getopt(argc, argv, "clLw")) > 0) {
-		switch (opt) {
-			case 'c':
-				print_type |= print_chars;
-				break;
-			case 'l':
-				print_type |= print_lines;
-				break;
-			case 'L':
-				print_type |= print_length;
-				break;
-			case 'w':
-				print_type |= print_words;
-				break;
-			default:
-				show_usage();
+	
+	memset(totals, 0, sizeof(totals));
+	
+	pcounts = counts;
+	
+	do {
+		++num_files;
+		if (!(fp = bb_wfopen_input(*argv))) {
+			status = EXIT_FAILURE;
+			continue;
 		}
-	}
-
-	if (print_type == 0) {
-		print_type = print_lines | print_words | print_chars;
-	}
-
-	if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) {
-		wc_file(stdin, "");
-	} else {
-		unsigned short num_files_counted = 0;
-		while (optind < argc) {
-			if (print_type == print_chars) {
-				struct stat statbuf;
-				stat(argv[optind], &statbuf);
-				print_counts(0, 0, statbuf.st_size, 0, argv[optind]);
-				total_chars += statbuf.st_size;
+		
+		memset(counts, 0, sizeof(counts));
+		linepos = 0;
+		in_word = 0;
+		
+		do {
+			++counts[WC_CHARS];
+			c = getc(fp);
+			if (isprint(c)) {
+				++linepos;
+				if (!isspace_given_isprint(c)) {
+					in_word = 1;
+					continue;
+				}
+			} else if (((unsigned int)(c - 9)) <= 4) {
+				/* \t  9
+				 * \n 10
+				 * \v 11
+				 * \f 12
+				 * \r 13
+				 */
+				if (c == '\t') {
+					linepos = (linepos | 7) + 1;
+				} else {			/* '\n', '\r', '\f', or '\v' */
+				DO_EOF:
+					if (linepos > counts[WC_LENGTH]) {
+						counts[WC_LENGTH] = linepos;
+					}
+					if (c == '\n') {
+						++counts[WC_LINES];
+					}
+					if (c != '\v') {
+						linepos = 0;
+					}
+				}
+			} else if (c == EOF) {
+				if (ferror(fp)) {
+					bb_perror_msg("%s", *argv);
+					status = EXIT_FAILURE;
+				}
+				--counts[WC_CHARS];
+				goto DO_EOF;		/* Treat an EOF as '\r'. */
 			} else {
-				FILE *file;
-				file = xfopen(argv[optind], "r");
-				wc_file(file, argv[optind]);
-				fclose(file);
+				continue;
 			}
-			optind++;
-			num_files_counted++;
+			
+			counts[WC_WORDS] += in_word;
+			in_word = 0;
+			if (c == EOF) {
+				break;
+			}
+		} while (1);
+		
+		if (totals[WC_LENGTH] < counts[WC_LENGTH]) {
+			totals[WC_LENGTH] = counts[WC_LENGTH];
 		}
-		if (num_files_counted > 1) {
-			print_counts(total_lines, total_words, total_chars, max_length, "total");
+		totals[WC_LENGTH] -= counts[WC_LENGTH];
+		
+		bb_fclose_nonstdin(fp);
+		
+	OUTPUT:
+		s = fmt_str + 1;			/* Skip the leading space on 1st pass. */
+		u = 0;
+		do {
+			if (print_type & (1 << u)) {
+				bb_printf(s, pcounts[u]);
+				s = fmt_str;		/* Ok... restore the leading space. */
+			}
+			totals[u] += pcounts[u];
+		} while (++u < 4);
+		
+		s += 8;						/* Set the format to the empty string. */
+		
+		if (*argv != bb_msg_standard_input) {
+			s -= 3;					/* We have a name, so do %s conversion. */
 		}
+		bb_printf(s, *argv);
+		
+	} while (*++argv);
+	
+	/* If more than one file was processed, we want the totals.  To save some
+	 * space, we set the pcounts ptr to the totals array.  This has the side
+	 * effect of trashing the totals array after outputting it, but that's
+	 * irrelavent since we no longer need it. */
+	if (num_files > 1) {
+		num_files = 0;				/* Make sure we don't get here again. */
+		*--argv = (char *) total_str;
+		pcounts = totals;
+		goto OUTPUT;
 	}
-
-	return(EXIT_SUCCESS);
+	
+	bb_fflush_stdout_and_exit(status);
 }

Index: who.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/who.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- who.c	26 Apr 2002 23:53:10 -0000	1.1
+++ who.c	19 Mar 2003 09:11:34 -0000	1.2
@@ -23,7 +23,7 @@
 #include <errno.h>
 #include <string.h>
 #include <time.h>
-#include <busybox.h>
+#include "busybox.h"
 
 extern int who_main(int argc, char **argv)
 {
@@ -33,7 +33,7 @@
     time_t      now, idle; 
 
     if (argc > 1) 
-        show_usage();
+        bb_show_usage();
 
     setutent();
     devlen = sizeof("/dev/") - 1;
@@ -81,5 +81,3 @@
 
     return 0;
 }
-       
-     

Index: whoami.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/whoami.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- whoami.c	30 Sep 2002 20:39:55 -0000	1.20
+++ whoami.c	19 Mar 2003 09:11:34 -0000	1.21
@@ -20,7 +20,7 @@
  *
  */
 
-/* getopt not needed */
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -30,14 +30,15 @@
 extern int whoami_main(int argc, char **argv)
 {
 	char user[9];
-	uid_t uid = geteuid();
+	uid_t uid;
 
 	if (argc > 1)
-		show_usage();
+		bb_show_usage();
 
+	uid = geteuid();
 	if (my_getpwuid(user, uid)) {
 		puts(user);
-		return EXIT_SUCCESS;
+		bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 	}
-	error_msg_and_die("cannot find username for UID %u", (unsigned) uid);
+	bb_error_msg_and_die("cannot find username for UID %u", (unsigned) uid);
 }

Index: yes.c
===================================================================
RCS file: /var/cvs/busybox/coreutils/yes.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- yes.c	9 Mar 2001 21:28:09 -0000	1.13
+++ yes.c	19 Mar 2003 09:11:34 -0000	1.14
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini yes implementation for busybox
+ * yes implementation for busybox
  *
- * Copyright (C) 2000  Edward Betts <edward at debian.org>.
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at 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
@@ -20,7 +20,12 @@
  *
  */
 
-/* getopt not needed */
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Size reductions and removed redundant applet name prefix from error messages.
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -28,26 +33,24 @@
 
 extern int yes_main(int argc, char **argv)
 {
-	int i;
-
-	if (argc >= 2 && *argv[1] == '-')
-		show_usage();
+	static const char fmt_str[] = " %s";
+	const char *fmt;
+	char **first_arg;
 
-	if (argc == 1) {
-		while (1)
-			if (puts("y") == EOF) {
-				perror("yes");
-				return EXIT_FAILURE;
-			}
+	*argv = "y";
+	if (argc != 1) {
+		++argv;
 	}
 
-	while (1)
-		for (i = 1; i < argc; i++)
-			if (fputs(argv[i], stdout) == EOF
-				|| putchar(i == argc - 1 ? '\n' : ' ') == EOF) {
-				perror("yes");
-				return EXIT_FAILURE;
-			}
+	first_arg = argv;
+	do {
+		fmt = fmt_str + 1;
+		do {
+			bb_printf(fmt, *argv);
+			fmt = fmt_str;
+		} while (*++argv);
+		argv = first_arg;
+	} while (putchar('\n') != EOF);
 
-	return EXIT_SUCCESS;
+	bb_perror_nomsg_and_die();
 }




More information about the busybox-cvs mailing list