Patch from vodz:
    Changed email address
    cmdedit API change
    optimizations for traceroute and md5sum
    added a new shared create_icmp_socket() function
diff --git a/shell/ash.c b/shell/ash.c
index 9855073..334d2fd 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -26,7 +26,7 @@
  * package.
  *
  * Modified by Erik Andersen <andersee@debian.org> and
- * Vladimir Oleynik <vodz@usa.net> to be used in busybox
+ * Vladimir Oleynik <dzo@simtreas.ru> to be used in busybox
  *
  *
  * Original copyright notice is retained at the end of this file.
@@ -4995,7 +4995,7 @@
 		if (--in.nleft < 0) {
 			if (in.fd < 0)
 				break;
-			while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
+			i = safe_read(in.fd, buf, sizeof buf);
 			TRACE(("expbackq: read returns %d\n", i));
 			if (i <= 0)
 				break;
@@ -6091,10 +6091,8 @@
  * interactive shell and control is returned to the main command loop.
  */
 
-#ifdef ASH_ALIAS
 /* 1 == check for aliases, 2 == also check for assignments */
-static int checkalias;
-#endif
+static int checkalias;  /* also used in no alias mode for check assignments */
 
 static void
 reset(void) {
@@ -6117,9 +6115,7 @@
       {
 	      tokpushback = 0;
 	      checkkwd = 0;
-#ifdef ASH_ALIAS
 	      checkalias = 0;
-#endif
       }
 
       /* from redir.c: */
@@ -6137,7 +6133,6 @@
  */
 
 #ifdef BB_FEATURE_COMMAND_EDITING
-unsigned int shell_context;
 static const char * cmdedit_prompt;
 static inline void putprompt(const char *s) {
     cmdedit_prompt = s;
@@ -6206,23 +6201,18 @@
 retry:
 #ifdef BB_FEATURE_COMMAND_EDITING
 	{
-	    if (parsefile->fd)
-		nr = read(parsefile->fd, buf, BUFSIZ - 1);
+	    if (!iflag)
+		    nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
 	    else {
-		do {
 		    cmdedit_read_input((char*)cmdedit_prompt, buf);
 		    nr = strlen(buf);
-		} while (nr <=0 || shell_context);
-		cmdedit_terminate();
 	    }
 	}
 #else
-	nr = read(parsefile->fd, buf, BUFSIZ - 1);
+	nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
 #endif
 
 	if (nr < 0) {
-		if (errno == EINTR)
-			goto retry;
 		if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
 			int flags = fcntl(0, F_GETFL, 0);
 			if (flags >= 0 && flags & O_NONBLOCK) {
@@ -9872,9 +9862,7 @@
 	redir = NULL;
 	rpp = &redir;
 
-#ifdef ASH_ALIAS
 	checkalias = 2;
-#endif
 	for (;;) {
 		switch (readtoken()) {
 		case TWORD:
@@ -10036,9 +10024,10 @@
 static int
 readtoken() {
 	int t;
+
 #ifdef ASH_ALIAS
-	int savecheckkwd = checkkwd;
 	int savecheckalias = checkalias;
+	int savecheckkwd = checkkwd;
 	struct alias *ap;
 #endif
 
@@ -10083,13 +10072,14 @@
 		}
 	}
 
-#ifdef ASH_ALIAS
+
 	if (t != TWORD) {
 		if (t != TREDIR) {
 			checkalias = 0;
 		}
 	} else if (checkalias == 2 && isassignment(wordtext)) {
 		lasttoken = t = TASSIGN;
+#ifdef ASH_ALIAS
 	} else if (checkalias) {
 		if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) {
 			if (*ap->val) {
@@ -10099,8 +10089,8 @@
 			goto top;
 		}
 		checkalias = 0;
-	}
 #endif
+	}
 out:
 #ifdef DEBUG
 	if (!alreadyseen)
@@ -12927,7 +12917,7 @@
 /*
  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
  * This file contains code for the times builtin.
- * $Id: ash.c,v 1.9 2001/07/10 16:57:09 andersen Exp $
+ * $Id: ash.c,v 1.10 2001/07/12 20:26:31 andersen Exp $
  */
 static int timescmd (int argc, char **argv)
 {
diff --git a/shell/cmdedit.c b/shell/cmdedit.c
index 4f124d6..540eb7e 100644
--- a/shell/cmdedit.c
+++ b/shell/cmdedit.c
@@ -3,7 +3,7 @@
  * Termios command line History and Editting.
  *
  * Copyright (c) 1986-2001 may safely be consumed by a BSD or GPL license.
- * Written by:   Vladimir Oleynik <vodz@usa.net>
+ * Written by:   Vladimir Oleynik <dzo@simtreas.ru>
  *
  * Used ideas:
  *      Adam Rogoyski    <rogoyski@cs.utexas.edu>
@@ -123,9 +123,8 @@
 enum {
 	SET_ATEXIT = 1,		/* when atexit() has been called 
 				   and get euid,uid,gid to fast compare */
-	SET_TERM_HANDLERS = 2,	/* set many terminates signal handlers */
-	SET_WCHG_HANDLERS = 4,	/* winchg signal handler */
-	SET_RESET_TERM = 8,	/* if the terminal needs to be reset upon exit */
+	SET_WCHG_HANDLERS = 2,  /* winchg signal handler */
+	SET_RESET_TERM = 4,     /* if the terminal needs to be reset upon exit */
 };
 
 
@@ -142,10 +141,6 @@
 #endif
 char *cmdedit_prompt;		/* --- "" - - "" - -"- --""-- --""--- */
 
-/* Link into lash to reset context to 0 on ^C and such */
-extern unsigned int shell_context;
-
-
 #ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR
 static char *user_buf = "";
 static char *home_pwd_buf = "";
@@ -319,6 +314,7 @@
 	out1str(cmdedit_prompt);
 	cmdedit_x = cmdedit_prmt_len;	/* count real x terminal position */
 	cursor = 0;
+	cmdedit_y = 0;                  /* new quasireal y */
 }
 
 #ifndef BB_FEATURE_SH_FANCY_PROMPT
@@ -456,7 +452,6 @@
 {
 	if (y > 0)				/* up to start y */
 		printf("\033[%dA", y);
-	cmdedit_y = 0;				/* new quasireal y */
 	putchar('\r');
 	put_prompt();
 	input_end();				/* rewrite */
@@ -497,14 +492,6 @@
 }
 
 
-static void clean_up_and_die(int sig)
-{
-	goto_new_line();
-	if (sig != SIGINT)
-		exit(EXIT_SUCCESS);	/* cmdedit_reset_term() called in atexit */
-	cmdedit_reset_term();
-}
-
 static void cmdedit_setwidth(int w, int redraw_flg)
 {
 	cmdedit_termw = cmdedit_prmt_len + 2;
@@ -525,7 +512,7 @@
 	} 
 }
 
-extern void cmdedit_init(void)
+static void cmdedit_init(void)
 {
 	cmdedit_prmt_len = 0;
 	if ((handlers_sets & SET_WCHG_HANDLERS) == 0) {
@@ -557,14 +544,6 @@
 		handlers_sets |= SET_ATEXIT;
 		atexit(cmdedit_reset_term);	/* be sure to do this only once */
 	}
-
-	if ((handlers_sets & SET_TERM_HANDLERS) == 0) {
-		signal(SIGKILL, clean_up_and_die);
-		signal(SIGINT, clean_up_and_die);
-		signal(SIGQUIT, clean_up_and_die);
-		signal(SIGTERM, clean_up_and_die);
-		handlers_sets |= SET_TERM_HANDLERS;
-	}
 }
 
 #ifdef BB_FEATURE_COMMAND_TAB_COMPLETION
@@ -1220,7 +1199,7 @@
 
 		fflush(stdout);			/* buffered out to fast */
 
-		if (read(0, &c, 1) < 1)
+		if (safe_read(0, &c, 1) < 1)
 			/* if we can't read input then exit */
 			goto prepare_to_die;
 
@@ -1241,22 +1220,21 @@
 			break;
 		case 3:
 			/* Control-c -- stop gathering input */
-
-			/* Link into lash to reset context to 0 on ^C and such */
-			shell_context = 0;
-
-			/* Go to the next line */
 			goto_new_line();
 			command[0] = 0;
-
-			return;
+			len = 0;
+			lastWasTab = FALSE;
+			put_prompt();
+			break;
 		case 4:
 			/* Control-d -- Delete one character, or exit
 			 * if the len=0 and no chars to delete */
 			if (len == 0) {
 prepare_to_die:
 				printf("exit");
-				clean_up_and_die(0);
+				goto_new_line();
+				/* cmdedit_reset_term() called in atexit */
+				exit(EXIT_SUCCESS);
 			} else {
 				input_delete();
 			}
@@ -1307,12 +1285,12 @@
 
 		case ESC:{
 			/* escape sequence follows */
-			if (read(0, &c, 1) < 1)
-				return;
+			if (safe_read(0, &c, 1) < 1)
+				goto prepare_to_die;
 			/* different vt100 emulations */
 			if (c == '[' || c == 'O') {
-				if (read(0, &c, 1) < 1)
-					return;
+				if (safe_read(0, &c, 1) < 1)
+					goto prepare_to_die;
 			}
 			switch (c) {
 #ifdef BB_FEATURE_COMMAND_TAB_COMPLETION
@@ -1376,8 +1354,8 @@
 			}
 			if (c >= '1' && c <= '9')
 				do
-					if (read(0, &c, 1) < 1)
-						return;
+					if (safe_read(0, &c, 1) < 1)
+						goto prepare_to_die;
 				while (c != '~');
 			break;
 		}
@@ -1386,8 +1364,8 @@
 #ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT
 			/* Control-V -- Add non-printable symbol */
 			if (c == 22) {
-				if (read(0, &c, 1) < 1)
-					return;
+				if (safe_read(0, &c, 1) < 1)
+					goto prepare_to_die;
 				if (c == 0) {
 					beep();
 					break;
@@ -1485,24 +1463,11 @@
 #if defined(BB_FEATURE_SH_FANCY_PROMPT)
 	free(cmdedit_prompt);
 #endif
-	return;
-}
-
-
-/* Undo the effects of cmdedit_init(). */
-extern void cmdedit_terminate(void)
-{
 	cmdedit_reset_term();
-	if ((handlers_sets & SET_TERM_HANDLERS) != 0) {
-		signal(SIGKILL, SIG_DFL);
-		signal(SIGINT, SIG_DFL);
-		signal(SIGQUIT, SIG_DFL);
-		signal(SIGTERM, SIG_DFL);
-		signal(SIGWINCH, SIG_DFL);
-		handlers_sets &= ~SET_TERM_HANDLERS;
-	}
 }
 
+
+
 #endif	/* BB_FEATURE_COMMAND_EDITING */
 
 
@@ -1515,8 +1480,6 @@
 #include <locale.h>
 #endif
 
-unsigned int shell_context;
-
 int main(int argc, char **argv)
 {
 	char buff[BUFSIZ];
@@ -1532,15 +1495,16 @@
 #ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT
 	setlocale(LC_ALL, "");
 #endif
-	shell_context = 1;
-	do {
+	while(1) {
 		int l;
 		cmdedit_read_input(prompt, buff);
 		l = strlen(buff);
+		if(l==0)
+			break;
 		if(l > 0 && buff[l-1] == '\n')
 			buff[l-1] = 0;
 		printf("*** cmdedit_read_input() returned line =%s=\n", buff);
-	} while (shell_context);
+	}
 	printf("*** cmdedit_read_input() detect ^C\n");
 	return 0;
 }
diff --git a/shell/cmdedit.h b/shell/cmdedit.h
index 9e3e44b..1482da3 100644
--- a/shell/cmdedit.h
+++ b/shell/cmdedit.h
@@ -1,8 +1,6 @@
 #ifndef CMDEDIT_H
 #define CMDEDIT_H
 
-void cmdedit_init(void);
-void cmdedit_terminate(void);
 void cmdedit_read_input(char* promptStr, char* command);		/* read a line of input */
 
 #endif /* CMDEDIT_H */
diff --git a/shell/hush.c b/shell/hush.c
index b74b9d1..1344042 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -237,10 +237,6 @@
 unsigned int last_return_code;
 extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
  
-/* Variables we export */
-unsigned int shell_context;  /* Used in cmdedit.c to reset the
-                              * context when someone hits ^C */
-
 /* "globals" within this file */
 static char *ifs;
 static char map[256];
@@ -883,7 +879,6 @@
 	 ** child processes (rob@sysgo.de)
 	 */
 	cmdedit_read_input(prompt_str, the_command);
-	cmdedit_terminate();
 #else
 	fputs(prompt_str, stdout);
 	fflush(stdout);
@@ -1411,6 +1406,7 @@
 			/* Set the handling for job control signals back to the default.  */
 			signal(SIGINT, SIG_DFL);
 			signal(SIGQUIT, SIG_DFL);
+			signal(SIGTERM, SIG_DFL);
 			signal(SIGTSTP, SIG_DFL);
 			signal(SIGTTIN, SIG_DFL);
 			signal(SIGTTOU, SIG_DFL);
@@ -2551,6 +2547,7 @@
 	/* Ignore interactive and job-control signals.  */
 	signal(SIGINT, SIG_IGN);
 	signal(SIGQUIT, SIG_IGN);
+	signal(SIGTERM, SIG_IGN);
 	signal(SIGTSTP, SIG_IGN);
 	signal(SIGTTIN, SIG_IGN);
 	signal(SIGTTOU, SIG_IGN);
diff --git a/shell/lash.c b/shell/lash.c
index 7c932a9..8f86095 100644
--- a/shell/lash.c
+++ b/shell/lash.c
@@ -170,9 +170,7 @@
 };
 
 
-/* Variables we export */
-unsigned int shell_context;  /* Used in cmdedit.c to reset the
-								context when someone hits ^C */
+static int shell_context;  /* Type prompt trigger (PS1 or PS2) */
 
 
 /* Globals that are static to this file */
@@ -716,7 +714,6 @@
 		** child processes (rob@sysgo.de)
 		*/
 		cmdedit_read_input(prompt_str, command);
-		cmdedit_terminate();
 		return 0;
 #else
 		fputs(prompt_str, stdout);
@@ -1557,7 +1554,6 @@
 
 	/* These variables need re-initializing when recursing */
 	last_jobid = 0;
-	shell_context = 0;
 	local_pending_command = NULL;
 	close_me_head = NULL;
 	job_list.head = NULL;
diff --git a/shell/msh.c b/shell/msh.c
index 230d74f..8f046e7 100644
--- a/shell/msh.c
+++ b/shell/msh.c
@@ -682,8 +682,7 @@
 
 
 #ifdef BB_FEATURE_COMMAND_EDITING
-char * current_prompt;
-unsigned int shell_context;
+static char * current_prompt;
 #endif
 
 
@@ -4449,9 +4448,7 @@
 	  if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
 	    if (i)
 	      lseek(ap->afile, ap->afpos, 0);
-	    do {
-	      i = read(ap->afile, bp->buf, sizeof(bp->buf));
-	    } while (i < 0 && errno == EINTR);
+	    i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
 	    if (i <= 0) {
 	      closef(ap->afile);
 	      return 0;
@@ -4470,7 +4467,6 @@
 
 	    while (size == 0 || position >= size) {
 		cmdedit_read_input(current_prompt, mycommand);
-		cmdedit_terminate();
 		size = strlen(mycommand);
 		position = 0;
 	    }
@@ -4480,9 +4476,7 @@
 	} else 
 #endif
 	{
-		do {
-			i = read(ap->afile, &c, sizeof(c));
-		} while (i < 0 && errno == EINTR);
+		i = safe_read(ap->afile, &c, sizeof(c));
 		return(i == sizeof(c)? c&0177: (closef(ap->afile), 0));
 	}
 }