Vladimir's last_patch_15
diff --git a/Makefile b/Makefile
index 0474d17..0e5086d 100644
--- a/Makefile
+++ b/Makefile
@@ -249,7 +249,7 @@
 trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \
 xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \
 copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \
-dirname.c make_directory.c strdup_substr.c
+dirname.c make_directory.c
 LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC))
 LIBBB_CFLAGS = -I$(LIBBB)
 ifneq ($(strip $(BB_SRC_DIR)),)
diff --git a/cmdedit.c b/cmdedit.c
index a2b2386..981253d 100644
--- a/cmdedit.c
+++ b/cmdedit.c
@@ -81,11 +81,11 @@
 #endif
 
 #ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR
-#ifndef TEST
-#include "pwd_grp/pwd.h"
-#else
-#include <pwd.h>
-#endif							/* TEST */
+#       ifndef TEST
+#               include "pwd_grp/pwd.h"
+#       else
+#               include <pwd.h>
+#       endif  /* TEST */
 #endif							/* advanced FEATURES */
 
 
@@ -106,28 +106,14 @@
 static struct history *his_end = NULL;
 
 
-/* ED: sparc termios is broken: revert back to old termio handling. */
-
-#if #cpu(sparc)
-#      include <termio.h>
-#      define termios termio
-#      define setTermSettings(fd,argp) ioctl(fd,TCSETAF,argp)
-#      define getTermSettings(fd,argp) ioctl(fd,TCGETA,argp)
-#else
-#      include <termios.h>
-#      define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
-#      define getTermSettings(fd,argp) tcgetattr(fd, argp);
-#endif
+#include <termios.h>
+#define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
+#define getTermSettings(fd,argp) tcgetattr(fd, argp);
 
 /* Current termio and the previous termio before starting sh */
 static struct termios initial_settings, new_settings;
 
 
-#ifndef _POSIX_VDISABLE
-#define _POSIX_VDISABLE '\0'
-#endif
-
-
 static
 volatile int cmdedit_termw = 80;	/* actual terminal width */
 static int history_counter = 0;	/* Number of commands in history list */
