aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-07-12 20:26:32 +0000
committerEric Andersen <andersen@codepoet.org>2001-07-12 20:26:32 +0000
commit7467c8d3b6a50e2cbd8db750963d40b420ad38d1 (patch)
tree10dcece1e0bb88e35aa95c3a68896ad426e43f7a
parentf69bfc76fa7acb0c87fa3f3b319fde361a8315a8 (diff)
downloadbusybox-w32-7467c8d3b6a50e2cbd8db750963d40b420ad38d1.tar.gz
busybox-w32-7467c8d3b6a50e2cbd8db750963d40b420ad38d1.tar.bz2
busybox-w32-7467c8d3b6a50e2cbd8db750963d40b420ad38d1.zip
Patch from vodz:
Changed email address cmdedit API change optimizations for traceroute and md5sum added a new shared create_icmp_socket() function
-rw-r--r--AUTHORS2
-rw-r--r--Changelog5
-rw-r--r--Makefile6
-rw-r--r--ash.c34
-rw-r--r--cmdedit.c88
-rw-r--r--cmdedit.h2
-rw-r--r--coreutils/md5sum.c12
-rw-r--r--coreutils/stty.c2
-rw-r--r--hush.c7
-rw-r--r--include/libbb.h2
-rw-r--r--lash.c6
-rw-r--r--libbb/create_icmp_socket.c37
-rw-r--r--libbb/libbb.h2
-rw-r--r--libbb/messages.c3
-rw-r--r--md5sum.c12
-rw-r--r--msh.c12
-rw-r--r--networking/ping.c10
-rw-r--r--networking/traceroute.c511
-rw-r--r--ping.c10
-rw-r--r--shell/ash.c34
-rw-r--r--shell/cmdedit.c88
-rw-r--r--shell/cmdedit.h2
-rw-r--r--shell/hush.c7
-rw-r--r--shell/lash.c6
-rw-r--r--shell/msh.c12
-rw-r--r--stty.c2
-rw-r--r--traceroute.c511
27 files changed, 639 insertions, 786 deletions
diff --git a/AUTHORS b/AUTHORS
index bb6f6782e..92d16f5b2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -74,7 +74,7 @@ Enrique Zanardi <ezanardi@ull.es>
74 tarcat (since removed), loadkmap, various fixes, Debian maintenance 74 tarcat (since removed), loadkmap, various fixes, Debian maintenance
75 75
76Vladimir Oleynik <dzo@simtreas.ru> 76Vladimir Oleynik <dzo@simtreas.ru>
77 cmdedit, stty-port, locale, various fixes 77 cmdedit; ports: ash, stty, traceroute; locale, various fixes
78 and irreconcilable critic of everything not perfect. 78 and irreconcilable critic of everything not perfect.
79 79
80Tim Riker <Tim@Rikers.org> 80Tim Riker <Tim@Rikers.org>
diff --git a/Changelog b/Changelog
index 90b767d81..cd8b992f9 100644
--- a/Changelog
+++ b/Changelog
@@ -4,10 +4,11 @@
4 * None yet 4 * None yet
5 5
6 New Applets: 6 New Applets:
7 * None yet 7 * Vladimir Oleynik -- traceroute
8 8
9 Other Changes: 9 Other Changes:
10 * Vladimir Oleynik -- Fixed tr to support 'tr a-z A-Z' syntax. 10 * Vladimir Oleynik -- Fixed tr to support 'tr a-z A-Z' syntax,
11 many ash corrections, and others optimizations, and cleanups.
11 12
12 13
13 -Not Yet Released 14 -Not Yet Released
diff --git a/Makefile b/Makefile
index 8ea5395d2..2b31895e6 100644
--- a/Makefile
+++ b/Makefile
@@ -247,7 +247,7 @@ safe_read.c safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \
247trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \ 247trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \
248xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \ 248xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \
249copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \ 249copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \
250dirname.c make_directory.c 250dirname.c make_directory.c create_icmp_socket.c
251LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC)) 251LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC))
252LIBBB_CFLAGS = -I$(LIBBB) 252LIBBB_CFLAGS = -I$(LIBBB)
253ifneq ($(strip $(BB_SRC_DIR)),) 253ifneq ($(strip $(BB_SRC_DIR)),)
@@ -257,7 +257,7 @@ endif
257LIBBB_MSRC=libbb/messages.c 257LIBBB_MSRC=libbb/messages.c
258LIBBB_MESSAGES= full_version name_too_long omitting_directory not_a_directory \ 258LIBBB_MESSAGES= full_version name_too_long omitting_directory not_a_directory \
259memory_exhausted invalid_date invalid_option io_error dash_dash_help \ 259memory_exhausted invalid_date invalid_option io_error dash_dash_help \
260write_error too_few_args name_longer_than_foo unknown 260write_error too_few_args name_longer_than_foo unknown can_not_create_raw_socket
261LIBBB_MOBJ=$(patsubst %,$(LIBBB)/%.o, $(LIBBB_MESSAGES)) 261LIBBB_MOBJ=$(patsubst %,$(LIBBB)/%.o, $(LIBBB_MESSAGES))
262 262
263LIBBB_ARCSRC=libbb/unarchive.c 263LIBBB_ARCSRC=libbb/unarchive.c
@@ -365,7 +365,7 @@ $(LIBBB_MOBJ): $(LIBBB_MSRC)
365 - mkdir -p $(LIBBB) 365 - mkdir -p $(LIBBB)
366 $(CC) $(CFLAGS) $(LIBBB_CFLAGS) -DL_$(patsubst libbb/%,%,$*) -c $< -o $*.o 366 $(CC) $(CFLAGS) $(LIBBB_CFLAGS) -DL_$(patsubst libbb/%,%,$*) -c $< -o $*.o
367 367
368$(LIBBB_AROBJS): $(LIBBB_ARCSRC) Makefile 368$(LIBBB_AROBJS): $(LIBBB_ARCSRC)
369 - mkdir -p $(LIBBB) 369 - mkdir -p $(LIBBB)
370 $(CC) $(CFLAGS) $(LIBBB_CFLAGS) -DL_$(patsubst libbb/%,%,$*) -c $< -o $*.o 370 $(CC) $(CFLAGS) $(LIBBB_CFLAGS) -DL_$(patsubst libbb/%,%,$*) -c $< -o $*.o
371 371
diff --git a/ash.c b/ash.c
index 985507341..334d2fddd 100644
--- a/ash.c
+++ b/ash.c
@@ -26,7 +26,7 @@
26 * package. 26 * package.
27 * 27 *
28 * Modified by Erik Andersen <andersee@debian.org> and 28 * Modified by Erik Andersen <andersee@debian.org> and
29 * Vladimir Oleynik <vodz@usa.net> to be used in busybox 29 * Vladimir Oleynik <dzo@simtreas.ru> to be used in busybox
30 * 30 *
31 * 31 *
32 * Original copyright notice is retained at the end of this file. 32 * Original copyright notice is retained at the end of this file.
@@ -4995,7 +4995,7 @@ err1:
4995 if (--in.nleft < 0) { 4995 if (--in.nleft < 0) {
4996 if (in.fd < 0) 4996 if (in.fd < 0)
4997 break; 4997 break;
4998 while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR); 4998 i = safe_read(in.fd, buf, sizeof buf);
4999 TRACE(("expbackq: read returns %d\n", i)); 4999 TRACE(("expbackq: read returns %d\n", i));
5000 if (i <= 0) 5000 if (i <= 0)
5001 break; 5001 break;
@@ -6091,10 +6091,8 @@ init(void) {
6091 * interactive shell and control is returned to the main command loop. 6091 * interactive shell and control is returned to the main command loop.
6092 */ 6092 */
6093 6093
6094#ifdef ASH_ALIAS
6095/* 1 == check for aliases, 2 == also check for assignments */ 6094/* 1 == check for aliases, 2 == also check for assignments */
6096static int checkalias; 6095static int checkalias; /* also used in no alias mode for check assignments */
6097#endif
6098 6096
6099static void 6097static void
6100reset(void) { 6098reset(void) {
@@ -6117,9 +6115,7 @@ reset(void) {
6117 { 6115 {
6118 tokpushback = 0; 6116 tokpushback = 0;
6119 checkkwd = 0; 6117 checkkwd = 0;
6120#ifdef ASH_ALIAS
6121 checkalias = 0; 6118 checkalias = 0;
6122#endif
6123 } 6119 }
6124 6120
6125 /* from redir.c: */ 6121 /* from redir.c: */
@@ -6137,7 +6133,6 @@ reset(void) {
6137 */ 6133 */
6138 6134
6139#ifdef BB_FEATURE_COMMAND_EDITING 6135#ifdef BB_FEATURE_COMMAND_EDITING
6140unsigned int shell_context;
6141static const char * cmdedit_prompt; 6136static const char * cmdedit_prompt;
6142static inline void putprompt(const char *s) { 6137static inline void putprompt(const char *s) {
6143 cmdedit_prompt = s; 6138 cmdedit_prompt = s;
@@ -6206,23 +6201,18 @@ preadfd(void)
6206retry: 6201retry:
6207#ifdef BB_FEATURE_COMMAND_EDITING 6202#ifdef BB_FEATURE_COMMAND_EDITING
6208 { 6203 {
6209 if (parsefile->fd) 6204 if (!iflag)
6210 nr = read(parsefile->fd, buf, BUFSIZ - 1); 6205 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6211 else { 6206 else {
6212 do {
6213 cmdedit_read_input((char*)cmdedit_prompt, buf); 6207 cmdedit_read_input((char*)cmdedit_prompt, buf);
6214 nr = strlen(buf); 6208 nr = strlen(buf);
6215 } while (nr <=0 || shell_context);
6216 cmdedit_terminate();
6217 } 6209 }
6218 } 6210 }
6219#else 6211#else
6220 nr = read(parsefile->fd, buf, BUFSIZ - 1); 6212 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6221#endif 6213#endif
6222 6214
6223 if (nr < 0) { 6215 if (nr < 0) {
6224 if (errno == EINTR)
6225 goto retry;
6226 if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 6216 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6227 int flags = fcntl(0, F_GETFL, 0); 6217 int flags = fcntl(0, F_GETFL, 0);
6228 if (flags >= 0 && flags & O_NONBLOCK) { 6218 if (flags >= 0 && flags & O_NONBLOCK) {
@@ -9872,9 +9862,7 @@ simplecmd() {
9872 redir = NULL; 9862 redir = NULL;
9873 rpp = &redir; 9863 rpp = &redir;
9874 9864
9875#ifdef ASH_ALIAS
9876 checkalias = 2; 9865 checkalias = 2;
9877#endif
9878 for (;;) { 9866 for (;;) {
9879 switch (readtoken()) { 9867 switch (readtoken()) {
9880 case TWORD: 9868 case TWORD:
@@ -10036,9 +10024,10 @@ peektoken() {
10036static int 10024static int
10037readtoken() { 10025readtoken() {
10038 int t; 10026 int t;
10027
10039#ifdef ASH_ALIAS 10028#ifdef ASH_ALIAS
10040 int savecheckkwd = checkkwd;
10041 int savecheckalias = checkalias; 10029 int savecheckalias = checkalias;
10030 int savecheckkwd = checkkwd;
10042 struct alias *ap; 10031 struct alias *ap;
10043#endif 10032#endif
10044 10033
@@ -10083,13 +10072,14 @@ top:
10083 } 10072 }
10084 } 10073 }
10085 10074
10086#ifdef ASH_ALIAS 10075
10087 if (t != TWORD) { 10076 if (t != TWORD) {
10088 if (t != TREDIR) { 10077 if (t != TREDIR) {
10089 checkalias = 0; 10078 checkalias = 0;
10090 } 10079 }
10091 } else if (checkalias == 2 && isassignment(wordtext)) { 10080 } else if (checkalias == 2 && isassignment(wordtext)) {
10092 lasttoken = t = TASSIGN; 10081 lasttoken = t = TASSIGN;
10082#ifdef ASH_ALIAS
10093 } else if (checkalias) { 10083 } else if (checkalias) {
10094 if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) { 10084 if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) {
10095 if (*ap->val) { 10085 if (*ap->val) {
@@ -10099,8 +10089,8 @@ top:
10099 goto top; 10089 goto top;
10100 } 10090 }
10101 checkalias = 0; 10091 checkalias = 0;
10102 }
10103#endif 10092#endif
10093 }
10104out: 10094out:
10105#ifdef DEBUG 10095#ifdef DEBUG
10106 if (!alreadyseen) 10096 if (!alreadyseen)
@@ -12927,7 +12917,7 @@ findvar(struct var **vpp, const char *name)
12927/* 12917/*
12928 * Copyright (c) 1999 Herbert Xu <herbert@debian.org> 12918 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12929 * This file contains code for the times builtin. 12919 * This file contains code for the times builtin.
12930 * $Id: ash.c,v 1.9 2001/07/10 16:57:09 andersen Exp $ 12920 * $Id: ash.c,v 1.10 2001/07/12 20:26:31 andersen Exp $
12931 */ 12921 */
12932static int timescmd (int argc, char **argv) 12922static int timescmd (int argc, char **argv)
12933{ 12923{
diff --git a/cmdedit.c b/cmdedit.c
index 4f124d647..540eb7ea7 100644
--- a/cmdedit.c
+++ b/cmdedit.c
@@ -3,7 +3,7 @@
3 * Termios command line History and Editting. 3 * Termios command line History and Editting.
4 * 4 *
5 * Copyright (c) 1986-2001 may safely be consumed by a BSD or GPL license. 5 * Copyright (c) 1986-2001 may safely be consumed by a BSD or GPL license.
6 * Written by: Vladimir Oleynik <vodz@usa.net> 6 * Written by: Vladimir Oleynik <dzo@simtreas.ru>
7 * 7 *
8 * Used ideas: 8 * Used ideas:
9 * Adam Rogoyski <rogoyski@cs.utexas.edu> 9 * Adam Rogoyski <rogoyski@cs.utexas.edu>
@@ -123,9 +123,8 @@ volatile int handlers_sets = 0; /* Set next bites: */
123enum { 123enum {
124 SET_ATEXIT = 1, /* when atexit() has been called 124 SET_ATEXIT = 1, /* when atexit() has been called
125 and get euid,uid,gid to fast compare */ 125 and get euid,uid,gid to fast compare */
126 SET_TERM_HANDLERS = 2, /* set many terminates signal handlers */ 126 SET_WCHG_HANDLERS = 2, /* winchg signal handler */
127 SET_WCHG_HANDLERS = 4, /* winchg signal handler */ 127 SET_RESET_TERM = 4, /* if the terminal needs to be reset upon exit */
128 SET_RESET_TERM = 8, /* if the terminal needs to be reset upon exit */
129}; 128};
130 129
131 130
@@ -142,10 +141,6 @@ static
142#endif 141#endif
143char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */ 142char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */
144 143
145/* Link into lash to reset context to 0 on ^C and such */
146extern unsigned int shell_context;
147
148
149#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR 144#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR
150static char *user_buf = ""; 145static char *user_buf = "";
151static char *home_pwd_buf = ""; 146static char *home_pwd_buf = "";
@@ -319,6 +314,7 @@ static void put_prompt(void)
319 out1str(cmdedit_prompt); 314 out1str(cmdedit_prompt);
320 cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */ 315 cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */
321 cursor = 0; 316 cursor = 0;
317 cmdedit_y = 0; /* new quasireal y */
322} 318}
323 319
324#ifndef BB_FEATURE_SH_FANCY_PROMPT 320#ifndef BB_FEATURE_SH_FANCY_PROMPT
@@ -456,7 +452,6 @@ static void redraw(int y, int back_cursor)
456{ 452{
457 if (y > 0) /* up to start y */ 453 if (y > 0) /* up to start y */
458 printf("\033[%dA", y); 454 printf("\033[%dA", y);
459 cmdedit_y = 0; /* new quasireal y */
460 putchar('\r'); 455 putchar('\r');
461 put_prompt(); 456 put_prompt();
462 input_end(); /* rewrite */ 457 input_end(); /* rewrite */
@@ -497,14 +492,6 @@ static void input_forward(void)
497} 492}
498 493
499 494
500static void clean_up_and_die(int sig)
501{
502 goto_new_line();
503 if (sig != SIGINT)
504 exit(EXIT_SUCCESS); /* cmdedit_reset_term() called in atexit */
505 cmdedit_reset_term();
506}
507
508static void cmdedit_setwidth(int w, int redraw_flg) 495static void cmdedit_setwidth(int w, int redraw_flg)
509{ 496{
510 cmdedit_termw = cmdedit_prmt_len + 2; 497 cmdedit_termw = cmdedit_prmt_len + 2;
@@ -525,7 +512,7 @@ static void cmdedit_setwidth(int w, int redraw_flg)
525 } 512 }
526} 513}
527 514
528extern void cmdedit_init(void) 515static void cmdedit_init(void)
529{ 516{
530 cmdedit_prmt_len = 0; 517 cmdedit_prmt_len = 0;
531 if ((handlers_sets & SET_WCHG_HANDLERS) == 0) { 518 if ((handlers_sets & SET_WCHG_HANDLERS) == 0) {
@@ -557,14 +544,6 @@ extern void cmdedit_init(void)
557 handlers_sets |= SET_ATEXIT; 544 handlers_sets |= SET_ATEXIT;
558 atexit(cmdedit_reset_term); /* be sure to do this only once */ 545 atexit(cmdedit_reset_term); /* be sure to do this only once */
559 } 546 }
560
561 if ((handlers_sets & SET_TERM_HANDLERS) == 0) {
562 signal(SIGKILL, clean_up_and_die);
563 signal(SIGINT, clean_up_and_die);
564 signal(SIGQUIT, clean_up_and_die);
565 signal(SIGTERM, clean_up_and_die);
566 handlers_sets |= SET_TERM_HANDLERS;
567 }
568} 547}
569 548
570#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION 549#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION
@@ -1220,7 +1199,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ])
1220 1199
1221 fflush(stdout); /* buffered out to fast */ 1200 fflush(stdout); /* buffered out to fast */
1222 1201
1223 if (read(0, &c, 1) < 1) 1202 if (safe_read(0, &c, 1) < 1)
1224 /* if we can't read input then exit */ 1203 /* if we can't read input then exit */
1225 goto prepare_to_die; 1204 goto prepare_to_die;
1226 1205
@@ -1241,22 +1220,21 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ])
1241 break; 1220 break;
1242 case 3: 1221 case 3:
1243 /* Control-c -- stop gathering input */ 1222 /* Control-c -- stop gathering input */
1244
1245 /* Link into lash to reset context to 0 on ^C and such */
1246 shell_context = 0;
1247
1248 /* Go to the next line */
1249 goto_new_line(); 1223 goto_new_line();
1250 command[0] = 0; 1224 command[0] = 0;
1251 1225 len = 0;
1252 return; 1226 lastWasTab = FALSE;
1227 put_prompt();
1228 break;
1253 case 4: 1229 case 4:
1254 /* Control-d -- Delete one character, or exit 1230 /* Control-d -- Delete one character, or exit
1255 * if the len=0 and no chars to delete */ 1231 * if the len=0 and no chars to delete */
1256 if (len == 0) { 1232 if (len == 0) {
1257prepare_to_die: 1233prepare_to_die:
1258 printf("exit"); 1234 printf("exit");
1259 clean_up_and_die(0); 1235 goto_new_line();
1236 /* cmdedit_reset_term() called in atexit */
1237 exit(EXIT_SUCCESS);
1260 } else { 1238 } else {
1261 input_delete(); 1239 input_delete();
1262 } 1240 }
@@ -1307,12 +1285,12 @@ prepare_to_die:
1307 1285
1308 case ESC:{ 1286 case ESC:{
1309 /* escape sequence follows */ 1287 /* escape sequence follows */
1310 if (read(0, &c, 1) < 1) 1288 if (safe_read(0, &c, 1) < 1)
1311 return; 1289 goto prepare_to_die;
1312 /* different vt100 emulations */ 1290 /* different vt100 emulations */
1313 if (c == '[' || c == 'O') { 1291 if (c == '[' || c == 'O') {
1314 if (read(0, &c, 1) < 1) 1292 if (safe_read(0, &c, 1) < 1)
1315 return; 1293 goto prepare_to_die;
1316 } 1294 }
1317 switch (c) { 1295 switch (c) {
1318#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION 1296#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION
@@ -1376,8 +1354,8 @@ prepare_to_die:
1376 } 1354 }
1377 if (c >= '1' && c <= '9') 1355 if (c >= '1' && c <= '9')
1378 do 1356 do
1379 if (read(0, &c, 1) < 1) 1357 if (safe_read(0, &c, 1) < 1)
1380 return; 1358 goto prepare_to_die;
1381 while (c != '~'); 1359 while (c != '~');
1382 break; 1360 break;
1383 } 1361 }
@@ -1386,8 +1364,8 @@ prepare_to_die:
1386#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT 1364#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT
1387 /* Control-V -- Add non-printable symbol */ 1365 /* Control-V -- Add non-printable symbol */
1388 if (c == 22) { 1366 if (c == 22) {
1389 if (read(0, &c, 1) < 1) 1367 if (safe_read(0, &c, 1) < 1)
1390 return; 1368 goto prepare_to_die;
1391 if (c == 0) { 1369 if (c == 0) {
1392 beep(); 1370 beep();
1393 break; 1371 break;
@@ -1485,23 +1463,10 @@ prepare_to_die:
1485#if defined(BB_FEATURE_SH_FANCY_PROMPT) 1463#if defined(BB_FEATURE_SH_FANCY_PROMPT)
1486 free(cmdedit_prompt); 1464 free(cmdedit_prompt);
1487#endif 1465#endif
1488 return; 1466 cmdedit_reset_term();
1489} 1467}
1490 1468
1491 1469
1492/* Undo the effects of cmdedit_init(). */
1493extern void cmdedit_terminate(void)
1494{
1495 cmdedit_reset_term();
1496 if ((handlers_sets & SET_TERM_HANDLERS) != 0) {
1497 signal(SIGKILL, SIG_DFL);
1498 signal(SIGINT, SIG_DFL);
1499 signal(SIGQUIT, SIG_DFL);
1500 signal(SIGTERM, SIG_DFL);
1501 signal(SIGWINCH, SIG_DFL);
1502 handlers_sets &= ~SET_TERM_HANDLERS;
1503 }
1504}
1505 1470
1506#endif /* BB_FEATURE_COMMAND_EDITING */ 1471#endif /* BB_FEATURE_COMMAND_EDITING */
1507 1472
@@ -1515,8 +1480,6 @@ const char *memory_exhausted = "Memory exhausted";
1515#include <locale.h> 1480#include <locale.h>
1516#endif 1481#endif
1517 1482
1518unsigned int shell_context;
1519
1520int main(int argc, char **argv) 1483int main(int argc, char **argv)
1521{ 1484{
1522 char buff[BUFSIZ]; 1485 char buff[BUFSIZ];
@@ -1532,15 +1495,16 @@ int main(int argc, char **argv)
1532#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT 1495#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT
1533 setlocale(LC_ALL, ""); 1496 setlocale(LC_ALL, "");
1534#endif 1497#endif
1535 shell_context = 1; 1498 while(1) {
1536 do {
1537 int l; 1499 int l;
1538 cmdedit_read_input(prompt, buff); 1500 cmdedit_read_input(prompt, buff);
1539 l = strlen(buff); 1501 l = strlen(buff);
1502 if(l==0)
1503 break;
1540 if(l > 0 && buff[l-1] == '\n') 1504 if(l > 0 && buff[l-1] == '\n')
1541 buff[l-1] = 0; 1505 buff[l-1] = 0;
1542 printf("*** cmdedit_read_input() returned line =%s=\n", buff); 1506 printf("*** cmdedit_read_input() returned line =%s=\n", buff);
1543 } while (shell_context); 1507 }
1544 printf("*** cmdedit_read_input() detect ^C\n"); 1508 printf("*** cmdedit_read_input() detect ^C\n");
1545 return 0; 1509 return 0;
1546} 1510}
diff --git a/cmdedit.h b/cmdedit.h
index 9e3e44b36..1482da3b8 100644
--- a/cmdedit.h
+++ b/cmdedit.h
@@ -1,8 +1,6 @@
1#ifndef CMDEDIT_H 1#ifndef CMDEDIT_H
2#define CMDEDIT_H 2#define CMDEDIT_H
3 3
4void cmdedit_init(void);
5void cmdedit_terminate(void);
6void cmdedit_read_input(char* promptStr, char* command); /* read a line of input */ 4void cmdedit_read_input(char* promptStr, char* command); /* read a line of input */
7 5
8#endif /* CMDEDIT_H */ 6#endif /* CMDEDIT_H */
diff --git a/coreutils/md5sum.c b/coreutils/md5sum.c
index 72bc08624..bb4d115ca 100644
--- a/coreutils/md5sum.c
+++ b/coreutils/md5sum.c
@@ -770,12 +770,10 @@ static int md5_file(const char *filename,
770 have_read_stdin = 1; 770 have_read_stdin = 1;
771 fp = stdin; 771 fp = stdin;
772 } else { 772 } else {
773 fp = fopen(filename, "r"); 773 fp = wfopen(filename, "r");
774 if (fp == NULL) { 774 if (fp == NULL)
775 perror_msg("%s", filename);
776 return FALSE; 775 return FALSE;
777 } 776 }
778 }
779 777
780 if (md5_stream(fp, md5_result)) { 778 if (md5_stream(fp, md5_result)) {
781 perror_msg("%s", filename); 779 perror_msg("%s", filename);
@@ -807,12 +805,10 @@ static int md5_check(const char *checkfile_name)
807 have_read_stdin = 1; 805 have_read_stdin = 1;
808 checkfile_stream = stdin; 806 checkfile_stream = stdin;
809 } else { 807 } else {
810 checkfile_stream = fopen(checkfile_name, "r"); 808 checkfile_stream = wfopen(checkfile_name, "r");
811 if (checkfile_stream == NULL) { 809 if (checkfile_stream == NULL)
812 perror_msg("%s", checkfile_name);
813 return FALSE; 810 return FALSE;
814 } 811 }
815 }
816 812
817 line_number = 0; 813 line_number = 0;
818 814
diff --git a/coreutils/stty.c b/coreutils/stty.c
index 1e1343370..2e00a496d 100644
--- a/coreutils/stty.c
+++ b/coreutils/stty.c
@@ -24,7 +24,7 @@
24 24
25 David MacKenzie <djm@gnu.ai.mit.edu> 25 David MacKenzie <djm@gnu.ai.mit.edu>
26 26
27 Special for busybox ported by Vladimir Oleynik <vodz@usa.net> 2001 27 Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001
28 28
29 */ 29 */
30 30
diff --git a/hush.c b/hush.c
index b74b9d159..134404251 100644
--- a/hush.c
+++ b/hush.c
@@ -237,10 +237,6 @@ unsigned int global_argc;
237unsigned int last_return_code; 237unsigned int last_return_code;
238extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */ 238extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
239 239
240/* Variables we export */
241unsigned int shell_context; /* Used in cmdedit.c to reset the
242 * context when someone hits ^C */
243
244/* "globals" within this file */ 240/* "globals" within this file */
245static char *ifs; 241static char *ifs;
246static char map[256]; 242static char map[256];
@@ -883,7 +879,6 @@ static void get_user_input(struct in_str *i)
883 ** child processes (rob@sysgo.de) 879 ** child processes (rob@sysgo.de)
884 */ 880 */
885 cmdedit_read_input(prompt_str, the_command); 881 cmdedit_read_input(prompt_str, the_command);
886 cmdedit_terminate();
887#else 882#else
888 fputs(prompt_str, stdout); 883 fputs(prompt_str, stdout);
889 fflush(stdout); 884 fflush(stdout);
@@ -1411,6 +1406,7 @@ static int run_pipe_real(struct pipe *pi)
1411 /* Set the handling for job control signals back to the default. */ 1406 /* Set the handling for job control signals back to the default. */
1412 signal(SIGINT, SIG_DFL); 1407 signal(SIGINT, SIG_DFL);
1413 signal(SIGQUIT, SIG_DFL); 1408 signal(SIGQUIT, SIG_DFL);
1409 signal(SIGTERM, SIG_DFL);
1414 signal(SIGTSTP, SIG_DFL); 1410 signal(SIGTSTP, SIG_DFL);
1415 signal(SIGTTIN, SIG_DFL); 1411 signal(SIGTTIN, SIG_DFL);
1416 signal(SIGTTOU, SIG_DFL); 1412 signal(SIGTTOU, SIG_DFL);
@@ -2551,6 +2547,7 @@ static void setup_job_control()
2551 /* Ignore interactive and job-control signals. */ 2547 /* Ignore interactive and job-control signals. */
2552 signal(SIGINT, SIG_IGN); 2548 signal(SIGINT, SIG_IGN);
2553 signal(SIGQUIT, SIG_IGN); 2549 signal(SIGQUIT, SIG_IGN);
2550 signal(SIGTERM, SIG_IGN);
2554 signal(SIGTSTP, SIG_IGN); 2551 signal(SIGTSTP, SIG_IGN);
2555 signal(SIGTTIN, SIG_IGN); 2552 signal(SIGTTIN, SIG_IGN);
2556 signal(SIGTTOU, SIG_IGN); 2553 signal(SIGTTOU, SIG_IGN);
diff --git a/include/libbb.h b/include/libbb.h
index 224c561d5..e3d713321 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -252,6 +252,7 @@ extern void gz_close(int gunzip_pid);
252extern FILE *gz_open(FILE *compressed_file, int *pid); 252extern FILE *gz_open(FILE *compressed_file, int *pid);
253 253
254extern struct hostent *xgethostbyname(const char *name); 254extern struct hostent *xgethostbyname(const char *name);
255extern int create_icmp_socket(void);
255 256
256char *dirname (const char *path); 257char *dirname (const char *path);
257 258
@@ -284,5 +285,6 @@ extern const char * const write_error;
284extern const char * const too_few_args; 285extern const char * const too_few_args;
285extern const char * const name_longer_than_foo; 286extern const char * const name_longer_than_foo;
286extern const char * const unknown; 287extern const char * const unknown;
288extern const char * const can_not_create_raw_socket;
287 289
288#endif /* __LIBBB_H__ */ 290#endif /* __LIBBB_H__ */
diff --git a/lash.c b/lash.c
index 7c932a910..8f8609534 100644
--- a/lash.c
+++ b/lash.c
@@ -170,9 +170,7 @@ static struct built_in_command bltins_forking[] = {
170}; 170};
171 171
172 172
173/* Variables we export */ 173static int shell_context; /* Type prompt trigger (PS1 or PS2) */
174unsigned int shell_context; /* Used in cmdedit.c to reset the
175 context when someone hits ^C */
176 174
177 175
178/* Globals that are static to this file */ 176/* Globals that are static to this file */
@@ -716,7 +714,6 @@ static int get_command(FILE * source, char *command)
716 ** child processes (rob@sysgo.de) 714 ** child processes (rob@sysgo.de)
717 */ 715 */
718 cmdedit_read_input(prompt_str, command); 716 cmdedit_read_input(prompt_str, command);
719 cmdedit_terminate();
720 return 0; 717 return 0;
721#else 718#else
722 fputs(prompt_str, stdout); 719 fputs(prompt_str, stdout);
@@ -1557,7 +1554,6 @@ int shell_main(int argc_l, char **argv_l)
1557 1554
1558 /* These variables need re-initializing when recursing */ 1555 /* These variables need re-initializing when recursing */
1559 last_jobid = 0; 1556 last_jobid = 0;
1560 shell_context = 0;
1561 local_pending_command = NULL; 1557 local_pending_command = NULL;
1562 close_me_head = NULL; 1558 close_me_head = NULL;
1563 job_list.head = NULL; 1559 job_list.head = NULL;
diff --git a/libbb/create_icmp_socket.c b/libbb/create_icmp_socket.c
new file mode 100644
index 000000000..d804b3987
--- /dev/null
+++ b/libbb/create_icmp_socket.c
@@ -0,0 +1,37 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
5 * create raw socket for icmp protocol test permision
6 * and drop root privilegies if running setuid
7 *
8 */
9
10#include <sys/types.h>
11#include <netdb.h>
12#include <sys/socket.h>
13#include <errno.h>
14#include <unistd.h>
15#include "libbb.h"
16
17int create_icmp_socket(void)
18{
19 struct protoent *proto;
20 int sock;
21
22 proto = getprotobyname("icmp");
23 /* if getprotobyname failed, just silently force
24 * proto->p_proto to have the correct value for "icmp" */
25 if ((sock = socket(AF_INET, SOCK_RAW,
26 (proto ? proto->p_proto : 1))) < 0) { /* 1 == ICMP */
27 if (errno == EPERM)
28 error_msg_and_die("permission denied. (are you root?)");
29 else
30 perror_msg_and_die(can_not_create_raw_socket);
31 }
32
33 /* drop root privs if running setuid */
34 setuid(getuid());
35
36 return sock;
37}
diff --git a/libbb/libbb.h b/libbb/libbb.h
index 224c561d5..e3d713321 100644
--- a/libbb/libbb.h
+++ b/libbb/libbb.h
@@ -252,6 +252,7 @@ extern void gz_close(int gunzip_pid);
252extern FILE *gz_open(FILE *compressed_file, int *pid); 252extern FILE *gz_open(FILE *compressed_file, int *pid);
253 253
254extern struct hostent *xgethostbyname(const char *name); 254extern struct hostent *xgethostbyname(const char *name);
255extern int create_icmp_socket(void);
255 256
256char *dirname (const char *path); 257char *dirname (const char *path);
257 258
@@ -284,5 +285,6 @@ extern const char * const write_error;
284extern const char * const too_few_args; 285extern const char * const too_few_args;
285extern const char * const name_longer_than_foo; 286extern const char * const name_longer_than_foo;
286extern const char * const unknown; 287extern const char * const unknown;
288extern const char * const can_not_create_raw_socket;
287 289
288#endif /* __LIBBB_H__ */ 290#endif /* __LIBBB_H__ */
diff --git a/libbb/messages.c b/libbb/messages.c
index 910cb8fa2..552c3ab5b 100644
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -62,3 +62,6 @@
62 const char * const unknown = "(unknown)"; 62 const char * const unknown = "(unknown)";
63#endif 63#endif
64 64
65#ifdef L_can_not_create_raw_socket
66 const char * const can_not_create_raw_socket = "can`t create raw socket";
67#endif
diff --git a/md5sum.c b/md5sum.c
index 72bc08624..bb4d115ca 100644
--- a/md5sum.c
+++ b/md5sum.c
@@ -770,12 +770,10 @@ static int md5_file(const char *filename,
770 have_read_stdin = 1; 770 have_read_stdin = 1;
771 fp = stdin; 771 fp = stdin;
772 } else { 772 } else {
773 fp = fopen(filename, "r"); 773 fp = wfopen(filename, "r");
774 if (fp == NULL) { 774 if (fp == NULL)
775 perror_msg("%s", filename);
776 return FALSE; 775 return FALSE;
777 } 776 }
778 }
779 777
780 if (md5_stream(fp, md5_result)) { 778 if (md5_stream(fp, md5_result)) {
781 perror_msg("%s", filename); 779 perror_msg("%s", filename);
@@ -807,12 +805,10 @@ static int md5_check(const char *checkfile_name)
807 have_read_stdin = 1; 805 have_read_stdin = 1;
808 checkfile_stream = stdin; 806 checkfile_stream = stdin;
809 } else { 807 } else {
810 checkfile_stream = fopen(checkfile_name, "r"); 808 checkfile_stream = wfopen(checkfile_name, "r");
811 if (checkfile_stream == NULL) { 809 if (checkfile_stream == NULL)
812 perror_msg("%s", checkfile_name);
813 return FALSE; 810 return FALSE;
814 } 811 }
815 }
816 812
817 line_number = 0; 813 line_number = 0;
818 814
diff --git a/msh.c b/msh.c
index 230d74f5a..8f046e794 100644
--- a/msh.c
+++ b/msh.c
@@ -682,8 +682,7 @@ static void * brkaddr;
682 682
683 683
684#ifdef BB_FEATURE_COMMAND_EDITING 684#ifdef BB_FEATURE_COMMAND_EDITING
685char * current_prompt; 685static char * current_prompt;
686unsigned int shell_context;
687#endif 686#endif
688 687
689 688
@@ -4449,9 +4448,7 @@ register struct ioarg *ap;
4449 if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) { 4448 if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
4450 if (i) 4449 if (i)
4451 lseek(ap->afile, ap->afpos, 0); 4450 lseek(ap->afile, ap->afpos, 0);
4452 do { 4451 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
4453 i = read(ap->afile, bp->buf, sizeof(bp->buf));
4454 } while (i < 0 && errno == EINTR);
4455 if (i <= 0) { 4452 if (i <= 0) {
4456 closef(ap->afile); 4453 closef(ap->afile);
4457 return 0; 4454 return 0;
@@ -4470,7 +4467,6 @@ register struct ioarg *ap;
4470 4467
4471 while (size == 0 || position >= size) { 4468 while (size == 0 || position >= size) {
4472 cmdedit_read_input(current_prompt, mycommand); 4469 cmdedit_read_input(current_prompt, mycommand);
4473 cmdedit_terminate();
4474 size = strlen(mycommand); 4470 size = strlen(mycommand);
4475 position = 0; 4471 position = 0;
4476 } 4472 }
@@ -4480,9 +4476,7 @@ register struct ioarg *ap;
4480 } else 4476 } else
4481#endif 4477#endif
4482 { 4478 {
4483 do { 4479 i = safe_read(ap->afile, &c, sizeof(c));
4484 i = read(ap->afile, &c, sizeof(c));
4485 } while (i < 0 && errno == EINTR);
4486 return(i == sizeof(c)? c&0177: (closef(ap->afile), 0)); 4480 return(i == sizeof(c)? c&0177: (closef(ap->afile), 0));
4487 } 4481 }
4488} 4482}
diff --git a/networking/ping.c b/networking/ping.c
index e4307d2de..205133d8c 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -1,6 +1,6 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * $Id: ping.c,v 1.43 2001/05/21 20:30:51 andersen Exp $ 3 * $Id: ping.c,v 1.44 2001/07/12 20:26:31 andersen Exp $
4 * Mini ping implementation for busybox 4 * Mini ping implementation for busybox
5 * 5 *
6 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> 6 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -191,11 +191,7 @@ static void ping(const char *host)
191 int pingsock, c; 191 int pingsock, c;
192 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; 192 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
193 193
194 if ((pingsock = socket(AF_INET, SOCK_RAW, 1)) < 0) /* 1 == ICMP */ 194 pingsock = create_raw_socket();
195 perror_msg_and_die("creating a raw socket");
196
197 /* drop root privs if running setuid */
198 setuid(getuid());
199 195
200 memset(&pingaddr, 0, sizeof(struct sockaddr_in)); 196 memset(&pingaddr, 0, sizeof(struct sockaddr_in));
201 197
@@ -434,7 +430,7 @@ static void ping(const char *host)
434 if (errno == EPERM) 430 if (errno == EPERM)
435 error_msg_and_die("permission denied. (are you root?)"); 431 error_msg_and_die("permission denied. (are you root?)");
436 else 432 else
437 perror_msg_and_die("creating a raw socket"); 433 perror_msg_and_die(can_not_create_raw_socket);
438 } 434 }
439 435
440 /* drop root privs if running setuid */ 436 /* drop root privs if running setuid */
diff --git a/networking/traceroute.c b/networking/traceroute.c
index a02be8a9e..106cf043b 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -5,6 +5,7 @@
5 * This code is derived from software contributed to Berkeley by 5 * This code is derived from software contributed to Berkeley by
6 * Van Jacobson. 6 * Van Jacobson.
7 * 7 *
8 * Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001
8 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
10 * are met: 11 * are met:
@@ -61,6 +62,10 @@
61 * Tue Dec 20 03:50:13 PST 1988 62 * Tue Dec 20 03:50:13 PST 1988
62 */ 63 */
63 64
65#undef BB_FEATURE_TRACEROUTE_VERBOSE
66//#define BB_FEATURE_TRACEROUTE_VERBOSE
67#undef BB_FEATURE_TRACEROUTE_SO_DEBUG /* not in documentation man */
68
64#include <stdio.h> 69#include <stdio.h>
65#include <errno.h> 70#include <errno.h>
66#include <stdlib.h> 71#include <stdlib.h>
@@ -100,13 +105,6 @@ struct opacket {
100 105
101#include "busybox.h" 106#include "busybox.h"
102 107
103static int wait_for_reply (int, struct sockaddr_in *, int);
104static void send_probe (int, int);
105static double deltaT (struct timeval *, struct timeval *);
106static int packet_ok (u_char *, int, struct sockaddr_in *, int);
107static void print (u_char *, int, struct sockaddr_in *);
108static char *inetname (struct in_addr);
109
110static u_char packet[512]; /* last inbound (icmp) packet */ 108static u_char packet[512]; /* last inbound (icmp) packet */
111static struct opacket *outpacket; /* last output (udp) packet */ 109static struct opacket *outpacket; /* last output (udp) packet */
112 110
@@ -122,10 +120,229 @@ static int max_ttl = 30;
122static u_short ident; 120static u_short ident;
123static u_short port = 32768+666; /* start udp dest port # for probe packets */ 121static u_short port = 32768+666; /* start udp dest port # for probe packets */
124 122
123#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
125static int verbose; 124static int verbose;
125#endif
126static int waittime = 5; /* time to wait for response (in seconds) */ 126static int waittime = 5; /* time to wait for response (in seconds) */
127static int nflag; /* print addresses numerically */ 127static int nflag; /* print addresses numerically */
128 128
129/*
130 * Construct an Internet address representation.
131 * If the nflag has been supplied, give
132 * numeric value, otherwise try for symbolic name.
133 */
134static inline char *
135inetname(struct in_addr in)
136{
137 char *cp;
138 static char line[50];
139 struct hostent *hp;
140 static char domain[MAXHOSTNAMELEN + 1];
141 static int first = 1;
142
143 if (first && !nflag) {
144 first = 0;
145 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
146 (cp = index(domain, '.')))
147 (void) strcpy(domain, cp + 1);
148 else
149 domain[0] = 0;
150 }
151 cp = 0;
152 if (!nflag && in.s_addr != INADDR_ANY) {
153 hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
154 if (hp) {
155 if ((cp = index(hp->h_name, '.')) &&
156 !strcmp(cp + 1, domain))
157 *cp = 0;
158 cp = (char *)hp->h_name;
159 }
160 }
161 if (cp)
162 (void) strcpy(line, cp);
163 else {
164 in.s_addr = ntohl(in.s_addr);
165 strcpy(line, inet_ntoa(in));
166 }
167 return (line);
168}
169
170static inline void
171print(u_char *buf, int cc, struct sockaddr_in *from)
172{
173 struct ip *ip;
174 int hlen;
175
176 ip = (struct ip *) buf;
177 hlen = ip->ip_hl << 2;
178 cc -= hlen;
179
180 if (nflag)
181 printf(" %s", inet_ntoa(from->sin_addr));
182 else
183 printf(" %s (%s)", inetname(from->sin_addr),
184 inet_ntoa(from->sin_addr));
185
186#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
187 if (verbose)
188 printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
189#endif
190}
191
192static inline double
193deltaT(struct timeval *t1p, struct timeval *t2p)
194{
195 double dt;
196
197 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
198 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
199 return (dt);
200}
201
202static inline int
203wait_for_reply(int sock, struct sockaddr_in *from, int reset_timer)
204{
205 fd_set fds;
206 static struct timeval wait;
207 int cc = 0;
208 int fromlen = sizeof (*from);
209
210 FD_ZERO(&fds);
211 FD_SET(sock, &fds);
212 if (reset_timer) {
213 /*
214 * traceroute could hang if someone else has a ping
215 * running and our ICMP reply gets dropped but we don't
216 * realize it because we keep waking up to handle those
217 * other ICMP packets that keep coming in. To fix this,
218 * "reset_timer" will only be true if the last packet that
219 * came in was for us or if this is the first time we're
220 * waiting for a reply since sending out a probe. Note
221 * that this takes advantage of the select() feature on
222 * Linux where the remaining timeout is written to the
223 * struct timeval area.
224 */
225 wait.tv_sec = waittime;
226 wait.tv_usec = 0;
227 }
228
229 if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
230 cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
231 (struct sockaddr *)from, &fromlen);
232
233 return(cc);
234}
235
236#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
237/*
238 * Convert an ICMP "type" field to a printable string.
239 */
240static inline const char *
241pr_type(t)
242 u_char t;
243{
244 static const char * const ttab[] = {
245 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
246 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
247 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
248 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
249 "Info Reply"
250 };
251
252 if(t > 16)
253 return("OUT-OF-RANGE");
254
255 return(ttab[t]);
256}
257#endif
258
259static inline int
260packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq)
261{
262 struct icmp *icp;
263 u_char type, code;
264 int hlen;
265 struct ip *ip;
266
267 ip = (struct ip *) buf;
268 hlen = ip->ip_hl << 2;
269 if (cc < hlen + ICMP_MINLEN) {
270#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
271 if (verbose)
272 printf("packet too short (%d bytes) from %s\n", cc,
273 inet_ntoa(from->sin_addr));
274#endif
275 return (0);
276 }
277 cc -= hlen;
278 icp = (struct icmp *)(buf + hlen);
279 type = icp->icmp_type; code = icp->icmp_code;
280 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
281 type == ICMP_UNREACH) {
282 struct ip *hip;
283 struct udphdr *up;
284
285 hip = &icp->icmp_ip;
286 hlen = hip->ip_hl << 2;
287 up = (struct udphdr *)((u_char *)hip + hlen);
288 if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
289 up->source == htons(ident) &&
290 up->dest == htons(port+seq))
291 return (type == ICMP_TIMXCEED? -1 : code+1);
292 }
293#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
294 if (verbose) {
295 int i;
296 u_long *lp = (u_long *)&icp->icmp_ip;
297
298 printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
299 cc, inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst),
300 type, pr_type(type), icp->icmp_code);
301 for (i = 4; i < cc ; i += sizeof(long))
302 printf("%2d: x%8.8lx\n", i, *lp++);
303 }
304#endif
305 return(0);
306}
307
308static void /* not inline */
309send_probe(int seq, int ttl)
310{
311 struct opacket *op = outpacket;
312 struct ip *ip = &op->ip;
313 struct udphdr *up = &op->udp;
314 int i;
315 struct timezone tz;
316
317 ip->ip_off = 0;
318 ip->ip_hl = sizeof(*ip) >> 2;
319 ip->ip_p = IPPROTO_UDP;
320 ip->ip_len = datalen;
321 ip->ip_ttl = ttl;
322 ip->ip_v = IPVERSION;
323 ip->ip_id = htons(ident+seq);
324
325 up->source = htons(ident);
326 up->dest = htons(port+seq);
327 up->len = htons((u_short)(datalen - sizeof(struct ip)));
328 up->check = 0;
329
330 op->seq = seq;
331 op->ttl = ttl;
332 (void) gettimeofday(&op->tv, &tz);
333
334 i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,
335 sizeof(struct sockaddr));
336 if (i < 0 || i != datalen) {
337 if (i<0)
338 perror("sendto");
339 printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
340 datalen, i);
341 (void) fflush(stdout);
342 }
343}
344
345
129int 346int
130#ifndef BB_TRACEROUTE 347#ifndef BB_TRACEROUTE
131main(argc, argv) 348main(argc, argv)
@@ -138,7 +355,6 @@ traceroute_main(argc, argv)
138 extern char *optarg; 355 extern char *optarg;
139 extern int optind; 356 extern int optind;
140 struct hostent *hp; 357 struct hostent *hp;
141 struct protoent *pe;
142 struct sockaddr_in from, *to; 358 struct sockaddr_in from, *to;
143 int ch, i, on, probe, seq, tos, ttl; 359 int ch, i, on, probe, seq, tos, ttl;
144 360
@@ -152,7 +368,9 @@ traceroute_main(argc, argv)
152 while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) 368 while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF)
153 switch(ch) { 369 switch(ch) {
154 case 'd': 370 case 'd':
371#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG
155 options |= SO_DEBUG; 372 options |= SO_DEBUG;
373#endif
156 break; 374 break;
157 case 'm': 375 case 'm':
158 max_ttl = atoi(optarg); 376 max_ttl = atoi(optarg);
@@ -188,7 +406,9 @@ traceroute_main(argc, argv)
188 error_msg_and_die("tos must be 0 to 255."); 406 error_msg_and_die("tos must be 0 to 255.");
189 break; 407 break;
190 case 'v': 408 case 'v':
409#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
191 verbose++; 410 verbose++;
411#endif
192 break; 412 break;
193 case 'w': 413 case 'w':
194 waittime = atoi(optarg); 414 waittime = atoi(optarg);
@@ -206,21 +426,11 @@ traceroute_main(argc, argv)
206 426
207 setlinebuf (stdout); 427 setlinebuf (stdout);
208 428
209 (void) bzero((char *)&whereto, sizeof(struct sockaddr)); 429 memset(&whereto, 0, sizeof(struct sockaddr));
210 to->sin_family = AF_INET; 430 hp = xgethostbyname(*argv);
211 to->sin_addr.s_addr = inet_addr(*argv);
212 if (to->sin_addr.s_addr != -1)
213 hostname = *argv;
214 else {
215 hp = gethostbyname(*argv);
216 if (hp) {
217 to->sin_family = hp->h_addrtype; 431 to->sin_family = hp->h_addrtype;
218 bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length); 432 memcpy(&to->sin_addr, hp->h_addr, hp->h_length);
219 hostname = (char *)hp->h_name; 433 hostname = (char *)hp->h_name;
220 } else {
221 error_msg_and_die("unknown host %s", *argv);
222 }
223 }
224 if (*++argv) 434 if (*++argv)
225 datalen = atoi(*argv); 435 datalen = atoi(*argv);
226 if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) 436 if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket))
@@ -228,7 +438,7 @@ traceroute_main(argc, argv)
228 MAXPACKET - sizeof(struct opacket)); 438 MAXPACKET - sizeof(struct opacket));
229 datalen += sizeof(struct opacket); 439 datalen += sizeof(struct opacket);
230 outpacket = (struct opacket *)xmalloc((unsigned)datalen); 440 outpacket = (struct opacket *)xmalloc((unsigned)datalen);
231 (void) bzero((char *)outpacket, datalen); 441 memset(outpacket, 0, datalen);
232 outpacket->ip.ip_dst = to->sin_addr; 442 outpacket->ip.ip_dst = to->sin_addr;
233 outpacket->ip.ip_tos = tos; 443 outpacket->ip.ip_tos = tos;
234 outpacket->ip.ip_v = IPVERSION; 444 outpacket->ip.ip_v = IPVERSION;
@@ -236,19 +446,19 @@ traceroute_main(argc, argv)
236 446
237 ident = (getpid() & 0xffff) | 0x8000; 447 ident = (getpid() & 0xffff) | 0x8000;
238 448
239 if ((pe = getprotobyname("icmp")) == NULL) 449 if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
240 error_msg_and_die("icmp: unknown protocol"); 450 perror_msg_and_die(can_not_create_raw_socket);
241 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) 451
242 perror_msg_and_die("icmp socket"); 452 s = create_icmp_socket();
453
454#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG
243 if (options & SO_DEBUG) 455 if (options & SO_DEBUG)
244 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 456 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
245 (char *)&on, sizeof(on)); 457 (char *)&on, sizeof(on));
458#endif
246 if (options & SO_DONTROUTE) 459 if (options & SO_DONTROUTE)
247 (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, 460 (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
248 (char *)&on, sizeof(on)); 461 (char *)&on, sizeof(on));
249
250 if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
251 perror_msg_and_die("raw socket");
252#ifdef SO_SNDBUF 462#ifdef SO_SNDBUF
253 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, 463 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
254 sizeof(datalen)) < 0) 464 sizeof(datalen)) < 0)
@@ -259,15 +469,17 @@ traceroute_main(argc, argv)
259 sizeof(on)) < 0) 469 sizeof(on)) < 0)
260 perror_msg_and_die("IP_HDRINCL"); 470 perror_msg_and_die("IP_HDRINCL");
261#endif IP_HDRINCL 471#endif IP_HDRINCL
472#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG
262 if (options & SO_DEBUG) 473 if (options & SO_DEBUG)
263 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 474 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
264 (char *)&on, sizeof(on)); 475 (char *)&on, sizeof(on));
476#endif
265 if (options & SO_DONTROUTE) 477 if (options & SO_DONTROUTE)
266 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 478 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
267 (char *)&on, sizeof(on)); 479 (char *)&on, sizeof(on));
268 480
269 if (source) { 481 if (source) {
270 (void) bzero((char *)&from, sizeof(struct sockaddr)); 482 memset(&from, 0, sizeof(struct sockaddr));
271 from.sin_family = AF_INET; 483 from.sin_family = AF_INET;
272 from.sin_addr.s_addr = inet_addr(source); 484 from.sin_addr.s_addr = inet_addr(source);
273 if (from.sin_addr.s_addr == -1) 485 if (from.sin_addr.s_addr == -1)
@@ -284,7 +496,6 @@ traceroute_main(argc, argv)
284 if (source) 496 if (source)
285 fprintf(stderr, " from %s", source); 497 fprintf(stderr, " from %s", source);
286 fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); 498 fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);
287 (void) fflush(stderr);
288 499
289 for (ttl = 1; ttl <= max_ttl; ++ttl) { 500 for (ttl = 1; ttl <= max_ttl; ++ttl) {
290 u_long lastaddr = 0; 501 u_long lastaddr = 0;
@@ -312,11 +523,9 @@ traceroute_main(argc, argv)
312 printf(" %g ms", deltaT(&t1, &t2)); 523 printf(" %g ms", deltaT(&t1, &t2));
313 switch(i - 1) { 524 switch(i - 1) {
314 case ICMP_UNREACH_PORT: 525 case ICMP_UNREACH_PORT:
315#ifndef ARCHAIC
316 ip = (struct ip *)packet; 526 ip = (struct ip *)packet;
317 if (ip->ip_ttl <= 1) 527 if (ip->ip_ttl <= 1)
318 printf(" !"); 528 printf(" !");
319#endif ARCHAIC
320 ++got_there; 529 ++got_there;
321 break; 530 break;
322 case ICMP_UNREACH_NET: 531 case ICMP_UNREACH_NET:
@@ -355,239 +564,3 @@ traceroute_main(argc, argv)
355 564
356 return 0; 565 return 0;
357} 566}
358
359static int
360wait_for_reply(sock, from, reset_timer)
361 int sock;
362 struct sockaddr_in *from;
363 int reset_timer;
364{
365 fd_set fds;
366 static struct timeval wait;
367 int cc = 0;
368 int fromlen = sizeof (*from);
369
370 FD_ZERO(&fds);
371 FD_SET(sock, &fds);
372 if (reset_timer) {
373 /*
374 * traceroute could hang if someone else has a ping
375 * running and our ICMP reply gets dropped but we don't
376 * realize it because we keep waking up to handle those
377 * other ICMP packets that keep coming in. To fix this,
378 * "reset_timer" will only be true if the last packet that
379 * came in was for us or if this is the first time we're
380 * waiting for a reply since sending out a probe. Note
381 * that this takes advantage of the select() feature on
382 * Linux where the remaining timeout is written to the
383 * struct timeval area.
384 */
385 wait.tv_sec = waittime;
386 wait.tv_usec = 0;
387 }
388
389 if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
390 cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
391 (struct sockaddr *)from, &fromlen);
392
393 return(cc);
394}
395
396
397static void
398send_probe(seq, ttl)
399 int seq, ttl;
400{
401 struct opacket *op = outpacket;
402 struct ip *ip = &op->ip;
403 struct udphdr *up = &op->udp;
404 int i;
405 struct timezone tz;
406
407 ip->ip_off = 0;
408 ip->ip_hl = sizeof(*ip) >> 2;
409 ip->ip_p = IPPROTO_UDP;
410 ip->ip_len = datalen;
411 ip->ip_ttl = ttl;
412 ip->ip_v = IPVERSION;
413 ip->ip_id = htons(ident+seq);
414
415 up->source = htons(ident);
416 up->dest = htons(port+seq);
417 up->len = htons((u_short)(datalen - sizeof(struct ip)));
418 up->check = 0;
419
420 op->seq = seq;
421 op->ttl = ttl;
422 (void) gettimeofday(&op->tv, &tz);
423
424 i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,
425 sizeof(struct sockaddr));
426 if (i < 0 || i != datalen) {
427 if (i<0)
428 perror("sendto");
429 printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
430 datalen, i);
431 (void) fflush(stdout);
432 }
433}
434
435
436static double
437deltaT(t1p, t2p)
438 struct timeval *t1p, *t2p;
439{
440 register double dt;
441
442 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
443 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
444 return (dt);
445}
446
447
448/*
449 * Convert an ICMP "type" field to a printable string.
450 */
451static const char *
452pr_type(t)
453 u_char t;
454{
455 static const char * const ttab[] = {
456 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
457 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
458 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
459 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
460 "Info Reply"
461 };
462
463 if(t > 16)
464 return("OUT-OF-RANGE");
465
466 return(ttab[t]);
467}
468
469
470static int
471packet_ok(buf, cc, from, seq)
472 u_char *buf;
473 int cc;
474 struct sockaddr_in *from;
475 int seq;
476{
477 register struct icmp *icp;
478 u_char type, code;
479 int hlen;
480#ifndef ARCHAIC
481 struct ip *ip;
482
483 ip = (struct ip *) buf;
484 hlen = ip->ip_hl << 2;
485 if (cc < hlen + ICMP_MINLEN) {
486 if (verbose)
487 printf("packet too short (%d bytes) from %s\n", cc,
488 inet_ntoa(from->sin_addr));
489 return (0);
490 }
491 cc -= hlen;
492 icp = (struct icmp *)(buf + hlen);
493#else
494 icp = (struct icmp *)buf;
495#endif ARCHAIC
496 type = icp->icmp_type; code = icp->icmp_code;
497 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
498 type == ICMP_UNREACH) {
499 struct ip *hip;
500 struct udphdr *up;
501
502 hip = &icp->icmp_ip;
503 hlen = hip->ip_hl << 2;
504 up = (struct udphdr *)((u_char *)hip + hlen);
505 if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
506 up->source == htons(ident) &&
507 up->dest == htons(port+seq))
508 return (type == ICMP_TIMXCEED? -1 : code+1);
509 }
510#ifndef ARCHAIC
511 if (verbose) {
512 int i;
513 u_long *lp = (u_long *)&icp->icmp_ip;
514
515 printf("\n%d bytes from %s to %s", cc,
516 inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst));
517 printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
518 icp->icmp_code);
519 for (i = 4; i < cc ; i += sizeof(long))
520 printf("%2d: x%8.8lx\n", i, *lp++);
521 }
522#endif ARCHAIC
523 return(0);
524}
525
526
527static void
528print(buf, cc, from)
529 u_char *buf;
530 int cc;
531 struct sockaddr_in *from;
532{
533 struct ip *ip;
534 int hlen;
535
536 ip = (struct ip *) buf;
537 hlen = ip->ip_hl << 2;
538 cc -= hlen;
539
540 if (nflag)
541 printf(" %s", inet_ntoa(from->sin_addr));
542 else
543 printf(" %s (%s)", inetname(from->sin_addr),
544 inet_ntoa(from->sin_addr));
545
546 if (verbose)
547 printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
548}
549
550
551/*
552 * Construct an Internet address representation.
553 * If the nflag has been supplied, give
554 * numeric value, otherwise try for symbolic name.
555 */
556static char *
557inetname(in)
558 struct in_addr in;
559{
560 register char *cp;
561 static char line[50];
562 struct hostent *hp;
563 static char domain[MAXHOSTNAMELEN + 1];
564 static int first = 1;
565
566 if (first && !nflag) {
567 first = 0;
568 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
569 (cp = index(domain, '.')))
570 (void) strcpy(domain, cp + 1);
571 else
572 domain[0] = 0;
573 }
574 cp = 0;
575 if (!nflag && in.s_addr != INADDR_ANY) {
576 hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
577 if (hp) {
578 if ((cp = index(hp->h_name, '.')) &&
579 !strcmp(cp + 1, domain))
580 *cp = 0;
581 cp = (char *)hp->h_name;
582 }
583 }
584 if (cp)
585 (void) strcpy(line, cp);
586 else {
587 in.s_addr = ntohl(in.s_addr);
588#define C(x) ((x) & 0xff)
589 sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
590 C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
591 }
592 return (line);
593}
diff --git a/ping.c b/ping.c
index e4307d2de..205133d8c 100644
--- a/ping.c
+++ b/ping.c
@@ -1,6 +1,6 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * $Id: ping.c,v 1.43 2001/05/21 20:30:51 andersen Exp $ 3 * $Id: ping.c,v 1.44 2001/07/12 20:26:31 andersen Exp $
4 * Mini ping implementation for busybox 4 * Mini ping implementation for busybox
5 * 5 *
6 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> 6 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
@@ -191,11 +191,7 @@ static void ping(const char *host)
191 int pingsock, c; 191 int pingsock, c;
192 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; 192 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
193 193
194 if ((pingsock = socket(AF_INET, SOCK_RAW, 1)) < 0) /* 1 == ICMP */ 194 pingsock = create_raw_socket();
195 perror_msg_and_die("creating a raw socket");
196
197 /* drop root privs if running setuid */
198 setuid(getuid());
199 195
200 memset(&pingaddr, 0, sizeof(struct sockaddr_in)); 196 memset(&pingaddr, 0, sizeof(struct sockaddr_in));
201 197
@@ -434,7 +430,7 @@ static void ping(const char *host)
434 if (errno == EPERM) 430 if (errno == EPERM)
435 error_msg_and_die("permission denied. (are you root?)"); 431 error_msg_and_die("permission denied. (are you root?)");
436 else 432 else
437 perror_msg_and_die("creating a raw socket"); 433 perror_msg_and_die(can_not_create_raw_socket);
438 } 434 }
439 435
440 /* drop root privs if running setuid */ 436 /* drop root privs if running setuid */
diff --git a/shell/ash.c b/shell/ash.c
index 985507341..334d2fddd 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -26,7 +26,7 @@
26 * package. 26 * package.
27 * 27 *
28 * Modified by Erik Andersen <andersee@debian.org> and 28 * Modified by Erik Andersen <andersee@debian.org> and
29 * Vladimir Oleynik <vodz@usa.net> to be used in busybox 29 * Vladimir Oleynik <dzo@simtreas.ru> to be used in busybox
30 * 30 *
31 * 31 *
32 * Original copyright notice is retained at the end of this file. 32 * Original copyright notice is retained at the end of this file.
@@ -4995,7 +4995,7 @@ err1:
4995 if (--in.nleft < 0) { 4995 if (--in.nleft < 0) {
4996 if (in.fd < 0) 4996 if (in.fd < 0)
4997 break; 4997 break;
4998 while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR); 4998 i = safe_read(in.fd, buf, sizeof buf);
4999 TRACE(("expbackq: read returns %d\n", i)); 4999 TRACE(("expbackq: read returns %d\n", i));
5000 if (i <= 0) 5000 if (i <= 0)
5001 break; 5001 break;
@@ -6091,10 +6091,8 @@ init(void) {
6091 * interactive shell and control is returned to the main command loop. 6091 * interactive shell and control is returned to the main command loop.
6092 */ 6092 */
6093 6093
6094#ifdef ASH_ALIAS
6095/* 1 == check for aliases, 2 == also check for assignments */ 6094/* 1 == check for aliases, 2 == also check for assignments */
6096static int checkalias; 6095static int checkalias; /* also used in no alias mode for check assignments */
6097#endif
6098 6096
6099static void 6097static void
6100reset(void) { 6098reset(void) {
@@ -6117,9 +6115,7 @@ reset(void) {
6117 { 6115 {
6118 tokpushback = 0; 6116 tokpushback = 0;
6119 checkkwd = 0; 6117 checkkwd = 0;
6120#ifdef ASH_ALIAS
6121 checkalias = 0; 6118 checkalias = 0;
6122#endif
6123 } 6119 }
6124 6120
6125 /* from redir.c: */ 6121 /* from redir.c: */
@@ -6137,7 +6133,6 @@ reset(void) {
6137 */ 6133 */
6138 6134
6139#ifdef BB_FEATURE_COMMAND_EDITING 6135#ifdef BB_FEATURE_COMMAND_EDITING
6140unsigned int shell_context;
6141static const char * cmdedit_prompt; 6136static const char * cmdedit_prompt;
6142static inline void putprompt(const char *s) { 6137static inline void putprompt(const char *s) {
6143 cmdedit_prompt = s; 6138 cmdedit_prompt = s;
@@ -6206,23 +6201,18 @@ preadfd(void)
6206retry: 6201retry:
6207#ifdef BB_FEATURE_COMMAND_EDITING 6202#ifdef BB_FEATURE_COMMAND_EDITING
6208 { 6203 {
6209 if (parsefile->fd) 6204 if (!iflag)
6210 nr = read(parsefile->fd, buf, BUFSIZ - 1); 6205 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6211 else { 6206 else {
6212 do {
6213 cmdedit_read_input((char*)cmdedit_prompt, buf); 6207 cmdedit_read_input((char*)cmdedit_prompt, buf);
6214 nr = strlen(buf); 6208 nr = strlen(buf);
6215 } while (nr <=0 || shell_context);
6216 cmdedit_terminate();
6217 } 6209 }
6218 } 6210 }
6219#else 6211#else
6220 nr = read(parsefile->fd, buf, BUFSIZ - 1); 6212 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6221#endif 6213#endif
6222 6214
6223 if (nr < 0) { 6215 if (nr < 0) {
6224 if (errno == EINTR)
6225 goto retry;
6226 if (parsefile->fd == 0 && errno == EWOULDBLOCK) { 6216 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6227 int flags = fcntl(0, F_GETFL, 0); 6217 int flags = fcntl(0, F_GETFL, 0);
6228 if (flags >= 0 && flags & O_NONBLOCK) { 6218 if (flags >= 0 && flags & O_NONBLOCK) {
@@ -9872,9 +9862,7 @@ simplecmd() {
9872 redir = NULL; 9862 redir = NULL;
9873 rpp = &redir; 9863 rpp = &redir;
9874 9864
9875#ifdef ASH_ALIAS
9876 checkalias = 2; 9865 checkalias = 2;
9877#endif
9878 for (;;) { 9866 for (;;) {
9879 switch (readtoken()) { 9867 switch (readtoken()) {
9880 case TWORD: 9868 case TWORD:
@@ -10036,9 +10024,10 @@ peektoken() {
10036static int 10024static int
10037readtoken() { 10025readtoken() {
10038 int t; 10026 int t;
10027
10039#ifdef ASH_ALIAS 10028#ifdef ASH_ALIAS
10040 int savecheckkwd = checkkwd;
10041 int savecheckalias = checkalias; 10029 int savecheckalias = checkalias;
10030 int savecheckkwd = checkkwd;
10042 struct alias *ap; 10031 struct alias *ap;
10043#endif 10032#endif
10044 10033
@@ -10083,13 +10072,14 @@ top:
10083 } 10072 }
10084 } 10073 }
10085 10074
10086#ifdef ASH_ALIAS 10075
10087 if (t != TWORD) { 10076 if (t != TWORD) {
10088 if (t != TREDIR) { 10077 if (t != TREDIR) {
10089 checkalias = 0; 10078 checkalias = 0;
10090 } 10079 }
10091 } else if (checkalias == 2 && isassignment(wordtext)) { 10080 } else if (checkalias == 2 && isassignment(wordtext)) {
10092 lasttoken = t = TASSIGN; 10081 lasttoken = t = TASSIGN;
10082#ifdef ASH_ALIAS
10093 } else if (checkalias) { 10083 } else if (checkalias) {
10094 if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) { 10084 if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) {
10095 if (*ap->val) { 10085 if (*ap->val) {
@@ -10099,8 +10089,8 @@ top:
10099 goto top; 10089 goto top;
10100 } 10090 }
10101 checkalias = 0; 10091 checkalias = 0;
10102 }
10103#endif 10092#endif
10093 }
10104out: 10094out:
10105#ifdef DEBUG 10095#ifdef DEBUG
10106 if (!alreadyseen) 10096 if (!alreadyseen)
@@ -12927,7 +12917,7 @@ findvar(struct var **vpp, const char *name)
12927/* 12917/*
12928 * Copyright (c) 1999 Herbert Xu <herbert@debian.org> 12918 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12929 * This file contains code for the times builtin. 12919 * This file contains code for the times builtin.
12930 * $Id: ash.c,v 1.9 2001/07/10 16:57:09 andersen Exp $ 12920 * $Id: ash.c,v 1.10 2001/07/12 20:26:31 andersen Exp $
12931 */ 12921 */
12932static int timescmd (int argc, char **argv) 12922static int timescmd (int argc, char **argv)
12933{ 12923{
diff --git a/shell/cmdedit.c b/shell/cmdedit.c
index 4f124d647..540eb7ea7 100644
--- a/shell/cmdedit.c
+++ b/shell/cmdedit.c
@@ -3,7 +3,7 @@
3 * Termios command line History and Editting. 3 * Termios command line History and Editting.
4 * 4 *
5 * Copyright (c) 1986-2001 may safely be consumed by a BSD or GPL license. 5 * Copyright (c) 1986-2001 may safely be consumed by a BSD or GPL license.
6 * Written by: Vladimir Oleynik <vodz@usa.net> 6 * Written by: Vladimir Oleynik <dzo@simtreas.ru>
7 * 7 *
8 * Used ideas: 8 * Used ideas:
9 * Adam Rogoyski <rogoyski@cs.utexas.edu> 9 * Adam Rogoyski <rogoyski@cs.utexas.edu>
@@ -123,9 +123,8 @@ volatile int handlers_sets = 0; /* Set next bites: */
123enum { 123enum {
124 SET_ATEXIT = 1, /* when atexit() has been called 124 SET_ATEXIT = 1, /* when atexit() has been called
125 and get euid,uid,gid to fast compare */ 125 and get euid,uid,gid to fast compare */
126 SET_TERM_HANDLERS = 2, /* set many terminates signal handlers */ 126 SET_WCHG_HANDLERS = 2, /* winchg signal handler */
127 SET_WCHG_HANDLERS = 4, /* winchg signal handler */ 127 SET_RESET_TERM = 4, /* if the terminal needs to be reset upon exit */
128 SET_RESET_TERM = 8, /* if the terminal needs to be reset upon exit */
129}; 128};
130 129
131 130
@@ -142,10 +141,6 @@ static
142#endif 141#endif
143char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */ 142char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */
144 143
145/* Link into lash to reset context to 0 on ^C and such */
146extern unsigned int shell_context;
147
148
149#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR 144#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR
150static char *user_buf = ""; 145static char *user_buf = "";
151static char *home_pwd_buf = ""; 146static char *home_pwd_buf = "";
@@ -319,6 +314,7 @@ static void put_prompt(void)
319 out1str(cmdedit_prompt); 314 out1str(cmdedit_prompt);
320 cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */ 315 cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */
321 cursor = 0; 316 cursor = 0;
317 cmdedit_y = 0; /* new quasireal y */
322} 318}
323 319
324#ifndef BB_FEATURE_SH_FANCY_PROMPT 320#ifndef BB_FEATURE_SH_FANCY_PROMPT
@@ -456,7 +452,6 @@ static void redraw(int y, int back_cursor)
456{ 452{
457 if (y > 0) /* up to start y */ 453 if (y > 0) /* up to start y */
458 printf("\033[%dA", y); 454 printf("\033[%dA", y);
459 cmdedit_y = 0; /* new quasireal y */
460 putchar('\r'); 455 putchar('\r');
461 put_prompt(); 456 put_prompt();
462 input_end(); /* rewrite */ 457 input_end(); /* rewrite */
@@ -497,14 +492,6 @@ static void input_forward(void)
497} 492}
498 493
499 494
500static void clean_up_and_die(int sig)
501{
502 goto_new_line();
503 if (sig != SIGINT)
504 exit(EXIT_SUCCESS); /* cmdedit_reset_term() called in atexit */
505 cmdedit_reset_term();
506}
507
508static void cmdedit_setwidth(int w, int redraw_flg) 495static void cmdedit_setwidth(int w, int redraw_flg)
509{ 496{
510 cmdedit_termw = cmdedit_prmt_len + 2; 497 cmdedit_termw = cmdedit_prmt_len + 2;
@@ -525,7 +512,7 @@ static void cmdedit_setwidth(int w, int redraw_flg)
525 } 512 }
526} 513}
527 514
528extern void cmdedit_init(void) 515static void cmdedit_init(void)
529{ 516{
530 cmdedit_prmt_len = 0; 517 cmdedit_prmt_len = 0;
531 if ((handlers_sets & SET_WCHG_HANDLERS) == 0) { 518 if ((handlers_sets & SET_WCHG_HANDLERS) == 0) {
@@ -557,14 +544,6 @@ extern void cmdedit_init(void)
557 handlers_sets |= SET_ATEXIT; 544 handlers_sets |= SET_ATEXIT;
558 atexit(cmdedit_reset_term); /* be sure to do this only once */ 545 atexit(cmdedit_reset_term); /* be sure to do this only once */
559 } 546 }
560
561 if ((handlers_sets & SET_TERM_HANDLERS) == 0) {
562 signal(SIGKILL, clean_up_and_die);
563 signal(SIGINT, clean_up_and_die);
564 signal(SIGQUIT, clean_up_and_die);
565 signal(SIGTERM, clean_up_and_die);
566 handlers_sets |= SET_TERM_HANDLERS;
567 }
568} 547}
569 548
570#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION 549#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION
@@ -1220,7 +1199,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ])
1220 1199
1221 fflush(stdout); /* buffered out to fast */ 1200 fflush(stdout); /* buffered out to fast */
1222 1201
1223 if (read(0, &c, 1) < 1) 1202 if (safe_read(0, &c, 1) < 1)
1224 /* if we can't read input then exit */ 1203 /* if we can't read input then exit */
1225 goto prepare_to_die; 1204 goto prepare_to_die;
1226 1205
@@ -1241,22 +1220,21 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ])
1241 break; 1220 break;
1242 case 3: 1221 case 3:
1243 /* Control-c -- stop gathering input */ 1222 /* Control-c -- stop gathering input */
1244
1245 /* Link into lash to reset context to 0 on ^C and such */
1246 shell_context = 0;
1247
1248 /* Go to the next line */
1249 goto_new_line(); 1223 goto_new_line();
1250 command[0] = 0; 1224 command[0] = 0;
1251 1225 len = 0;
1252 return; 1226 lastWasTab = FALSE;
1227 put_prompt();
1228 break;
1253 case 4: 1229 case 4:
1254 /* Control-d -- Delete one character, or exit 1230 /* Control-d -- Delete one character, or exit
1255 * if the len=0 and no chars to delete */ 1231 * if the len=0 and no chars to delete */
1256 if (len == 0) { 1232 if (len == 0) {
1257prepare_to_die: 1233prepare_to_die:
1258 printf("exit"); 1234 printf("exit");
1259 clean_up_and_die(0); 1235 goto_new_line();
1236 /* cmdedit_reset_term() called in atexit */
1237 exit(EXIT_SUCCESS);
1260 } else { 1238 } else {
1261 input_delete(); 1239 input_delete();
1262 } 1240 }
@@ -1307,12 +1285,12 @@ prepare_to_die:
1307 1285
1308 case ESC:{ 1286 case ESC:{
1309 /* escape sequence follows */ 1287 /* escape sequence follows */
1310 if (read(0, &c, 1) < 1) 1288 if (safe_read(0, &c, 1) < 1)
1311 return; 1289 goto prepare_to_die;
1312 /* different vt100 emulations */ 1290 /* different vt100 emulations */
1313 if (c == '[' || c == 'O') { 1291 if (c == '[' || c == 'O') {
1314 if (read(0, &c, 1) < 1) 1292 if (safe_read(0, &c, 1) < 1)
1315 return; 1293 goto prepare_to_die;
1316 } 1294 }
1317 switch (c) { 1295 switch (c) {
1318#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION 1296#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION
@@ -1376,8 +1354,8 @@ prepare_to_die:
1376 } 1354 }
1377 if (c >= '1' && c <= '9') 1355 if (c >= '1' && c <= '9')
1378 do 1356 do
1379 if (read(0, &c, 1) < 1) 1357 if (safe_read(0, &c, 1) < 1)
1380 return; 1358 goto prepare_to_die;
1381 while (c != '~'); 1359 while (c != '~');
1382 break; 1360 break;
1383 } 1361 }
@@ -1386,8 +1364,8 @@ prepare_to_die:
1386#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT 1364#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT
1387 /* Control-V -- Add non-printable symbol */ 1365 /* Control-V -- Add non-printable symbol */
1388 if (c == 22) { 1366 if (c == 22) {
1389 if (read(0, &c, 1) < 1) 1367 if (safe_read(0, &c, 1) < 1)
1390 return; 1368 goto prepare_to_die;
1391 if (c == 0) { 1369 if (c == 0) {
1392 beep(); 1370 beep();
1393 break; 1371 break;
@@ -1485,23 +1463,10 @@ prepare_to_die:
1485#if defined(BB_FEATURE_SH_FANCY_PROMPT) 1463#if defined(BB_FEATURE_SH_FANCY_PROMPT)
1486 free(cmdedit_prompt); 1464 free(cmdedit_prompt);
1487#endif 1465#endif
1488 return; 1466 cmdedit_reset_term();
1489} 1467}
1490 1468
1491 1469
1492/* Undo the effects of cmdedit_init(). */
1493extern void cmdedit_terminate(void)
1494{
1495 cmdedit_reset_term();
1496 if ((handlers_sets & SET_TERM_HANDLERS) != 0) {
1497 signal(SIGKILL, SIG_DFL);
1498 signal(SIGINT, SIG_DFL);
1499 signal(SIGQUIT, SIG_DFL);
1500 signal(SIGTERM, SIG_DFL);
1501 signal(SIGWINCH, SIG_DFL);
1502 handlers_sets &= ~SET_TERM_HANDLERS;
1503 }
1504}
1505 1470
1506#endif /* BB_FEATURE_COMMAND_EDITING */ 1471#endif /* BB_FEATURE_COMMAND_EDITING */
1507 1472
@@ -1515,8 +1480,6 @@ const char *memory_exhausted = "Memory exhausted";
1515#include <locale.h> 1480#include <locale.h>
1516#endif 1481#endif
1517 1482
1518unsigned int shell_context;
1519
1520int main(int argc, char **argv) 1483int main(int argc, char **argv)
1521{ 1484{
1522 char buff[BUFSIZ]; 1485 char buff[BUFSIZ];
@@ -1532,15 +1495,16 @@ int main(int argc, char **argv)
1532#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT 1495#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT
1533 setlocale(LC_ALL, ""); 1496 setlocale(LC_ALL, "");
1534#endif 1497#endif
1535 shell_context = 1; 1498 while(1) {
1536 do {
1537 int l; 1499 int l;
1538 cmdedit_read_input(prompt, buff); 1500 cmdedit_read_input(prompt, buff);
1539 l = strlen(buff); 1501 l = strlen(buff);
1502 if(l==0)
1503 break;
1540 if(l > 0 && buff[l-1] == '\n') 1504 if(l > 0 && buff[l-1] == '\n')
1541 buff[l-1] = 0; 1505 buff[l-1] = 0;
1542 printf("*** cmdedit_read_input() returned line =%s=\n", buff); 1506 printf("*** cmdedit_read_input() returned line =%s=\n", buff);
1543 } while (shell_context); 1507 }
1544 printf("*** cmdedit_read_input() detect ^C\n"); 1508 printf("*** cmdedit_read_input() detect ^C\n");
1545 return 0; 1509 return 0;
1546} 1510}
diff --git a/shell/cmdedit.h b/shell/cmdedit.h
index 9e3e44b36..1482da3b8 100644
--- a/shell/cmdedit.h
+++ b/shell/cmdedit.h
@@ -1,8 +1,6 @@
1#ifndef CMDEDIT_H 1#ifndef CMDEDIT_H
2#define CMDEDIT_H 2#define CMDEDIT_H
3 3
4void cmdedit_init(void);
5void cmdedit_terminate(void);
6void cmdedit_read_input(char* promptStr, char* command); /* read a line of input */ 4void cmdedit_read_input(char* promptStr, char* command); /* read a line of input */
7 5
8#endif /* CMDEDIT_H */ 6#endif /* CMDEDIT_H */
diff --git a/shell/hush.c b/shell/hush.c
index b74b9d159..134404251 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -237,10 +237,6 @@ unsigned int global_argc;
237unsigned int last_return_code; 237unsigned int last_return_code;
238extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */ 238extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
239 239
240/* Variables we export */
241unsigned int shell_context; /* Used in cmdedit.c to reset the
242 * context when someone hits ^C */
243
244/* "globals" within this file */ 240/* "globals" within this file */
245static char *ifs; 241static char *ifs;
246static char map[256]; 242static char map[256];
@@ -883,7 +879,6 @@ static void get_user_input(struct in_str *i)
883 ** child processes (rob@sysgo.de) 879 ** child processes (rob@sysgo.de)
884 */ 880 */
885 cmdedit_read_input(prompt_str, the_command); 881 cmdedit_read_input(prompt_str, the_command);
886 cmdedit_terminate();
887#else 882#else
888 fputs(prompt_str, stdout); 883 fputs(prompt_str, stdout);
889 fflush(stdout); 884 fflush(stdout);
@@ -1411,6 +1406,7 @@ static int run_pipe_real(struct pipe *pi)
1411 /* Set the handling for job control signals back to the default. */ 1406 /* Set the handling for job control signals back to the default. */
1412 signal(SIGINT, SIG_DFL); 1407 signal(SIGINT, SIG_DFL);
1413 signal(SIGQUIT, SIG_DFL); 1408 signal(SIGQUIT, SIG_DFL);
1409 signal(SIGTERM, SIG_DFL);
1414 signal(SIGTSTP, SIG_DFL); 1410 signal(SIGTSTP, SIG_DFL);
1415 signal(SIGTTIN, SIG_DFL); 1411 signal(SIGTTIN, SIG_DFL);
1416 signal(SIGTTOU, SIG_DFL); 1412 signal(SIGTTOU, SIG_DFL);
@@ -2551,6 +2547,7 @@ static void setup_job_control()
2551 /* Ignore interactive and job-control signals. */ 2547 /* Ignore interactive and job-control signals. */
2552 signal(SIGINT, SIG_IGN); 2548 signal(SIGINT, SIG_IGN);
2553 signal(SIGQUIT, SIG_IGN); 2549 signal(SIGQUIT, SIG_IGN);
2550 signal(SIGTERM, SIG_IGN);
2554 signal(SIGTSTP, SIG_IGN); 2551 signal(SIGTSTP, SIG_IGN);
2555 signal(SIGTTIN, SIG_IGN); 2552 signal(SIGTTIN, SIG_IGN);
2556 signal(SIGTTOU, SIG_IGN); 2553 signal(SIGTTOU, SIG_IGN);
diff --git a/shell/lash.c b/shell/lash.c
index 7c932a910..8f8609534 100644
--- a/shell/lash.c
+++ b/shell/lash.c
@@ -170,9 +170,7 @@ static struct built_in_command bltins_forking[] = {
170}; 170};
171 171
172 172
173/* Variables we export */ 173static int shell_context; /* Type prompt trigger (PS1 or PS2) */
174unsigned int shell_context; /* Used in cmdedit.c to reset the
175 context when someone hits ^C */
176 174
177 175
178/* Globals that are static to this file */ 176/* Globals that are static to this file */
@@ -716,7 +714,6 @@ static int get_command(FILE * source, char *command)
716 ** child processes (rob@sysgo.de) 714 ** child processes (rob@sysgo.de)
717 */ 715 */
718 cmdedit_read_input(prompt_str, command); 716 cmdedit_read_input(prompt_str, command);
719 cmdedit_terminate();
720 return 0; 717 return 0;
721#else 718#else
722 fputs(prompt_str, stdout); 719 fputs(prompt_str, stdout);
@@ -1557,7 +1554,6 @@ int shell_main(int argc_l, char **argv_l)
1557 1554
1558 /* These variables need re-initializing when recursing */ 1555 /* These variables need re-initializing when recursing */
1559 last_jobid = 0; 1556 last_jobid = 0;
1560 shell_context = 0;
1561 local_pending_command = NULL; 1557 local_pending_command = NULL;
1562 close_me_head = NULL; 1558 close_me_head = NULL;
1563 job_list.head = NULL; 1559 job_list.head = NULL;
diff --git a/shell/msh.c b/shell/msh.c
index 230d74f5a..8f046e794 100644
--- a/shell/msh.c
+++ b/shell/msh.c
@@ -682,8 +682,7 @@ static void * brkaddr;
682 682
683 683
684#ifdef BB_FEATURE_COMMAND_EDITING 684#ifdef BB_FEATURE_COMMAND_EDITING
685char * current_prompt; 685static char * current_prompt;
686unsigned int shell_context;
687#endif 686#endif
688 687
689 688
@@ -4449,9 +4448,7 @@ register struct ioarg *ap;
4449 if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) { 4448 if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
4450 if (i) 4449 if (i)
4451 lseek(ap->afile, ap->afpos, 0); 4450 lseek(ap->afile, ap->afpos, 0);
4452 do { 4451 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
4453 i = read(ap->afile, bp->buf, sizeof(bp->buf));
4454 } while (i < 0 && errno == EINTR);
4455 if (i <= 0) { 4452 if (i <= 0) {
4456 closef(ap->afile); 4453 closef(ap->afile);
4457 return 0; 4454 return 0;
@@ -4470,7 +4467,6 @@ register struct ioarg *ap;
4470 4467
4471 while (size == 0 || position >= size) { 4468 while (size == 0 || position >= size) {
4472 cmdedit_read_input(current_prompt, mycommand); 4469 cmdedit_read_input(current_prompt, mycommand);
4473 cmdedit_terminate();
4474 size = strlen(mycommand); 4470 size = strlen(mycommand);
4475 position = 0; 4471 position = 0;
4476 } 4472 }
@@ -4480,9 +4476,7 @@ register struct ioarg *ap;
4480 } else 4476 } else
4481#endif 4477#endif
4482 { 4478 {
4483 do { 4479 i = safe_read(ap->afile, &c, sizeof(c));
4484 i = read(ap->afile, &c, sizeof(c));
4485 } while (i < 0 && errno == EINTR);
4486 return(i == sizeof(c)? c&0177: (closef(ap->afile), 0)); 4480 return(i == sizeof(c)? c&0177: (closef(ap->afile), 0));
4487 } 4481 }
4488} 4482}
diff --git a/stty.c b/stty.c
index 1e1343370..2e00a496d 100644
--- a/stty.c
+++ b/stty.c
@@ -24,7 +24,7 @@
24 24
25 David MacKenzie <djm@gnu.ai.mit.edu> 25 David MacKenzie <djm@gnu.ai.mit.edu>
26 26
27 Special for busybox ported by Vladimir Oleynik <vodz@usa.net> 2001 27 Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001
28 28
29 */ 29 */
30 30
diff --git a/traceroute.c b/traceroute.c
index a02be8a9e..106cf043b 100644
--- a/traceroute.c
+++ b/traceroute.c
@@ -5,6 +5,7 @@
5 * This code is derived from software contributed to Berkeley by 5 * This code is derived from software contributed to Berkeley by
6 * Van Jacobson. 6 * Van Jacobson.
7 * 7 *
8 * Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001
8 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
10 * are met: 11 * are met:
@@ -61,6 +62,10 @@
61 * Tue Dec 20 03:50:13 PST 1988 62 * Tue Dec 20 03:50:13 PST 1988
62 */ 63 */
63 64
65#undef BB_FEATURE_TRACEROUTE_VERBOSE
66//#define BB_FEATURE_TRACEROUTE_VERBOSE
67#undef BB_FEATURE_TRACEROUTE_SO_DEBUG /* not in documentation man */
68
64#include <stdio.h> 69#include <stdio.h>
65#include <errno.h> 70#include <errno.h>
66#include <stdlib.h> 71#include <stdlib.h>
@@ -100,13 +105,6 @@ struct opacket {
100 105
101#include "busybox.h" 106#include "busybox.h"
102 107
103static int wait_for_reply (int, struct sockaddr_in *, int);
104static void send_probe (int, int);
105static double deltaT (struct timeval *, struct timeval *);
106static int packet_ok (u_char *, int, struct sockaddr_in *, int);
107static void print (u_char *, int, struct sockaddr_in *);
108static char *inetname (struct in_addr);
109
110static u_char packet[512]; /* last inbound (icmp) packet */ 108static u_char packet[512]; /* last inbound (icmp) packet */
111static struct opacket *outpacket; /* last output (udp) packet */ 109static struct opacket *outpacket; /* last output (udp) packet */
112 110
@@ -122,10 +120,229 @@ static int max_ttl = 30;
122static u_short ident; 120static u_short ident;
123static u_short port = 32768+666; /* start udp dest port # for probe packets */ 121static u_short port = 32768+666; /* start udp dest port # for probe packets */
124 122
123#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
125static int verbose; 124static int verbose;
125#endif
126static int waittime = 5; /* time to wait for response (in seconds) */ 126static int waittime = 5; /* time to wait for response (in seconds) */
127static int nflag; /* print addresses numerically */ 127static int nflag; /* print addresses numerically */
128 128
129/*
130 * Construct an Internet address representation.
131 * If the nflag has been supplied, give
132 * numeric value, otherwise try for symbolic name.
133 */
134static inline char *
135inetname(struct in_addr in)
136{
137 char *cp;
138 static char line[50];
139 struct hostent *hp;
140 static char domain[MAXHOSTNAMELEN + 1];
141 static int first = 1;
142
143 if (first && !nflag) {
144 first = 0;
145 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
146 (cp = index(domain, '.')))
147 (void) strcpy(domain, cp + 1);
148 else
149 domain[0] = 0;
150 }
151 cp = 0;
152 if (!nflag && in.s_addr != INADDR_ANY) {
153 hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
154 if (hp) {
155 if ((cp = index(hp->h_name, '.')) &&
156 !strcmp(cp + 1, domain))
157 *cp = 0;
158 cp = (char *)hp->h_name;
159 }
160 }
161 if (cp)
162 (void) strcpy(line, cp);
163 else {
164 in.s_addr = ntohl(in.s_addr);
165 strcpy(line, inet_ntoa(in));
166 }
167 return (line);
168}
169
170static inline void
171print(u_char *buf, int cc, struct sockaddr_in *from)
172{
173 struct ip *ip;
174 int hlen;
175
176 ip = (struct ip *) buf;
177 hlen = ip->ip_hl << 2;
178 cc -= hlen;
179
180 if (nflag)
181 printf(" %s", inet_ntoa(from->sin_addr));
182 else
183 printf(" %s (%s)", inetname(from->sin_addr),
184 inet_ntoa(from->sin_addr));
185
186#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
187 if (verbose)
188 printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
189#endif
190}
191
192static inline double
193deltaT(struct timeval *t1p, struct timeval *t2p)
194{
195 double dt;
196
197 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
198 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
199 return (dt);
200}
201
202static inline int
203wait_for_reply(int sock, struct sockaddr_in *from, int reset_timer)
204{
205 fd_set fds;
206 static struct timeval wait;
207 int cc = 0;
208 int fromlen = sizeof (*from);
209
210 FD_ZERO(&fds);
211 FD_SET(sock, &fds);
212 if (reset_timer) {
213 /*
214 * traceroute could hang if someone else has a ping
215 * running and our ICMP reply gets dropped but we don't
216 * realize it because we keep waking up to handle those
217 * other ICMP packets that keep coming in. To fix this,
218 * "reset_timer" will only be true if the last packet that
219 * came in was for us or if this is the first time we're
220 * waiting for a reply since sending out a probe. Note
221 * that this takes advantage of the select() feature on
222 * Linux where the remaining timeout is written to the
223 * struct timeval area.
224 */
225 wait.tv_sec = waittime;
226 wait.tv_usec = 0;
227 }
228
229 if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
230 cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
231 (struct sockaddr *)from, &fromlen);
232
233 return(cc);
234}
235
236#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
237/*
238 * Convert an ICMP "type" field to a printable string.
239 */
240static inline const char *
241pr_type(t)
242 u_char t;
243{
244 static const char * const ttab[] = {
245 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
246 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
247 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
248 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
249 "Info Reply"
250 };
251
252 if(t > 16)
253 return("OUT-OF-RANGE");
254
255 return(ttab[t]);
256}
257#endif
258
259static inline int
260packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq)
261{
262 struct icmp *icp;
263 u_char type, code;
264 int hlen;
265 struct ip *ip;
266
267 ip = (struct ip *) buf;
268 hlen = ip->ip_hl << 2;
269 if (cc < hlen + ICMP_MINLEN) {
270#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
271 if (verbose)
272 printf("packet too short (%d bytes) from %s\n", cc,
273 inet_ntoa(from->sin_addr));
274#endif
275 return (0);
276 }
277 cc -= hlen;
278 icp = (struct icmp *)(buf + hlen);
279 type = icp->icmp_type; code = icp->icmp_code;
280 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
281 type == ICMP_UNREACH) {
282 struct ip *hip;
283 struct udphdr *up;
284
285 hip = &icp->icmp_ip;
286 hlen = hip->ip_hl << 2;
287 up = (struct udphdr *)((u_char *)hip + hlen);
288 if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
289 up->source == htons(ident) &&
290 up->dest == htons(port+seq))
291 return (type == ICMP_TIMXCEED? -1 : code+1);
292 }
293#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
294 if (verbose) {
295 int i;
296 u_long *lp = (u_long *)&icp->icmp_ip;
297
298 printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
299 cc, inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst),
300 type, pr_type(type), icp->icmp_code);
301 for (i = 4; i < cc ; i += sizeof(long))
302 printf("%2d: x%8.8lx\n", i, *lp++);
303 }
304#endif
305 return(0);
306}
307
308static void /* not inline */
309send_probe(int seq, int ttl)
310{
311 struct opacket *op = outpacket;
312 struct ip *ip = &op->ip;
313 struct udphdr *up = &op->udp;
314 int i;
315 struct timezone tz;
316
317 ip->ip_off = 0;
318 ip->ip_hl = sizeof(*ip) >> 2;
319 ip->ip_p = IPPROTO_UDP;
320 ip->ip_len = datalen;
321 ip->ip_ttl = ttl;
322 ip->ip_v = IPVERSION;
323 ip->ip_id = htons(ident+seq);
324
325 up->source = htons(ident);
326 up->dest = htons(port+seq);
327 up->len = htons((u_short)(datalen - sizeof(struct ip)));
328 up->check = 0;
329
330 op->seq = seq;
331 op->ttl = ttl;
332 (void) gettimeofday(&op->tv, &tz);
333
334 i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,
335 sizeof(struct sockaddr));
336 if (i < 0 || i != datalen) {
337 if (i<0)
338 perror("sendto");
339 printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
340 datalen, i);
341 (void) fflush(stdout);
342 }
343}
344
345
129int 346int
130#ifndef BB_TRACEROUTE 347#ifndef BB_TRACEROUTE
131main(argc, argv) 348main(argc, argv)
@@ -138,7 +355,6 @@ traceroute_main(argc, argv)
138 extern char *optarg; 355 extern char *optarg;
139 extern int optind; 356 extern int optind;
140 struct hostent *hp; 357 struct hostent *hp;
141 struct protoent *pe;
142 struct sockaddr_in from, *to; 358 struct sockaddr_in from, *to;
143 int ch, i, on, probe, seq, tos, ttl; 359 int ch, i, on, probe, seq, tos, ttl;
144 360
@@ -152,7 +368,9 @@ traceroute_main(argc, argv)
152 while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) 368 while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF)
153 switch(ch) { 369 switch(ch) {
154 case 'd': 370 case 'd':
371#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG
155 options |= SO_DEBUG; 372 options |= SO_DEBUG;
373#endif
156 break; 374 break;
157 case 'm': 375 case 'm':
158 max_ttl = atoi(optarg); 376 max_ttl = atoi(optarg);
@@ -188,7 +406,9 @@ traceroute_main(argc, argv)
188 error_msg_and_die("tos must be 0 to 255."); 406 error_msg_and_die("tos must be 0 to 255.");
189 break; 407 break;
190 case 'v': 408 case 'v':
409#ifdef BB_FEATURE_TRACEROUTE_VERBOSE
191 verbose++; 410 verbose++;
411#endif
192 break; 412 break;
193 case 'w': 413 case 'w':
194 waittime = atoi(optarg); 414 waittime = atoi(optarg);
@@ -206,21 +426,11 @@ traceroute_main(argc, argv)
206 426
207 setlinebuf (stdout); 427 setlinebuf (stdout);
208 428
209 (void) bzero((char *)&whereto, sizeof(struct sockaddr)); 429 memset(&whereto, 0, sizeof(struct sockaddr));
210 to->sin_family = AF_INET; 430 hp = xgethostbyname(*argv);
211 to->sin_addr.s_addr = inet_addr(*argv);
212 if (to->sin_addr.s_addr != -1)
213 hostname = *argv;
214 else {
215 hp = gethostbyname(*argv);
216 if (hp) {
217 to->sin_family = hp->h_addrtype; 431 to->sin_family = hp->h_addrtype;
218 bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length); 432 memcpy(&to->sin_addr, hp->h_addr, hp->h_length);
219 hostname = (char *)hp->h_name; 433 hostname = (char *)hp->h_name;
220 } else {
221 error_msg_and_die("unknown host %s", *argv);
222 }
223 }
224 if (*++argv) 434 if (*++argv)
225 datalen = atoi(*argv); 435 datalen = atoi(*argv);
226 if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) 436 if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket))
@@ -228,7 +438,7 @@ traceroute_main(argc, argv)
228 MAXPACKET - sizeof(struct opacket)); 438 MAXPACKET - sizeof(struct opacket));
229 datalen += sizeof(struct opacket); 439 datalen += sizeof(struct opacket);
230 outpacket = (struct opacket *)xmalloc((unsigned)datalen); 440 outpacket = (struct opacket *)xmalloc((unsigned)datalen);
231 (void) bzero((char *)outpacket, datalen); 441 memset(outpacket, 0, datalen);
232 outpacket->ip.ip_dst = to->sin_addr; 442 outpacket->ip.ip_dst = to->sin_addr;
233 outpacket->ip.ip_tos = tos; 443 outpacket->ip.ip_tos = tos;
234 outpacket->ip.ip_v = IPVERSION; 444 outpacket->ip.ip_v = IPVERSION;
@@ -236,19 +446,19 @@ traceroute_main(argc, argv)
236 446
237 ident = (getpid() & 0xffff) | 0x8000; 447 ident = (getpid() & 0xffff) | 0x8000;
238 448
239 if ((pe = getprotobyname("icmp")) == NULL) 449 if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
240 error_msg_and_die("icmp: unknown protocol"); 450 perror_msg_and_die(can_not_create_raw_socket);
241 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) 451
242 perror_msg_and_die("icmp socket"); 452 s = create_icmp_socket();
453
454#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG
243 if (options & SO_DEBUG) 455 if (options & SO_DEBUG)
244 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 456 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
245 (char *)&on, sizeof(on)); 457 (char *)&on, sizeof(on));
458#endif
246 if (options & SO_DONTROUTE) 459 if (options & SO_DONTROUTE)
247 (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, 460 (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
248 (char *)&on, sizeof(on)); 461 (char *)&on, sizeof(on));
249
250 if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
251 perror_msg_and_die("raw socket");
252#ifdef SO_SNDBUF 462#ifdef SO_SNDBUF
253 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, 463 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
254 sizeof(datalen)) < 0) 464 sizeof(datalen)) < 0)
@@ -259,15 +469,17 @@ traceroute_main(argc, argv)
259 sizeof(on)) < 0) 469 sizeof(on)) < 0)
260 perror_msg_and_die("IP_HDRINCL"); 470 perror_msg_and_die("IP_HDRINCL");
261#endif IP_HDRINCL 471#endif IP_HDRINCL
472#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG
262 if (options & SO_DEBUG) 473 if (options & SO_DEBUG)
263 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 474 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
264 (char *)&on, sizeof(on)); 475 (char *)&on, sizeof(on));
476#endif
265 if (options & SO_DONTROUTE) 477 if (options & SO_DONTROUTE)
266 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 478 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
267 (char *)&on, sizeof(on)); 479 (char *)&on, sizeof(on));
268 480
269 if (source) { 481 if (source) {
270 (void) bzero((char *)&from, sizeof(struct sockaddr)); 482 memset(&from, 0, sizeof(struct sockaddr));
271 from.sin_family = AF_INET; 483 from.sin_family = AF_INET;
272 from.sin_addr.s_addr = inet_addr(source); 484 from.sin_addr.s_addr = inet_addr(source);
273 if (from.sin_addr.s_addr == -1) 485 if (from.sin_addr.s_addr == -1)
@@ -284,7 +496,6 @@ traceroute_main(argc, argv)
284 if (source) 496 if (source)
285 fprintf(stderr, " from %s", source); 497 fprintf(stderr, " from %s", source);
286 fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); 498 fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);
287 (void) fflush(stderr);
288 499
289 for (ttl = 1; ttl <= max_ttl; ++ttl) { 500 for (ttl = 1; ttl <= max_ttl; ++ttl) {
290 u_long lastaddr = 0; 501 u_long lastaddr = 0;
@@ -312,11 +523,9 @@ traceroute_main(argc, argv)
312 printf(" %g ms", deltaT(&t1, &t2)); 523 printf(" %g ms", deltaT(&t1, &t2));
313 switch(i - 1) { 524 switch(i - 1) {
314 case ICMP_UNREACH_PORT: 525 case ICMP_UNREACH_PORT:
315#ifndef ARCHAIC
316 ip = (struct ip *)packet; 526 ip = (struct ip *)packet;
317 if (ip->ip_ttl <= 1) 527 if (ip->ip_ttl <= 1)
318 printf(" !"); 528 printf(" !");
319#endif ARCHAIC
320 ++got_there; 529 ++got_there;
321 break; 530 break;
322 case ICMP_UNREACH_NET: 531 case ICMP_UNREACH_NET:
@@ -355,239 +564,3 @@ traceroute_main(argc, argv)
355 564
356 return 0; 565 return 0;
357} 566}
358
359static int
360wait_for_reply(sock, from, reset_timer)
361 int sock;
362 struct sockaddr_in *from;
363 int reset_timer;
364{
365 fd_set fds;
366 static struct timeval wait;
367 int cc = 0;
368 int fromlen = sizeof (*from);
369
370 FD_ZERO(&fds);
371 FD_SET(sock, &fds);
372 if (reset_timer) {
373 /*
374 * traceroute could hang if someone else has a ping
375 * running and our ICMP reply gets dropped but we don't
376 * realize it because we keep waking up to handle those
377 * other ICMP packets that keep coming in. To fix this,
378 * "reset_timer" will only be true if the last packet that
379 * came in was for us or if this is the first time we're
380 * waiting for a reply since sending out a probe. Note
381 * that this takes advantage of the select() feature on
382 * Linux where the remaining timeout is written to the
383 * struct timeval area.
384 */
385 wait.tv_sec = waittime;
386 wait.tv_usec = 0;
387 }
388
389 if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
390 cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
391 (struct sockaddr *)from, &fromlen);
392
393 return(cc);
394}
395
396
397static void
398send_probe(seq, ttl)
399 int seq, ttl;
400{
401 struct opacket *op = outpacket;
402 struct ip *ip = &op->ip;
403 struct udphdr *up = &op->udp;
404 int i;
405 struct timezone tz;
406
407 ip->ip_off = 0;
408 ip->ip_hl = sizeof(*ip) >> 2;
409 ip->ip_p = IPPROTO_UDP;
410 ip->ip_len = datalen;
411 ip->ip_ttl = ttl;
412 ip->ip_v = IPVERSION;
413 ip->ip_id = htons(ident+seq);
414
415 up->source = htons(ident);
416 up->dest = htons(port+seq);
417 up->len = htons((u_short)(datalen - sizeof(struct ip)));
418 up->check = 0;
419
420 op->seq = seq;
421 op->ttl = ttl;
422 (void) gettimeofday(&op->tv, &tz);
423
424 i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,
425 sizeof(struct sockaddr));
426 if (i < 0 || i != datalen) {
427 if (i<0)
428 perror("sendto");
429 printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
430 datalen, i);
431 (void) fflush(stdout);
432 }
433}
434
435
436static double
437deltaT(t1p, t2p)
438 struct timeval *t1p, *t2p;
439{
440 register double dt;
441
442 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
443 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
444 return (dt);
445}
446
447
448/*
449 * Convert an ICMP "type" field to a printable string.
450 */
451static const char *
452pr_type(t)
453 u_char t;
454{
455 static const char * const ttab[] = {
456 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
457 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
458 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
459 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
460 "Info Reply"
461 };
462
463 if(t > 16)
464 return("OUT-OF-RANGE");
465
466 return(ttab[t]);
467}
468
469
470static int
471packet_ok(buf, cc, from, seq)
472 u_char *buf;
473 int cc;
474 struct sockaddr_in *from;
475 int seq;
476{
477 register struct icmp *icp;
478 u_char type, code;
479 int hlen;
480#ifndef ARCHAIC
481 struct ip *ip;
482
483 ip = (struct ip *) buf;
484 hlen = ip->ip_hl << 2;
485 if (cc < hlen + ICMP_MINLEN) {
486 if (verbose)
487 printf("packet too short (%d bytes) from %s\n", cc,
488 inet_ntoa(from->sin_addr));
489 return (0);
490 }
491 cc -= hlen;
492 icp = (struct icmp *)(buf + hlen);
493#else
494 icp = (struct icmp *)buf;
495#endif ARCHAIC
496 type = icp->icmp_type; code = icp->icmp_code;
497 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
498 type == ICMP_UNREACH) {
499 struct ip *hip;
500 struct udphdr *up;
501
502 hip = &icp->icmp_ip;
503 hlen = hip->ip_hl << 2;
504 up = (struct udphdr *)((u_char *)hip + hlen);
505 if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
506 up->source == htons(ident) &&
507 up->dest == htons(port+seq))
508 return (type == ICMP_TIMXCEED? -1 : code+1);
509 }
510#ifndef ARCHAIC
511 if (verbose) {
512 int i;
513 u_long *lp = (u_long *)&icp->icmp_ip;
514
515 printf("\n%d bytes from %s to %s", cc,
516 inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst));
517 printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
518 icp->icmp_code);
519 for (i = 4; i < cc ; i += sizeof(long))
520 printf("%2d: x%8.8lx\n", i, *lp++);
521 }
522#endif ARCHAIC
523 return(0);
524}
525
526
527static void
528print(buf, cc, from)
529 u_char *buf;
530 int cc;
531 struct sockaddr_in *from;
532{
533 struct ip *ip;
534 int hlen;
535
536 ip = (struct ip *) buf;
537 hlen = ip->ip_hl << 2;
538 cc -= hlen;
539
540 if (nflag)
541 printf(" %s", inet_ntoa(from->sin_addr));
542 else
543 printf(" %s (%s)", inetname(from->sin_addr),
544 inet_ntoa(from->sin_addr));
545
546 if (verbose)
547 printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
548}
549
550
551/*
552 * Construct an Internet address representation.
553 * If the nflag has been supplied, give
554 * numeric value, otherwise try for symbolic name.
555 */
556static char *
557inetname(in)
558 struct in_addr in;
559{
560 register char *cp;
561 static char line[50];
562 struct hostent *hp;
563 static char domain[MAXHOSTNAMELEN + 1];
564 static int first = 1;
565
566 if (first && !nflag) {
567 first = 0;
568 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
569 (cp = index(domain, '.')))
570 (void) strcpy(domain, cp + 1);
571 else
572 domain[0] = 0;
573 }
574 cp = 0;
575 if (!nflag && in.s_addr != INADDR_ANY) {
576 hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
577 if (hp) {
578 if ((cp = index(hp->h_name, '.')) &&
579 !strcmp(cp + 1, domain))
580 *cp = 0;
581 cp = (char *)hp->h_name;
582 }
583 }
584 if (cp)
585 (void) strcpy(line, cp);
586 else {
587 in.s_addr = ntohl(in.s_addr);
588#define C(x) ((x) & 0xff)
589 sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
590 C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
591 }
592 return (line);
593}