cut: add proper stdout error handling, fix "-" handling;
modest code shrink

diff --git a/coreutils/cut.c b/coreutils/cut.c
index 257f3d6..4f0bed3 100644
--- a/coreutils/cut.c
+++ b/coreutils/cut.c
@@ -16,13 +16,11 @@
 
 /* option vars */
 static const char optstring[] ALIGN1 = "b:c:f:d:sn";
-#define CUT_OPT_BYTE_FLGS	(1<<0)
-#define CUT_OPT_CHAR_FLGS	(1<<1)
-#define CUT_OPT_FIELDS_FLGS	(1<<2)
-#define CUT_OPT_DELIM_FLGS	(1<<3)
-#define CUT_OPT_SUPPRESS_FLGS (1<<4)
-
-static char delim = '\t';	/* delimiter, default is tab */
+#define CUT_OPT_BYTE_FLGS     (1 << 0)
+#define CUT_OPT_CHAR_FLGS     (1 << 1)
+#define CUT_OPT_FIELDS_FLGS   (1 << 2)
+#define CUT_OPT_DELIM_FLGS    (1 << 3)
+#define CUT_OPT_SUPPRESS_FLGS (1 << 4)
 
 struct cut_list {
 	int startpos;
@@ -47,7 +45,7 @@
 
 }
 
-static void cut_file(FILE * file)
+static void cut_file(FILE *file, char delim)
 {
 	char *line = NULL;
 	unsigned int linenum = 0;	/* keep these zero-based to be consistent */
@@ -163,11 +161,10 @@
 	}
 }
 
-static const char _op_on_field[] ALIGN1 = " only when operating on fields";
-
 int cut_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int cut_main(int argc, char **argv)
 {
+	char delim = '\t';	/* delimiter, default is tab */
 	char *sopt, *ltok;
 
 	opt_complementary = "b--bcf:c--bcf:f--bcf";
@@ -178,7 +175,7 @@
 		bb_error_msg_and_die("expected a list of bytes, characters, or fields");
 
 	if (option_mask32 & CUT_OPT_DELIM_FLGS) {
-		if (strlen(ltok) > 1) {
+		if (ltok[0] && ltok[1]) { /* more than 1 char? */
 			bb_error_msg_and_die("the delimiter must be a single character");
 		}
 		delim = ltok[0];
@@ -186,6 +183,8 @@
 
 	/*  non-field (char or byte) cutting has some special handling */
 	if (!(option_mask32 & CUT_OPT_FIELDS_FLGS)) {
+		static const char _op_on_field[] ALIGN1 = " only when operating on fields";
+
 		if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) {
 			bb_error_msg_and_die
 				("suppressing non-delimited lines makes sense%s",
@@ -210,15 +209,12 @@
 		while ((ltok = strsep(&sopt, ",")) != NULL) {
 
 			/* it's actually legal to pass an empty list */
-			if (strlen(ltok) == 0)
+			if (!ltok[0])
 				continue;
 
 			/* get the start pos */
 			ntok = strsep(&ltok, "-");
-			if (ntok == NULL) {
-				bb_error_msg
-					("internal error: ntok is null for start pos!?\n");
-			} else if (strlen(ntok) == 0) {
+			if (!ntok[0]) {
 				s = BOL;
 			} else {
 				s = xatoi_u(ntok);
@@ -229,13 +225,12 @@
 			}
 
 			/* get the end pos */
-			ntok = strsep(&ltok, "-");
-			if (ntok == NULL) {
+			if (ltok == NULL) {
 				e = NON_RANGE;
-			} else if (strlen(ntok) == 0) {
+			} else if (!ltok[0]) {
 				e = EOL;
 			} else {
-				e = xatoi_u(ntok);
+				e = xatoi_u(ltok);
 				/* if the user specified and end position of 0, that means "til the
 				 * end of the line */
 				if (e == 0)
@@ -245,11 +240,6 @@
 					e = NON_RANGE;
 			}
 
-			/* if there's something left to tokenize, the user passed
-			 * an invalid list */
-			if (ltok)
-				bb_error_msg_and_die("invalid byte or field list");
-
 			/* add the new list */
 			cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
 			cut_lists[nlists-1].startpos = s;
@@ -266,23 +256,31 @@
 		qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
 	}
 
-	/* argv[0..argc-1] should be names of file to process. If no
-	 * files were specified or '-' was specified, take input from stdin.
-	 * Otherwise, we process all the files specified. */
-	if (argv[0] == NULL || LONE_DASH(argv[0])) {
-		cut_file(stdin);
-	} else {
-		FILE *file;
+	{
+		int retval = EXIT_SUCCESS;
+		FILE *file = stdin;
+
+		if (!*argv) {
+			argv--;
+			goto jump_in;
+		}
 
 		do {
-			file = fopen_or_warn(argv[0], "r");
-			if (file) {
-				cut_file(file);
-				fclose(file);
+			file = stdin;
+			if (NOT_LONE_DASH(*argv))
+				file = fopen_or_warn(*argv, "r");
+			if (!file) {
+				retval = EXIT_FAILURE;
+				continue;
 			}
+ jump_in:
+			cut_file(file, delim);
+			if (NOT_LONE_DASH(*argv))
+				fclose(file);
 		} while (*++argv);
+
+		if (ENABLE_FEATURE_CLEAN_UP)
+			free(cut_lists);
+		fflush_stdout_and_exit(retval);
 	}
-	if (ENABLE_FEATURE_CLEAN_UP)
-		free(cut_lists);
-	return EXIT_SUCCESS;
 }