@@ -356,7 +342,7 @@
 	char *pbuf;
 
 	if (!pwd_buf) {
-		pwd_buf=unknown;
+		pwd_buf=(char *)unknown;
 	}
 
 	while (*prmt_ptr) {
@@ -1041,9 +1027,30 @@
 		 * in the current working directory that matches.  */
 		if (!matches)
 			matches =
-				exe_n_cwd_tab_completion(matchBuf, &num_matches,
-										 find_type);
-
+				exe_n_cwd_tab_completion(matchBuf,
+					&num_matches, find_type);
+		/* Remove duplicate found */
+		if(matches) {
+			int i, j;
+			/* bubble */
+			for(i=0; i<(num_matches-1); i++)
+				for(j=i+1; j<num_matches; j++)
+					if(matches[i]!=0 && matches[j]!=0 &&
+						strcmp(matches[i], matches[j])==0) {
+							free(matches[j]);
+							matches[j]=0;
+					}
+			j=num_matches;
+			num_matches = 0;
+			for(i=0; i<j; i++)
+				if(matches[i]) {
+					if(!strcmp(matches[i], "./"))
+						matches[i][1]=0;
+					else if(!strcmp(matches[i], "../"))
+						matches[i][2]=0;
+					matches[num_matches++]=matches[i];
+				}
+		}
 		/* Did we find exactly one match? */
 		if (!matches || num_matches > 1) {
 			char *tmp1;
@@ -1169,8 +1176,6 @@
 extern void cmdedit_read_input(char *prompt, char command[BUFSIZ])
 {
 
-	int inputFd = fileno(stdin);
-
 	int break_out = 0;
 	int lastWasTab = FALSE;
 	unsigned char c = 0;
@@ -1181,23 +1186,28 @@
 	len = 0;
 	command_ps = command;
 
-	if (new_settings.c_cc[VMIN] == 0) {	/* first call */
+	if (new_settings.c_cc[VERASE] == 0) {     /* first call */
 
-		getTermSettings(inputFd, (void *) &initial_settings);
+		getTermSettings(0, (void *) &initial_settings);
 		memcpy(&new_settings, &initial_settings, sizeof(struct termios));
-
+		new_settings.c_lflag &= ~ICANON;        /* unbuffered input */
+		/* Turn off echoing and CTRL-C, so we can trap it */
+		new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
+#ifndef linux
+		/* Hmm, in linux c_cc[] not parsed if set ~ICANON */
 		new_settings.c_cc[VMIN] = 1;
 		new_settings.c_cc[VTIME] = 0;
 		/* Turn off CTRL-C, so we can trap it */
+#       ifndef _POSIX_VDISABLE
+#               define _POSIX_VDISABLE '\0'
+#       endif
 		new_settings.c_cc[VINTR] = _POSIX_VDISABLE;	
-		new_settings.c_lflag &= ~ICANON;	/* unbuffered input */
-		/* Turn off echoing */
-		new_settings.c_lflag &= ~(ECHO | ECHOCTL | ECHONL);	
+#endif
 	}
 
 	command[0] = 0;
 
-	setTermSettings(inputFd, (void *) &new_settings);
+	setTermSettings(0, (void *) &new_settings);
 	handlers_sets |= SET_RESET_TERM;
 
 	/* Now initialize things */
@@ -1209,7 +1219,7 @@
 
 		fflush(stdout);			/* buffered out to fast */
 
-		if (read(inputFd, &c, 1) < 1)
+		if (read(0, &c, 1) < 1)
 			/* if we can't read input then exit */
 			goto prepare_to_die;
 
@@ -1296,11 +1306,11 @@
 
 		case ESC:{
 			/* escape sequence follows */
-			if (read(inputFd, &c, 1) < 1)
+			if (read(0, &c, 1) < 1)
 				return;
 			/* different vt100 emulations */
 			if (c == '[' || c == 'O') {
-				if (read(inputFd, &c, 1) < 1)
+				if (read(0, &c, 1) < 1)
 					return;
 			}
 			switch (c) {
@@ -1365,7 +1375,7 @@
 			}
 			if (c >= '1' && c <= '9')
 				do
-					if (read(inputFd, &c, 1) < 1)
+					if (read(0, &c, 1) < 1)
 						return;
 				while (c != '~');
 			break;
@@ -1375,7 +1385,7 @@
 #ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT
 			/* Control-V -- Add non-printable symbol */
 			if (c == 22) {
-				if (read(inputFd, &c, 1) < 1)
+				if (read(0, &c, 1) < 1)
 					return;
 				if (c == 0) {
 					beep();
@@ -1416,7 +1426,7 @@
 			lastWasTab = FALSE;
 	}
 
-	setTermSettings(inputFd, (void *) &initial_settings);
+	setTermSettings(0, (void *) &initial_settings);
 	handlers_sets &= ~SET_RESET_TERM;
 
 	/* Handle command history log */
diff --git a/editors/vi.c b/editors/vi.c
index bd183e8..e1ff933 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -19,7 +19,7 @@
  */
 
 char *vi_Version =
-	"$Id: vi.c,v 1.9 2001/06/23 13:49:14 andersen Exp $";
+	"$Id: vi.c,v 1.10 2001/06/26 02:06:08 bug1 Exp $";
 
 /*
  * To compile for standalone use:
@@ -3152,8 +3152,10 @@
 	term_vi.c_lflag &= (~ICANON & ~ECHO);	// leave ISIG ON- allow intr's
 	term_vi.c_iflag &= (~IXON & ~ICRNL);
 	term_vi.c_oflag &= (~ONLCR);
+#ifndef linux
 	term_vi.c_cc[VMIN] = 1;
 	term_vi.c_cc[VTIME] = 0;
+#endif
 	erase_char = term_vi.c_cc[VERASE];
 	tcsetattr(0, TCSANOW, &term_vi);
 }
diff --git a/hostname.c b/hostname.c
index 573c8ce..d878515 100644
--- a/hostname.c
+++ b/hostname.c
@@ -1,6 +1,6 @@
 /* vi: set sw=4 ts=4: */
 /*
- * $Id: hostname.c,v 1.29 2001/06/23 13:49:14 andersen Exp $
+ * $Id: hostname.c,v 1.30 2001/06/26 02:06:08 bug1 Exp $
  * Mini hostname implementation for busybox
  *
  * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -49,10 +49,11 @@
 	} else {
 		f = xfopen(s, "r");
 		fgets(buf, 255, f);
+#ifdef BB_FEATURE_CLEAN_UP
 		fclose(f);
+#endif
 		chomp(buf);
-		if (sethostname(buf, strlen(buf)) < 0)
-			perror_msg_and_die("sethostname");
+		do_sethostname(buf, 0);
 	}
 }
 
diff --git a/hush.c b/hush.c
index b0637f8..859353d 100644
--- a/hush.c
+++ b/hush.c
@@ -861,7 +861,7 @@
 		*prompt_str = PS2;
 	}
 #else
-	*prompt_str = (promptmode==0)? PS1 : PS2;
+	*prompt_str = (promptmode==1)? PS1 : PS2;
 #endif
 	debug_printf("result %s\n",*prompt_str);
 }
diff --git a/include/libbb.h b/include/libbb.h
index 102596c..3b0ced7 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -243,7 +243,11 @@
 extern struct hostent *xgethostbyname(const char *name);
 
 char *dirname (const char *path);
-char *strdup_substr (const char *s, int start, int end);
+
+static inline char *strdup_substr (const char *s, int start, int end)
+{
+        return xstrndup (s+start, end-start);
+}
 int make_directory (char *path, mode_t mode, int flags);
 
 #define CT_AUTO	0
diff --git a/libbb/libbb.h b/libbb/libbb.h
index 102596c..3b0ced7 100644
--- a/libbb/libbb.h
+++ b/libbb/libbb.h
@@ -243,7 +243,11 @@
 extern struct hostent *xgethostbyname(const char *name);
 
 char *dirname (const char *path);
-char *strdup_substr (const char *s, int start, int end);
+
+static inline char *strdup_substr (const char *s, int start, int end)
+{
+        return xstrndup (s+start, end-start);
+}
 int make_directory (char *path, mode_t mode, int flags);
 
 #define CT_AUTO	0
diff --git a/more.c b/more.c
index 9f07633..6cdec72 100644
--- a/more.c
+++ b/more.c
@@ -9,6 +9,8 @@
  * based on the original more implementation by Bruce, and code from the 
  * Debian boot-floppies team.
  *
+ * Termios corrects by Vladimir Oleynik <vodz@usa.net>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -29,29 +31,26 @@
 #include <fcntl.h>
 #include <signal.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <sys/ioctl.h>
 #include "busybox.h"
 
-/* ED: sparc termios is broken: revert back to old termio handling. */
-#ifdef BB_FEATURE_USE_TERMIOS
-#	if #cpu(sparc)
-#		include <termio.h>
-#		define termios termio
-#		define setTermSettings(fd,argp) ioctl(fd,TCSETAF,argp)
-#		define getTermSettings(fd,argp) ioctl(fd,TCGETA,argp)
-#	else
-#		include <termios.h>
-#		define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
-#		define getTermSettings(fd,argp) tcgetattr(fd, argp);
-#	endif
-
 static FILE *cin;
 
+#ifdef BB_FEATURE_USE_TERMIOS
+#include <termios.h>
+#define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
+#define getTermSettings(fd,argp) tcgetattr(fd, argp);
+
 static struct termios initial_settings, new_settings;
 
-static void gotsig(int sig)
+static void set_tty_to_initial_mode(void)
 {
 	setTermSettings(fileno(cin), &initial_settings);
+}
+
+static void gotsig(int sig)
+{
 	putchar('\n');
 	exit(EXIT_FAILURE);
 }
@@ -65,7 +64,7 @@
 extern int more_main(int argc, char **argv)
 {
 	int c, lines, input = 0;
-	int please_display_more_prompt;
+	int please_display_more_prompt = -1;
 	struct stat st;
 	FILE *file;
 	int len, page_height;
@@ -77,46 +76,57 @@
 	argc--;
 	argv++;
 
+
+	/* not use inputing from terminal if usage: more > outfile */
+	if(isatty(fileno(stdout))) {
+		cin = fopen("/dev/tty", "r");
+		if (!cin)
+			cin = xfopen("/dev/console", "r");
+		please_display_more_prompt = 0;
+#ifdef BB_FEATURE_USE_TERMIOS
+		getTermSettings(fileno(cin), &initial_settings);
+		new_settings = initial_settings;
+		new_settings.c_lflag &= ~ICANON;
+		new_settings.c_lflag &= ~ECHO;
+#ifndef linux
+                /* Hmm, in linux c_cc[] not parsed if set ~ICANON */
+		new_settings.c_cc[VMIN] = 1;
+		new_settings.c_cc[VTIME] = 0;
+#endif
+		setTermSettings(fileno(cin), &new_settings);
+		atexit(set_tty_to_initial_mode);
+		(void) signal(SIGINT, gotsig);
+		(void) signal(SIGQUIT, gotsig);
+		(void) signal(SIGTERM, gotsig);
+#endif
+	}
+
 	do {
 		if (argc == 0) {
 			file = stdin;
 		} else
-			file = xfopen(*argv, "r");
-
+			file = wfopen(*argv, "r");
+		if(file==0)
+			goto loop;
+			
 		fstat(fileno(file), &st);
 
-#ifdef BB_FEATURE_USE_TERMIOS
-		cin = fopen("/dev/tty", "r");
-		if (!cin)
-			cin = xfopen("/dev/console", "r");
-		getTermSettings(fileno(cin), &initial_settings);
-		new_settings = initial_settings;
-		new_settings.c_cc[VMIN] = 1;
-		new_settings.c_cc[VTIME] = 0;
-		new_settings.c_lflag &= ~ICANON;
-		new_settings.c_lflag &= ~ECHO;
-		setTermSettings(fileno(cin), &new_settings);
+		if(please_display_more_prompt>0)
+			please_display_more_prompt = 0;
 
-#	ifdef BB_FEATURE_AUTOWIDTH
+#if defined BB_FEATURE_AUTOWIDTH && defined BB_FEATURE_USE_TERMIOS
 		ioctl(fileno(stdout), TIOCGWINSZ, &win);
 		if (win.ws_row > 4)
 			terminal_height = win.ws_row - 2;
 		if (win.ws_col > 0)
 			terminal_width = win.ws_col - 1;
-#	endif
-
-		(void) signal(SIGINT, gotsig);
-		(void) signal(SIGQUIT, gotsig);
-		(void) signal(SIGTERM, gotsig);
-
 #endif
 		len=0;
 		lines = 0;
 		page_height = terminal_height;
-		please_display_more_prompt = 0;
 		while ((c = getc(file)) != EOF) {
 
-			if (please_display_more_prompt) {
+			if (please_display_more_prompt>0) {
 				len = printf("--More-- ");
 				if (file != stdin) {
 #if _FILE_OFFSET_BITS == 64
@@ -129,13 +139,6 @@
 						   (double) st.st_size)), (long)st.st_size);
 #endif
 				}
-				len += printf("%s",
-#ifdef BB_FEATURE_USE_TERMIOS
-							   ""
-#else
-							   "\n"
-#endif
-					);
 
 				fflush(stdout);
 
@@ -143,20 +146,16 @@
 				 * We've just displayed the "--More--" prompt, so now we need
 				 * to get input from the user.
 				 */
-#ifdef BB_FEATURE_USE_TERMIOS
 				input = getc(cin);
-#else
-				input = getc(stdin);
+#ifndef BB_FEATURE_USE_TERMIOS
+				printf("\033[A"); /* up cursor */
 #endif
-
-#ifdef BB_FEATURE_USE_TERMIOS
 				/* Erase the "More" message */
 				putc('\r', stdout);
 				while (--len >= 0)
 					putc(' ', stdout);
 				putc('\r', stdout);
 				fflush(stdout);
-#endif
 				len=0;
 				lines = 0;
 				page_height = terminal_height;
@@ -180,6 +179,7 @@
 				/* increment by just one line if we are at
 				 * the end of this line */
 				if (input == '\n')
+					if(please_display_more_prompt==0)
 					please_display_more_prompt = 1;
 				/* Adjust the terminal height for any overlap, so that
 				 * no lines get lost off the top. */
@@ -195,6 +195,7 @@
 					}
 				}
 				if (++lines >= page_height) {
+					if(please_display_more_prompt==0)
 					please_display_more_prompt = 1;
 				}
 				len=0;
@@ -208,12 +209,9 @@
 		}
 		fclose(file);
 		fflush(stdout);
-
+loop:
 		argv++;
 	} while (--argc > 0);
   end:
-#ifdef BB_FEATURE_USE_TERMIOS
-	setTermSettings(fileno(cin), &initial_settings);
-#endif
 	return 0;
 }
diff --git a/networking/hostname.c b/networking/hostname.c
index 573c8ce..d878515 100644
--- a/networking/hostname.c
+++ b/networking/hostname.c
@@ -1,6 +1,6 @@
 /* vi: set sw=4 ts=4: */
 /*
- * $Id: hostname.c,v 1.29 2001/06/23 13:49:14 andersen Exp $
+ * $Id: hostname.c,v 1.30 2001/06/26 02:06:08 bug1 Exp $
  * Mini hostname implementation for busybox
  *
  * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -49,10 +49,11 @@
 	} else {
 		f = xfopen(s, "r");
 		fgets(buf, 255, f);
+#ifdef BB_FEATURE_CLEAN_UP
 		fclose(f);
+#endif
 		chomp(buf);
-		if (sethostname(buf, strlen(buf)) < 0)
-			perror_msg_and_die("sethostname");
+		do_sethostname(buf, 0);
 	}
 }
 
diff --git a/networking/telnet.c b/networking/telnet.c
index 2587193..ce82a0e 100644
--- a/networking/telnet.c
+++ b/networking/telnet.c
@@ -64,8 +64,8 @@
 #include <sys/time.h>
 #endif
 
-static const int DATABUFSIZE = 128;
-static const int IACBUFSIZE = 128;
+#define DATABUFSIZE  128
+#define IACBUFSIZE   128
 
 static const int CHM_TRY = 0;
 static const int CHM_ON = 1;
@@ -90,15 +90,14 @@
 static struct Globalvars {
 	int		netfd; /* console fd:s are 0 and 1 (and 2) */
     /* same buffer used both for network and console read/write */
-	char *	buf; /* allocating so static size is smaller */
-	short	len;
+	char    buf[DATABUFSIZE]; /* allocating so static size is smaller */
 	byte	telstate; /* telnet negotiation state from network input */
 	byte	telwish;  /* DO, DONT, WILL, WONT */
 	byte    charmode;
 	byte    telflags;
 	byte	gotsig;
 	/* buffer to handle telnet negotiations */
-	char *	iacbuf;
+	char    iacbuf[IACBUFSIZE];
 	short	iaclen; /* could even use byte */
 	struct termios termios_def;	
 	struct termios termios_raw;	
@@ -198,7 +197,7 @@
 	G.gotsig = 0;
 	
 }
-static void handlenetoutput()
+static void handlenetoutput(int len)
 {
 	/*	here we could do smart tricks how to handle 0xFF:s in output
 	 *	stream  like writing twice every sequence of FF:s (thus doing
@@ -209,7 +208,7 @@
 	int i;
 	byte * p = G.buf;
 
-	for (i = G.len; i > 0; i--, p++)
+	for (i = len; i > 0; i--, p++)
 	{
 		if (*p == 0x1d)
 		{
@@ -219,16 +218,16 @@
 		if (*p == 0xff)
 			*p = 0x7f;
 	}
-	write(G.netfd, G.buf, G.len);
+	write(G.netfd, G.buf, len);
 }
 
 
-static void handlenetinput()
+static void handlenetinput(int len)
 {
 	int i;
 	int cstart = 0;
 
-	for (i = 0; i < G.len; i++)
+	for (i = 0; i < len; i++)
 	{
 		byte c = G.buf[i];
 
@@ -290,11 +289,11 @@
 		if (G.iaclen)			iacflush();
 		if (G.telstate == TS_0)	G.telstate = 0;
 
-		G.len = cstart;
+		len = cstart;
 	}
 
-	if (G.len)
-		write(1, G.buf, G.len);
+	if (len)
+		write(1, G.buf, len);
 }
 
 
@@ -530,6 +529,7 @@
 {
 	struct in_addr host;
 	int port;
+	int len;
 #ifdef USE_POLL
 	struct pollfd ufds[2];
 #else	
@@ -547,15 +547,11 @@
 		exit(1);
 	
 	G.termios_raw = G.termios_def;
-
 	cfmakeraw(&G.termios_raw);
 	
 	if (argc < 2)	show_usage();
 	port = (argc > 2)? getport(argv[2]): 23;
 	
-	G.buf = xmalloc(DATABUFSIZE);
-	G.iacbuf = xmalloc(IACBUFSIZE);
-	
 	host = getserver(argv[1]);
 
 	G.netfd = remote_connect(host, port);
@@ -599,14 +595,14 @@
 			if (FD_ISSET(0, &rfds))
 #endif				
 			{
-				G.len = read(0, G.buf, DATABUFSIZE);
+				len = read(0, G.buf, DATABUFSIZE);
 
-				if (G.len <= 0)
+				if (len <= 0)
 					doexit(0);
 
-				TRACE(0, ("Read con: %d\n", G.len));
+				TRACE(0, ("Read con: %d\n", len));
 				
-				handlenetoutput();
+				handlenetoutput(len);
 			}
 
 #ifdef USE_POLL
@@ -615,16 +611,16 @@
 			if (FD_ISSET(G.netfd, &rfds))
 #endif				
 			{
-				G.len = read(G.netfd, G.buf, DATABUFSIZE);
+				len = read(G.netfd, G.buf, DATABUFSIZE);
 
-				if (G.len <= 0)
+				if (len <= 0)
 				{
 					WriteCS(1, "Connection closed by foreign host.\r\n");
 					doexit(1);
 				}
-				TRACE(0, ("Read netfd (%d): %d\n", G.netfd, G.len));
+				TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len));
 
-				handlenetinput();
+				handlenetinput(len);
 			}
 		}
 	}
diff --git a/shell/cmdedit.c b/shell/cmdedit.c
index a2b2386..981253d 100644
--- a/shell/cmdedit.c
+++ b/shell/cmdedit.c
@@ -81,11 +81,11 @@
 #endif
 
 #ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR
-#ifndef TEST
-#include "pwd_grp/pwd.h"
-#else
-#include <pwd.h>
-#endif							/* TEST */
+#       ifndef TEST
+#               include "pwd_grp/pwd.h"
+#       else
+#               include <pwd.h>
+#       endif  /* TEST */
 #endif							/* advanced FEATURES */
 
 
@@ -106,28 +106,14 @@
 static struct history *his_end = NULL;
 
 
-/* ED: sparc termios is broken: revert back to old termio handling. */
-
-#if #cpu(sparc)
-#      include <termio.h>
-#      define termios termio
-#      define setTermSettings(fd,argp) ioctl(fd,TCSETAF,argp)
-#      define getTermSettings(fd,argp) ioctl(fd,TCGETA,argp)
-#else
-#      include <termios.h>
-#      define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
-#      define getTermSettings(fd,argp) tcgetattr(fd, argp);
-#endif
+#include <termios.h>
+#define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
+#define getTermSettings(fd,argp) tcgetattr(fd, argp);
 
 /* Current termio and the previous termio before starting sh */
 static struct termios initial_settings, new_settings;
 
 
-#ifndef _POSIX_VDISABLE
-#define _POSIX_VDISABLE '\0'
-#endif
-
-
 static
 volatile int cmdedit_termw = 80;	/* actual terminal width */
 static int history_counter = 0;	/* Number of commands in history list */
@@ -356,7 +342,7 @@
 	char *pbuf;
 
 	if (!pwd_buf) {
-		pwd_buf=unknown;
+		pwd_buf=(char *)unknown;
 	}
 
 	while (*prmt_ptr) {
@@ -1041,9 +1027,30 @@
 		 * in the current working directory that matches.  */
 		if (!matches)
 			matches =
-				exe_n_cwd_tab_completion(matchBuf, &num_matches,
-										 find_type);
-
+				exe_n_cwd_tab_completion(matchBuf,
+					&num_matches, find_type);
+		/* Remove duplicate found */
+		if(matches) {
+			int i, j;
+			/* bubble */
+			for(i=0; i<(num_matches-1); i++)
+				for(j=i+1; j<num_matches; j++)
+					if(matches[i]!=0 && matches[j]!=0 &&
+						strcmp(matches[i], matches[j])==0) {
+							free(matches[j]);
+							matches[j]=0;
+					}
+			j=num_matches;
+			num_matches = 0;
+			for(i=0; i<j; i++)
+				if(matches[i]) {
+					if(!strcmp(matches[i], "./"))
+						matches[i][1]=0;
+					else if(!strcmp(matches[i], "../"))
+						matches[i][2]=0;
+					matches[num_matches++]=matches[i];
+				}
+		}
 		/* Did we find exactly one match? */
 		if (!matches || num_matches > 1) {
 			char *tmp1;
@@ -1169,8 +1176,6 @@
 extern void cmdedit_read_input(char *prompt, char command[BUFSIZ])
 {
 
-	int inputFd = fileno(stdin);
-
 	int break_out = 0;
 	int lastWasTab = FALSE;
 	unsigned char c = 0;
@@ -1181,23 +1186,28 @@
 	len = 0;
 	command_ps = command;
 
-	if (new_settings.c_cc[VMIN] == 0) {	/* first call */
+	if (new_settings.c_cc[VERASE] == 0) {     /* first call */
 
-		getTermSettings(inputFd, (void *) &initial_settings);
+		getTermSettings(0, (void *) &initial_settings);
 		memcpy(&new_settings, &initial_settings, sizeof(struct termios));
-
+		new_settings.c_lflag &= ~ICANON;        /* unbuffered input */
+		/* Turn off echoing and CTRL-C, so we can trap it */
+		new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
+#ifndef linux
+		/* Hmm, in linux c_cc[] not parsed if set ~ICANON */
 		new_settings.c_cc[VMIN] = 1;
 		new_settings.c_cc[VTIME] = 0;
 		/* Turn off CTRL-C, so we can trap it */
+#       ifndef _POSIX_VDISABLE
+#               define _POSIX_VDISABLE '\0'
+#       endif
 		new_settings.c_cc[VINTR] = _POSIX_VDISABLE;	
-		new_settings.c_lflag &= ~ICANON;	/* unbuffered input */
-		/* Turn off echoing */
-		new_settings.c_lflag &= ~(ECHO | ECHOCTL | ECHONL);	
+#endif
 	}
 
 	command[0] = 0;
 
-	setTermSettings(inputFd, (void *) &new_settings);
+	setTermSettings(0, (void *) &new_settings);
 	handlers_sets |= SET_RESET_TERM;
 
 	/* Now initialize things */
@@ -1209,7 +1219,7 @@
 
 		fflush(stdout);			/* buffered out to fast */
 
-		if (read(inputFd, &c, 1) < 1)
+		if (read(0, &c, 1) < 1)
 			/* if we can't read input then exit */
 			goto prepare_to_die;
 
@@ -1296,11 +1306,11 @@
 
 		case ESC:{
 			/* escape sequence follows */
-			if (read(inputFd, &c, 1) < 1)
+			if (read(0, &c, 1) < 1)
 				return;
 			/* different vt100 emulations */
 			if (c == '[' || c == 'O') {
-				if (read(inputFd, &c, 1) < 1)
+				if (read(0, &c, 1) < 1)
 					return;
 			}
 			switch (c) {
@@ -1365,7 +1375,7 @@
 			}
 			if (c >= '1' && c <= '9')
 				do
-					if (read(inputFd, &c, 1) < 1)
+					if (read(0, &c, 1) < 1)
 						return;
 				while (c != '~');
 			break;
@@ -1375,7 +1385,7 @@
 #ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT
 			/* Control-V -- Add non-printable symbol */
 			if (c == 22) {
-				if (read(inputFd, &c, 1) < 1)
+				if (read(0, &c, 1) < 1)
 					return;
 				if (c == 0) {
 					beep();
@@ -1416,7 +1426,7 @@
 			lastWasTab = FALSE;
 	}
 
-	setTermSettings(inputFd, (void *) &initial_settings);
+	setTermSettings(0, (void *) &initial_settings);
 	handlers_sets &= ~SET_RESET_TERM;
 
 	/* Handle command history log */
diff --git a/shell/hush.c b/shell/hush.c
index b0637f8..859353d 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -861,7 +861,7 @@
 		*prompt_str = PS2;
 	}
 #else
-	*prompt_str = (promptmode==0)? PS1 : PS2;
+	*prompt_str = (promptmode==1)? PS1 : PS2;
 #endif
 	debug_printf("result %s\n",*prompt_str);
 }
diff --git a/telnet.c b/telnet.c
index 2587193..ce82a0e 100644
--- a/telnet.c
+++ b/telnet.c
@@ -64,8 +64,8 @@
 #include <sys/time.h>
 #endif
 
-static const int DATABUFSIZE = 128;
-static const int IACBUFSIZE = 128;
+#define DATABUFSIZE  128
+#define IACBUFSIZE   128
 
 static const int CHM_TRY = 0;
 static const int CHM_ON = 1;
@@ -90,15 +90,14 @@
 static struct Globalvars {
 	int		netfd; /* console fd:s are 0 and 1 (and 2) */
     /* same buffer used both for network and console read/write */
-	char *	buf; /* allocating so static size is smaller */
-	short	len;
+	char    buf[DATABUFSIZE]; /* allocating so static size is smaller */
 	byte	telstate; /* telnet negotiation state from network input */
 	byte	telwish;  /* DO, DONT, WILL, WONT */
 	byte    charmode;
 	byte    telflags;
 	byte	gotsig;
 	/* buffer to handle telnet negotiations */
-	char *	iacbuf;
+	char    iacbuf[IACBUFSIZE];
 	short	iaclen; /* could even use byte */
 	struct termios termios_def;	
 	struct termios termios_raw;	
@@ -198,7 +197,7 @@
 	G.gotsig = 0;
 	
 }
-static void handlenetoutput()
+static void handlenetoutput(int len)
 {
 	/*	here we could do smart tricks how to handle 0xFF:s in output
 	 *	stream  like writing twice every sequence of FF:s (thus doing
@@ -209,7 +208,7 @@
 	int i;
 	byte * p = G.buf;
 
-	for (i = G.len; i > 0; i--, p++)
+	for (i = len; i > 0; i--, p++)
 	{
 		if (*p == 0x1d)
 		{
@@ -219,16 +218,16 @@
 		if (*p == 0xff)
 			*p = 0x7f;
 	}
-	write(G.netfd, G.buf, G.len);
+	write(G.netfd, G.buf, len);
 }
 
 
-static void handlenetinput()
+static void handlenetinput(int len)
 {
 	int i;
 	int cstart = 0;
 
-	for (i = 0; i < G.len; i++)
+	for (i = 0; i < len; i++)
 	{
 		byte c = G.buf[i];
 
@@ -290,11 +289,11 @@
 		if (G.iaclen)			iacflush();
 		if (G.telstate == TS_0)	G.telstate = 0;
 
-		G.len = cstart;
+		len = cstart;
 	}
 
-	if (G.len)
-		write(1, G.buf, G.len);
+	if (len)
+		write(1, G.buf, len);
 }
 
 
@@ -530,6 +529,7 @@
 {
 	struct in_addr host;
 	int port;
+	int len;
 #ifdef USE_POLL
 	struct pollfd ufds[2];
 #else	
@@ -547,15 +547,11 @@
 		exit(1);
 	
 	G.termios_raw = G.termios_def;
-
 	cfmakeraw(&G.termios_raw);
 	
 	if (argc < 2)	show_usage();
 	port = (argc > 2)? getport(argv[2]): 23;
 	
-	G.buf = xmalloc(DATABUFSIZE);
-	G.iacbuf = xmalloc(IACBUFSIZE);
-	
 	host = getserver(argv[1]);
 
 	G.netfd = remote_connect(host, port);
@@ -599,14 +595,14 @@
 			if (FD_ISSET(0, &rfds))
 #endif				
 			{
-				G.len = read(0, G.buf, DATABUFSIZE);
+				len = read(0, G.buf, DATABUFSIZE);
 
-				if (G.len <= 0)
+				if (len <= 0)
 					doexit(0);
 
-				TRACE(0, ("Read con: %d\n", G.len));
+				TRACE(0, ("Read con: %d\n", len));
 				
-				handlenetoutput();
+				handlenetoutput(len);
 			}
 
 #ifdef USE_POLL
@@ -615,16 +611,16 @@
 			if (FD_ISSET(G.netfd, &rfds))
 #endif				
 			{
-				G.len = read(G.netfd, G.buf, DATABUFSIZE);
+				len = read(G.netfd, G.buf, DATABUFSIZE);
 
-				if (G.len <= 0)
+				if (len <= 0)
 				{
 					WriteCS(1, "Connection closed by foreign host.\r\n");
 					doexit(1);
 				}
-				TRACE(0, ("Read netfd (%d): %d\n", G.netfd, G.len));
+				TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len));
 
-				handlenetinput();
+				handlenetinput(len);
 			}
 		}
 	}
diff --git a/util-linux/more.c b/util-linux/more.c
index 9f07633..6cdec72 100644
--- a/util-linux/more.c
+++ b/util-linux/more.c
@@ -9,6 +9,8 @@
  * based on the original more implementation by Bruce, and code from the 
  * Debian boot-floppies team.
  *
+ * Termios corrects by Vladimir Oleynik <vodz@usa.net>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -29,29 +31,26 @@
 #include <fcntl.h>
 #include <signal.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <sys/ioctl.h>
 #include "busybox.h"
 
-/* ED: sparc termios is broken: revert back to old termio handling. */
-#ifdef BB_FEATURE_USE_TERMIOS
-#	if #cpu(sparc)
-#		include <termio.h>
-#		define termios termio
-#		define setTermSettings(fd,argp) ioctl(fd,TCSETAF,argp)
-#		define getTermSettings(fd,argp) ioctl(fd,TCGETA,argp)
-#	else
-#		include <termios.h>
-#		define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
-#		define getTermSettings(fd,argp) tcgetattr(fd, argp);
-#	endif
-
 static FILE *cin;
 
+#ifdef BB_FEATURE_USE_TERMIOS
+#include <termios.h>
+#define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
+#define getTermSettings(fd,argp) tcgetattr(fd, argp);
+
 static struct termios initial_settings, new_settings;
 
-static void gotsig(int sig)
+static void set_tty_to_initial_mode(void)
 {
 	setTermSettings(fileno(cin), &initial_settings);
+}
+
+static void gotsig(int sig)
+{
 	putchar('\n');
 	exit(EXIT_FAILURE);
 }
@@ -65,7 +64,7 @@
 extern int more_main(int argc, char **argv)
 {
 	int c, lines, input = 0;
-	int please_display_more_prompt;
+	int please_display_more_prompt = -1;
 	struct stat st;
 	FILE *file;
 	int len, page_height;
@@ -77,46 +76,57 @@
 	argc--;
 	argv++;
 
+
+	/* not use inputing from terminal if usage: more > outfile */
+	if(isatty(fileno(stdout))) {
+		cin = fopen("/dev/tty", "r");
+		if (!cin)
+			cin = xfopen("/dev/console", "r");
+		please_display_more_prompt = 0;
+#ifdef BB_FEATURE_USE_TERMIOS
+		getTermSettings(fileno(cin), &initial_settings);
+		new_settings = initial_settings;
+		new_settings.c_lflag &= ~ICANON;
+		new_settings.c_lflag &= ~ECHO;
+#ifndef linux
+                /* Hmm, in linux c_cc[] not parsed if set ~ICANON */
+		new_settings.c_cc[VMIN] = 1;
+		new_settings.c_cc[VTIME] = 0;
+#endif
+		setTermSettings(fileno(cin), &new_settings);
+		atexit(set_tty_to_initial_mode);
+		(void) signal(SIGINT, gotsig);
+		(void) signal(SIGQUIT, gotsig);
+		(void) signal(SIGTERM, gotsig);
+#endif
+	}
+
 	do {
 		if (argc == 0) {
 			file = stdin;
 		} else
-			file = xfopen(*argv, "r");
-
+			file = wfopen(*argv, "r");
+		if(file==0)
+			goto loop;
+			
 		fstat(fileno(file), &st);
 
-#ifdef BB_FEATURE_USE_TERMIOS
-		cin = fopen("/dev/tty", "r");
-		if (!cin)
-			cin = xfopen("/dev/console", "r");
-		getTermSettings(fileno(cin), &initial_settings);
-		new_settings = initial_settings;
-		new_settings.c_cc[VMIN] = 1;
-		new_settings.c_cc[VTIME] = 0;
-		new_settings.c_lflag &= ~ICANON;
-		new_settings.c_lflag &= ~ECHO;
-		setTermSettings(fileno(cin), &new_settings);
+		if(please_display_more_prompt>0)
+			please_display_more_prompt = 0;
 
-#	ifdef BB_FEATURE_AUTOWIDTH
+#if defined BB_FEATURE_AUTOWIDTH && defined BB_FEATURE_USE_TERMIOS
 		ioctl(fileno(stdout), TIOCGWINSZ, &win);
 		if (win.ws_row > 4)
 			terminal_height = win.ws_row - 2;
 		if (win.ws_col > 0)
 			terminal_width = win.ws_col - 1;
-#	endif
-
-		(void) signal(SIGINT, gotsig);
-		(void) signal(SIGQUIT, gotsig);
-		(void) signal(SIGTERM, gotsig);
-
 #endif
 		len=0;
 		lines = 0;
 		page_height = terminal_height;
-		please_display_more_prompt = 0;
 		while ((c = getc(file)) != EOF) {
 
-			if (please_display_more_prompt) {
+			if (please_display_more_prompt>0) {
 				len = printf("--More-- ");
 				if (file != stdin) {
 #if _FILE_OFFSET_BITS == 64
@@ -129,13 +139,6 @@
 						   (double) st.st_size)), (long)st.st_size);
 #endif
 				}
-				len += printf("%s",
-#ifdef BB_FEATURE_USE_TERMIOS
-							   ""
-#else
-							   "\n"
-#endif
-					);
 
 				fflush(stdout);
 
@@ -143,20 +146,16 @@
 				 * We've just displayed the "--More--" prompt, so now we need
 				 * to get input from the user.
 				 */
-#ifdef BB_FEATURE_USE_TERMIOS
 				input = getc(cin);
-#else
-				input = getc(stdin);
+#ifndef BB_FEATURE_USE_TERMIOS
+				printf("\033[A"); /* up cursor */
 #endif
-
-#ifdef BB_FEATURE_USE_TERMIOS
 				/* Erase the "More" message */
 				putc('\r', stdout);
 				while (--len >= 0)
 					putc(' ', stdout);
 				putc('\r', stdout);
 				fflush(stdout);
-#endif
 				len=0;
 				lines = 0;
 				page_height = terminal_height;
@@ -180,6 +179,7 @@
 				/* increment by just one line if we are at
 				 * the end of this line */
 				if (input == '\n')
+					if(please_display_more_prompt==0)
 					please_display_more_prompt = 1;
 				/* Adjust the terminal height for any overlap, so that
 				 * no lines get lost off the top. */
@@ -195,6 +195,7 @@
 					}
 				}
 				if (++lines >= page_height) {
+					if(please_display_more_prompt==0)
 					please_display_more_prompt = 1;
 				}
 				len=0;
@@ -208,12 +209,9 @@
 		}
 		fclose(file);
 		fflush(stdout);
-
+loop:
 		argv++;
 	} while (--argc > 0);
   end:
-#ifdef BB_FEATURE_USE_TERMIOS
-	setTermSettings(fileno(cin), &initial_settings);
-#endif
 	return 0;
 }
diff --git a/vi.c b/vi.c
index bd183e8..e1ff933 100644
--- a/vi.c
+++ b/vi.c
@@ -19,7 +19,7 @@
  */
 
 char *vi_Version =
-	"$Id: vi.c,v 1.9 2001/06/23 13:49:14 andersen Exp $";
+	"$Id: vi.c,v 1.10 2001/06/26 02:06:08 bug1 Exp $";
 
 /*
  * To compile for standalone use:
@@ -3152,8 +3152,10 @@
 	term_vi.c_lflag &= (~ICANON & ~ECHO);	// leave ISIG ON- allow intr's
 	term_vi.c_iflag &= (~IXON & ~ICRNL);
 	term_vi.c_oflag &= (~ONLCR);
+#ifndef linux
 	term_vi.c_cc[VMIN] = 1;
 	term_vi.c_cc[VTIME] = 0;
+#endif
 	erase_char = term_vi.c_cc[VERASE];
 	tcsetattr(0, TCSANOW, &term_vi);
 }