From 43b094b584d8e24406bb819e056c9ce618167ee8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Apr 2010 20:16:11 -0700 Subject: remove stdio from allnoconfig build Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 2d52c3db9..7a5e7ae4d 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -105,7 +105,9 @@ static const char *unpack_usage_messages(void) static void full_write2_str(const char *str) { - xwrite_str(STDERR_FILENO, str); + // This uses stdio: + //xwrite_str(STDERR_FILENO, str); + write(STDERR_FILENO, str, strlen(str)); } void FAST_FUNC bb_show_usage(void) -- cgit v1.2.3-55-g6feb From def4783a8a8b00f58d224ff6735d3532809aeb54 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Apr 2010 20:39:41 -0700 Subject: vi: remove superfluous check on filename == "" Signed-off-by: Denys Vlasenko --- editors/vi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/vi.c b/editors/vi.c index 28612508f..f925984ba 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2306,7 +2306,7 @@ static int file_size(const char *fn) // what is the byte size of "fn" int cnt; cnt = -1; - if (fn && fn[0] && stat(fn, &st_buf) == 0) // see if file exists + if (fn && stat(fn, &st_buf) == 0) // see if file exists cnt = (int) st_buf.st_size; return cnt; } -- cgit v1.2.3-55-g6feb From c175c4664734e5a363d8cc8668c08f551eff1485 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Apr 2010 22:09:30 -0700 Subject: vi: discover window size even on serial consoles. optional function old new delta edit_file 671 761 +90 wh_helper - 57 +57 query_screen_dimensions 54 63 +9 ar_main 533 542 +9 refresh 767 773 +6 vi_main 242 243 +1 text_yank 56 54 -2 get_terminal_width_height 180 135 -45 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 5/2 up/down: 172/-47) Total: 125 bytes Signed-off-by: Denys Vlasenko --- editors/Config.in | 12 ++++++++++++ editors/vi.c | 23 ++++++++++++++++++++++- libbb/read_key.c | 2 +- libbb/xfuncs.c | 54 ++++++++++++++++++++++++++++++------------------------ 4 files changed, 65 insertions(+), 26 deletions(-) diff --git a/editors/Config.in b/editors/Config.in index e4fdd0f38..5f9566f0a 100644 --- a/editors/Config.in +++ b/editors/Config.in @@ -168,6 +168,18 @@ config FEATURE_VI_WIN_RESIZE help Make busybox vi behave nicely with terminals that get resized. +config FEATURE_VI_ASK_TERMINAL + bool "Use 'tell me cursor position' ESC sequence to measure window" + default n + depends on VI + help + If terminal size can't be retrieved and $LINES/$COLUMNS are not set, + this option makes vi perform a last-ditch effort to find it: + vi positions cursor to 999,999 and asks terminal to report real + cursor position using "ESC [ 6 n" escape sequence, then reads stdin. + + This is not clean but helps a lot on serial lines and such. + config FEATURE_VI_OPTIMIZE_CURSOR bool "Optimize cursor movement" default y diff --git a/editors/vi.c b/editors/vi.c index f925984ba..d3a35e781 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -138,6 +138,9 @@ struct globals { int save_argc; // how many file names on cmd line int cmdcnt; // repetition count unsigned rows, columns; // the terminal screen is this size +#if ENABLE_FEATURE_VI_ASK_TERMINAL + int get_rowcol_error; +#endif int crow, ccol; // cursor is on Crow x Ccol int offset; // chars scrolled off the screen to the left int have_status_msg; // is default edit status needed? @@ -503,7 +506,11 @@ static int init_text_buffer(char *fn) #if ENABLE_FEATURE_VI_WIN_RESIZE static void query_screen_dimensions(void) { - get_terminal_width_height(STDIN_FILENO, &columns, &rows); +# if ENABLE_FEATURE_VI_ASK_TERMINAL + if (!G.get_rowcol_error) + G.get_rowcol_error = +# endif + get_terminal_width_height(STDIN_FILENO, &columns, &rows); if (rows > MAX_SCR_ROWS) rows = MAX_SCR_ROWS; if (columns > MAX_SCR_COLS) @@ -530,6 +537,20 @@ static void edit_file(char *fn) columns = 80; size = 0; query_screen_dimensions(); +#if ENABLE_FEATURE_VI_ASK_TERMINAL + if (G.get_rowcol_error /* TODO? && no input on stdin */) { + uint64_t k; + write1("\033[999;999H" "\033[6n"); + fflush_all(); + k = read_key(STDIN_FILENO, readbuffer, /*timeout_ms:*/ 100); + if ((int32_t)k == KEYCODE_CURSOR_POS) { + uint32_t rc = (k >> 32); + columns = (rc & 0x7fff); + rows = ((rc >> 16) & 0x7fff); + } + query_screen_dimensions(); + } +#endif new_screen(rows, columns); // get memory for virtual screen init_text_buffer(fn); diff --git a/libbb/read_key.c b/libbb/read_key.c index 8422976c9..64557ab14 100644 --- a/libbb/read_key.c +++ b/libbb/read_key.c @@ -214,7 +214,7 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) } n++; /* Try to decipher "ESC [ NNN ; NNN R" sequence */ - if (ENABLE_FEATURE_EDITING_ASK_TERMINAL + if ((ENABLE_FEATURE_EDITING_ASK_TERMINAL || ENABLE_FEATURE_VI_ASK_TERMINAL) && n >= 5 && buffer[0] == '[' && buffer[n-1] == 'R' diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index aec165f06..d93dd2af9 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -210,34 +210,40 @@ char* FAST_FUNC xmalloc_ttyname(int fd) return buf; } -/* It is perfectly ok to pass in a NULL for either width or for - * height, in which case that value will not be set. */ -int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height) +static int wh_helper(int value, int def_val, const char *env_name, int *err) { - struct winsize win = { 0, 0, 0, 0 }; - int ret = ioctl(fd, TIOCGWINSZ, &win); - - if (height) { - if (!win.ws_row) { - char *s = getenv("LINES"); - if (s) win.ws_row = atoi(s); - } - if (win.ws_row <= 1 || win.ws_row >= 30000) - win.ws_row = 24; - *height = (int) win.ws_row; - } - - if (width) { - if (!win.ws_col) { - char *s = getenv("COLUMNS"); - if (s) win.ws_col = atoi(s); + if (value == 0) { + char *s = getenv(env_name); + if (s) { + value = atoi(s); + /* If LINES/COLUMNS are set, pretent that there is + * no error getting w/h, this prevents some ugly + * cursor tricks by our callers */ + *err = 0; } - if (win.ws_col <= 1 || win.ws_col >= 30000) - win.ws_col = 80; - *width = (int) win.ws_col; } + if (value <= 1 || value >= 30000) + value = def_val; + return value; +} - return ret; +/* It is perfectly ok to pass in a NULL for either width or for + * height, in which case that value will not be set. */ +int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height) +{ + struct winsize win; + int err; + + win.ws_row = 0; + win.ws_col = 0; + /* I've seen ioctl returning 0, but row/col is (still?) 0. + * We treat that as an error too. */ + err = ioctl(fd, TIOCGWINSZ, &win) != 0 || win.ws_row == 0; + if (height) + *height = wh_helper(win.ws_row, 24, "LINES", &err); + if (width) + *width = wh_helper(win.ws_col, 80, "COLUMNS", &err); + return err; } int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) -- cgit v1.2.3-55-g6feb From 96a18332316568ebccaa186ffb519b48c4310714 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 Apr 2010 22:36:07 -0400 Subject: sed: fix c cmd Signed-off-by: Denys Vlasenko --- editors/sed.c | 2 +- testsuite/sed.tests | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/editors/sed.c b/editors/sed.c index e5e187725..302a15605 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -1031,7 +1031,7 @@ static void process_files(void) case 'c': /* Only triggers on last line of a matching range. */ if (!sed_cmd->in_match) - sed_puts(sed_cmd->string, NO_EOL_CHAR); + sed_puts(sed_cmd->string, '\n'); goto discard_line; /* Read file, append contents to output */ diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 875c946be..f88524d07 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests @@ -248,4 +248,9 @@ testing "sed beginning (^) matches only once" \ ">/usrlib<\n" "" \ "/usr/lib\n" +testing "sed c" \ + "sed 'crepl'" \ + "repl\nrepl\n" "" \ + "first\nsecond\n" + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From f2c16edf99486a0ce2ca57f111831668e77d0fd1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 20 Apr 2010 04:00:03 -0400 Subject: sed: fix nested {} case Signed-off-by: Denys Vlasenko --- editors/sed.c | 10 +++++++++- testsuite/sed.tests | 5 +++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/editors/sed.c b/editors/sed.c index 302a15605..30ab8c9fb 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -936,7 +936,15 @@ static void process_files(void) /* Skip blocks of commands we didn't match */ if (sed_cmd->cmd == '{') { if (sed_cmd->invert ? matched : !matched) { - while (sed_cmd->cmd != '}') { + unsigned nest_cnt = 0; + while (1) { + if (sed_cmd->cmd == '{') + nest_cnt++; + if (sed_cmd->cmd == '}') { + nest_cnt--; + if (nest_cnt == 0) + break; + } sed_cmd = sed_cmd->next; if (!sed_cmd) bb_error_msg_and_die("unterminated {"); diff --git a/testsuite/sed.tests b/testsuite/sed.tests index f88524d07..b0de9657c 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests @@ -253,4 +253,9 @@ testing "sed c" \ "repl\nrepl\n" "" \ "first\nsecond\n" +testing "sed nested {}s" \ + "sed '/asd/ { p; /s/ { s/s/c/ }; p; q }'" \ + "qwe\nasd\nacd\nacd\n" "" \ + "qwe\nasd\nzxc\n" + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 5a7c72015c0562dbe19f1e493b54b4c9db7f6f3a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 20 Apr 2010 21:02:57 -0400 Subject: busybox --list option. +140 bytes. Rob wanted it. Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 69 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 7a5e7ae4d..a8cd8e65f 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -595,6 +595,17 @@ static void check_suid(int applet_no) #if ENABLE_FEATURE_INSTALLER +static const char usr_bin [] ALIGN1 = "/usr/bin/"; +static const char usr_sbin[] ALIGN1 = "/usr/sbin/"; +static const char *const install_dir[] = { + &usr_bin [8], /* "/" */ + &usr_bin [4], /* "/bin/" */ + &usr_sbin[4], /* "/sbin/" */ + usr_bin, + usr_sbin +}; + + /* create (sym)links for each applet */ static void install_links(const char *busybox, int use_symbolic_links, char *custom_install_dir) @@ -602,16 +613,6 @@ static void install_links(const char *busybox, int use_symbolic_links, /* directory table * this should be consistent w/ the enum, * busybox.h::bb_install_loc_t, or else... */ - static const char usr_bin [] ALIGN1 = "/usr/bin"; - static const char usr_sbin[] ALIGN1 = "/usr/sbin"; - static const char *const install_dir[] = { - &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */ - &usr_bin [4], /* "/bin" */ - &usr_sbin[4], /* "/sbin" */ - usr_bin, - usr_sbin - }; - int (*lf)(const char *, const char *); char *fpc; unsigned i; @@ -635,8 +636,8 @@ static void install_links(const char *busybox, int use_symbolic_links, } } #else -#define install_links(x,y,z) ((void)0) -#endif /* FEATURE_INSTALLER */ +# define install_links(x,y,z) ((void)0) +#endif /* If we were called as "busybox..." */ static int busybox_main(char **argv) @@ -657,19 +658,20 @@ static int busybox_main(char **argv) full_write2_str(bb_banner); /* reuse const string */ full_write2_str(" multi-call binary.\n"); /* reuse */ full_write2_str( - "Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko\n" - "and others. Licensed under GPLv2.\n" - "See source distribution for full notice.\n" - "\n" - "Usage: busybox [function] [arguments]...\n" - " or: function [arguments]...\n" - "\n" - "\tBusyBox is a multi-call binary that combines many common Unix\n" - "\tutilities into a single executable. Most people will create a\n" - "\tlink to busybox for each function they wish to use and BusyBox\n" - "\twill act like whatever it was invoked as.\n" - "\n" - "Currently defined functions:\n"); + "Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko\n" + "and others. Licensed under GPLv2.\n" + "See source distribution for full notice.\n" + "\n" + "Usage: busybox [function] [arguments]...\n" + " or: function [arguments]...\n" + "\n" + "\tBusyBox is a multi-call binary that combines many common Unix\n" + "\tutilities into a single executable. Most people will create a\n" + "\tlink to busybox for each function they wish to use and BusyBox\n" + "\twill act like whatever it was invoked as.\n" + "\n" + "Currently defined functions:\n" + ); col = 0; a = applet_names; /* prevent last comma to be in the very last pos */ @@ -694,6 +696,23 @@ static int busybox_main(char **argv) return 0; } + if (strncmp(argv[1], "--list", 6) == 0) { + unsigned i = 0; + const char *a = applet_names; + dup2(1, 2); + while (*a) { +#if ENABLE_FEATURE_INSTALLER + if (argv[1][6]) /* --list-path? */ + full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); +#endif + full_write2_str(a); + full_write2_str("\n"); + i++; + a += strlen(a) + 1; + } + return 0; + } + if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) { int use_symbolic_links; const char *busybox; -- cgit v1.2.3-55-g6feb From 238c83bd8237e482911b8272e7f420060f5e7714 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 21 Apr 2010 18:05:10 -0400 Subject: ftpd: work around LIST -aXYZ too, not only LIST -lXYZ Signed-off-by: Denys Vlasenko --- networking/Config.in | 4 ++-- networking/ftpd.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/networking/Config.in b/networking/Config.in index 61e59b244..ce7166f98 100644 --- a/networking/Config.in +++ b/networking/Config.in @@ -122,8 +122,8 @@ config FEATURE_FTPD_ACCEPT_BROKEN_LIST default y depends on FTPD help - Some ftp-clients (among them KDE's Konqueror) issue illegal - "LIST -la" requests. This option works around those problems. + Some ftp clients (among them KDE's Konqueror) issue illegal + "LIST -l" requests. This option works around such problems. It might prevent you from listing files starting with "-" and it increases the code size by ~40 bytes. Most other ftp servers seem to behave similar to this. diff --git a/networking/ftpd.c b/networking/ftpd.c index 9d43ea3a2..c63b9319e 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -618,10 +618,10 @@ popen_ls(const char *opt) argv[4] = NULL; /* Improve compatibility with non-RFC conforming FTP clients - * which send e.g. "LIST -l", "LIST -la". + * which send e.g. "LIST -l", "LIST -la", "LIST -aL". * See https://bugs.kde.org/show_bug.cgi?id=195578 */ if (ENABLE_FEATURE_FTPD_ACCEPT_BROKEN_LIST - && G.ftp_arg && G.ftp_arg[0] == '-' && G.ftp_arg[1] == 'l' + && G.ftp_arg && G.ftp_arg[0] == '-' ) { const char *tmp = strchr(G.ftp_arg, ' '); if (tmp) /* skip the space */ -- cgit v1.2.3-55-g6feb From 5f94346f7387cb5e33cf202dd3306f062bb22052 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 22 Apr 2010 00:45:28 -0400 Subject: date: support -d @SECONDS_SINCE_1970 function old new delta parse_datestr 647 721 +74 Signed-off-by: Denys Vlasenko --- libbb/time.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libbb/time.c b/libbb/time.c index 5cd04268c..8d176e52e 100644 --- a/libbb/time.c +++ b/libbb/time.c @@ -68,6 +68,16 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) end = '\0'; /* else end != NUL and we error out */ } + } else if (date_str[0] == '@') { + time_t t = bb_strtol(date_str + 1, NULL, 10); + if (!errno) { + struct tm *lt = localtime(&t); + if (lt) { + *ptm = *lt; + return; + } + } + end = '1'; } else { /* Googled the following on an old date manpage: * -- cgit v1.2.3-55-g6feb From 05273daf6ff570e5e4936028ef501c59be745311 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Apr 2010 08:45:44 +0200 Subject: grep: makw -w support unconditional Signed-off-by: Denys Vlasenko --- findutils/grep.c | 7 +++---- include/usage.h | 5 +---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/findutils/grep.c b/findutils/grep.c index a321cc31b..40caef423 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -24,10 +24,9 @@ /* options */ #define OPTSTR_GREP \ - "lnqvscFiHhe:f:Lorm:" \ + "lnqvscFiHhe:f:Lorm:w" \ IF_FEATURE_GREP_CONTEXT("A:B:C:") \ IF_FEATURE_GREP_EGREP_ALIAS("E") \ - IF_DESKTOP("w") \ IF_EXTRA_COMPAT("z") \ "aI" @@ -51,11 +50,11 @@ enum { OPTBIT_o, /* show only matching parts of lines */ OPTBIT_r, /* recurse dirs */ OPTBIT_m, /* -m MAX_MATCHES */ + OPTBIT_w, /* -w whole word match */ IF_FEATURE_GREP_CONTEXT( OPTBIT_A ,) /* -A NUM: after-match context */ IF_FEATURE_GREP_CONTEXT( OPTBIT_B ,) /* -B NUM: before-match context */ IF_FEATURE_GREP_CONTEXT( OPTBIT_C ,) /* -C NUM: -A and -B combined */ IF_FEATURE_GREP_EGREP_ALIAS(OPTBIT_E ,) /* extended regexp */ - IF_DESKTOP( OPTBIT_w ,) /* whole word match */ IF_EXTRA_COMPAT( OPTBIT_z ,) /* input is NUL terminated */ OPT_l = 1 << OPTBIT_l, OPT_n = 1 << OPTBIT_n, @@ -73,11 +72,11 @@ enum { OPT_o = 1 << OPTBIT_o, OPT_r = 1 << OPTBIT_r, OPT_m = 1 << OPTBIT_m, + OPT_w = 1 << OPTBIT_w, OPT_A = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_A)) + 0, OPT_B = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_B)) + 0, OPT_C = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_C)) + 0, OPT_E = IF_FEATURE_GREP_EGREP_ALIAS((1 << OPTBIT_E)) + 0, - OPT_w = IF_DESKTOP( (1 << OPTBIT_w)) + 0, OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0, }; diff --git a/include/usage.h b/include/usage.h index 4568fac9f..38594811e 100644 --- a/include/usage.h +++ b/include/usage.h @@ -1531,8 +1531,7 @@ "\n -H HOST Log HOST into the utmp file as the hostname" \ #define grep_trivial_usage \ - "[-HhnlLoqvsri" \ - IF_DESKTOP("w") \ + "[-HhnlLoqvsriw" \ "F" \ IF_FEATURE_GREP_EGREP_ALIAS("E") \ IF_EXTRA_COMPAT("z") \ @@ -1554,9 +1553,7 @@ "\n -s Suppress open and read errors" \ "\n -r Recurse" \ "\n -i Ignore case" \ - IF_DESKTOP( \ "\n -w Match whole words only" \ - ) \ "\n -F PATTERN is a literal (not regexp)" \ IF_FEATURE_GREP_EGREP_ALIAS( \ "\n -E PATTERN is an extended regexp" \ -- cgit v1.2.3-55-g6feb From 9138817a27068073a565d915d10301ca00e79659 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Apr 2010 09:54:04 +0200 Subject: find: fix -name matching for dotfiles. -1 byte Signed-off-by: Denys Vlasenko --- findutils/find.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/findutils/find.c b/findutils/find.c index 0b06938da..30fb03dd1 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -198,14 +198,19 @@ static int exec_actions(action ***appp, const char *fileName, const struct stat ACTF(name) { const char *tmp = bb_basename(fileName); - if (tmp != fileName && !*tmp) { /* "foo/bar/". Oh no... go back to 'b' */ + if (tmp != fileName && *tmp == '\0') { + /* "foo/bar/". Oh no... go back to 'b' */ tmp--; while (tmp != fileName && *--tmp != '/') continue; if (*tmp == '/') tmp++; } - return fnmatch(ap->pattern, tmp, FNM_PERIOD | (ap->iname ? FNM_CASEFOLD : 0)) == 0; + /* Was using FNM_PERIOD flag too, + * but somewhere between 4.1.20 and 4.4.0 GNU find stopped using it. + * find -name '*foo' should match .foo too: + */ + return fnmatch(ap->pattern, tmp, (ap->iname ? FNM_CASEFOLD : 0)) == 0; } #if ENABLE_FEATURE_FIND_PATH -- cgit v1.2.3-55-g6feb From 4640ccc39940a4842c62a9c1cf91f425b3f0bc99 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Mon, 26 Apr 2010 13:53:57 +0200 Subject: cpio: "NNN blocks" should go to stderr Signed-off-by: Matheus Izvekov Signed-off-by: Denys Vlasenko --- archival/cpio.c | 2 +- testsuite/cpio.tests | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/archival/cpio.c b/archival/cpio.c index 858e59b30..2698f0791 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -424,7 +424,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) if (archive_handle->cpio__blocks != (off_t)-1 && !(opt & CPIO_OPT_QUIET) ) { - printf("%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); + fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); } return EXIT_SUCCESS; diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index e53ade925..325664d71 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests @@ -32,7 +32,7 @@ rm -rf cpio.testdir cpio.testdir2 2>/dev/null # testing "test name" "command" "expected result" "file input" "stdin" testing "cpio extracts zero-sized hardlinks" \ -"$ECHO -ne '$hexdump' | bzcat | cpio -i; echo \$?; +"$ECHO -ne '$hexdump' | bzcat | cpio -i 2>&1; echo \$?; ls -ln cpio.testdir | $FILTER_LS" \ "\ 1 blocks @@ -45,7 +45,7 @@ ls -ln cpio.testdir | $FILTER_LS" \ test x"$SKIP_KNOWN_BUGS" = x"" && { # Currently fails. Numerous buglets: "1 blocks" versus "1 block", -# "1 block" must go to stderr, does not list cpio.testdir/x and cpio.testdir/y +# does not list cpio.testdir/x and cpio.testdir/y testing "cpio lists hardlinks" \ "$ECHO -ne '$hexdump' | bzcat | cpio -t 2>&1; echo \$?" \ "\ @@ -70,7 +70,7 @@ ln cpio.testdir/nonempty cpio.testdir/nonempty1 mkdir cpio.testdir2 testing "cpio extracts zero-sized hardlinks 2" \ -"find cpio.testdir | cpio -H newc --create | (cd cpio.testdir2 && cpio -i); echo \$?; +"find cpio.testdir | cpio -H newc --create | (cd cpio.testdir2 && cpio -i 2>&1); echo \$?; ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ "\ 2 blocks @@ -87,7 +87,7 @@ ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ # Was trying to create "/usr/bin", correct is "usr/bin". rm -rf cpio.testdir testing "cpio -p with absolute paths" \ -"echo /usr/bin | cpio -dp cpio.testdir; echo \$?; +"echo /usr/bin | cpio -dp cpio.testdir 2>&1; echo \$?; ls cpio.testdir" \ "\ 1 blocks -- cgit v1.2.3-55-g6feb From 0c1ba443c83553e85d39e26ae4bb126a2c58ce93 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 26 Apr 2010 14:01:14 +0200 Subject: cmp: ifdefectomy Signed-off-by: Rob Landley Signed-off-by: Denys Vlasenko --- editors/cmp.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/editors/cmp.c b/editors/cmp.c index 0cb80f21e..e8294510a 100644 --- a/editors/cmp.c +++ b/editors/cmp.c @@ -37,8 +37,7 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) { FILE *fp1, *fp2, *outfile = stdout; const char *filename1, *filename2 = "-"; - IF_DESKTOP(off_t skip1 = 0, skip2 = 0;) - off_t char_pos = 0; + off_t skip1 = 0, skip2 = 0, char_pos = 0; int line_pos = 1; /* Hopefully won't overflow... */ const char *fmt; int c1, c2; @@ -59,14 +58,12 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) if (*++argv) { filename2 = *argv; -#if ENABLE_DESKTOP - if (*++argv) { + if (ENABLE_DESKTOP && *++argv) { skip1 = XATOOFF(*argv); if (*++argv) { skip2 = XATOOFF(*argv); } } -#endif } fp2 = xfopen_stdin(filename2); @@ -83,10 +80,10 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) else fmt = fmt_differ; -#if ENABLE_DESKTOP - while (skip1) { getc(fp1); skip1--; } - while (skip2) { getc(fp2); skip2--; } -#endif + if (ENABLE_DESKTOP) { + while (skip1) { getc(fp1); skip1--; } + while (skip2) { getc(fp2); skip2--; } + } do { c1 = getc(fp1); c2 = getc(fp2); -- cgit v1.2.3-55-g6feb From 920185c69ac9addf06cb47a0f2336e075d6dacb2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Apr 2010 14:04:29 +0200 Subject: cmp: remove history comment. it is more natural to keep it in source control The comment was: * Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) * * Original version majorly reworked for SUSv3 compliance, bug fixes, and * size optimizations. Changes include: * 1) Now correctly distinguishes between errors and actual file differences. * 2) Proper handling of '-' args. * 3) Actual error checking of i/o. * 4) Accept SUSv3 -l option. Note that we use the slightly nicer gnu format * in the '-l' case. Signed-off-by: Denys Vlasenko --- editors/cmp.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/editors/cmp.c b/editors/cmp.c index e8294510a..dbfa4be35 100644 --- a/editors/cmp.c +++ b/editors/cmp.c @@ -10,17 +10,6 @@ /* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */ /* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */ -/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) - * - * Original version majorly reworked for SUSv3 compliance, bug fixes, and - * size optimizations. Changes include: - * 1) Now correctly distinguishes between errors and actual file differences. - * 2) Proper handling of '-' args. - * 3) Actual error checking of i/o. - * 4) Accept SUSv3 -l option. Note that we use the slightly nicer gnu format - * in the '-l' case. - */ - #include "libbb.h" static const char fmt_eof[] ALIGN1 = "cmp: EOF on %s\n"; -- cgit v1.2.3-55-g6feb From 3963d943f8a9b4ef89f000b5e1424e63dba920f5 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 26 Apr 2010 14:21:27 +0200 Subject: ash: refresh stack pointers after makestrspace in rmescapes Without this, rmescapes sometimes returns random garbage while performing parameter expansions such as ${foo#bar}, in the event that the allocation of r happens to need to reallocate the stack and hence invalidate str and p. I'd love to provide a test case but unfortunately it's dependent on exact stack layout, so I don't have anything simpler than the situation described in https://bugs.launchpad.net/ubuntu/+source/partman-base/+bug/527401/comments/23 which involved a sequence of foo="${foo#*, }" expansions on a long string inside our RAID configuration tool. The same fix has been in dash since 2007-09-26, contributed by Roy Marples . I actually came up with it independently almost to the character, but then synced it up with the variable naming used in dash when I noticed that change afterwards. Signed-off-by: Colin Watson Signed-off-by: Denys Vlasenko --- shell/ash.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/shell/ash.c b/shell/ash.c index 9d55f892e..ec5e0b8c7 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5425,7 +5425,11 @@ rmescapes(char *str, int flag) size_t fulllen = len + strlen(p) + 1; if (flag & RMESCAPE_GROW) { + int strloc = str - (char *)stackblock(); r = makestrspace(fulllen, expdest); + /* p and str may be invalidated by makestrspace */ + str = (char *)stackblock() + strloc; + p = str + len; } else if (flag & RMESCAPE_HEAP) { r = ckmalloc(fulllen); } else { -- cgit v1.2.3-55-g6feb From 6646de02148cecdc1b97a999b10eaa930d9cfca5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Apr 2010 14:25:33 +0200 Subject: dnsd: fix unaligned access problem Signed-off-by: Denys Vlasenko --- networking/dnsd.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/networking/dnsd.c b/networking/dnsd.c index c76a54f9e..1a99040ac 100644 --- a/networking/dnsd.c +++ b/networking/dnsd.c @@ -44,10 +44,15 @@ struct dns_head { uint16_t nauth; uint16_t nadd; }; +/* Structure used to access type and class fields. + * They are totally unaligned, but gcc 4.3.4 thinks that pointer of type uint16_t* + * is 16-bit aligned and replaces 16-bit memcpy (in move_from_unaligned16 macro) + * with aligned halfword access on arm920t! + * Oh well. Slapping PACKED everywhere seems to help: */ struct type_and_class { - uint16_t type; - uint16_t class; -}; + uint16_t type PACKED; + uint16_t class PACKED; +} PACKED; /* element of known name, ip address and reversed ip address */ struct dns_entry { struct dns_entry *next; -- cgit v1.2.3-55-g6feb From 25b10d97e66a74d4e5a5571afb1b8369c31eefca Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Apr 2010 08:54:24 +0200 Subject: telnet: prevent SEGV if we are requested TELOPT_NEW_ENVIRON. Signed-off-by: Denys Vlasenko --- networking/telnet.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/networking/telnet.c b/networking/telnet.c index 09f75cc84..ec3db0c5e 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -299,7 +299,7 @@ static void put_iac_subopt(byte c, char *str) static void put_iac_subopt_autologin(void) { int len = strlen(G.autologin) + 6; // (2 + 1 + 1 + strlen + 2) - const char *user = "USER"; + const char *p = "USER"; if (G.iaclen + len > IACBUFSIZE) iac_flush(); @@ -310,13 +310,14 @@ static void put_iac_subopt_autologin(void) put_iac(TELQUAL_IS); put_iac(NEW_ENV_VAR); - while (*user) - put_iac(*user++); + while (*p) + put_iac(*p++); put_iac(NEW_ENV_VALUE); - while (*G.autologin) - put_iac(*G.autologin++); + p = G.autologin; + while (*p) + put_iac(*p++); put_iac(IAC); put_iac(SE); @@ -441,7 +442,6 @@ static void to_sga(void) static void to_ttype(void) { /* Tell server we will (or won't) do TTYPE */ - if (G.ttype) put_iac2(WILL, TELOPT_TTYPE); else @@ -453,7 +453,6 @@ static void to_ttype(void) static void to_new_environ(void) { /* Tell server we will (or will not) do AUTOLOGIN */ - if (G.autologin) put_iac2(WILL, TELOPT_NEW_ENVIRON); else @@ -505,12 +504,12 @@ static int subneg(byte c) G.telstate = TS_SUB2; #if ENABLE_FEATURE_TELNET_TTYPE else - if (c == TELOPT_TTYPE) + if (c == TELOPT_TTYPE && G.ttype) put_iac_subopt(TELOPT_TTYPE, G.ttype); #endif #if ENABLE_FEATURE_TELNET_AUTOLOGIN else - if (c == TELOPT_NEW_ENVIRON) + if (c == TELOPT_NEW_ENVIRON && G.autologin) put_iac_subopt_autologin(); #endif break; -- cgit v1.2.3-55-g6feb From a659b81dfa435aa19130a8c7dd1bfe8fa9a22131 Mon Sep 17 00:00:00 2001 From: Tomas Heinrich Date: Thu, 29 Apr 2010 13:43:39 +0200 Subject: libbb/lineedit: add support for preserving "broken" (non-unicode) chars Signed-off-by: Tomas Heinrich Signed-off-by: Denys Vlasenko --- Config.in | 11 ++++++++++ libbb/lineedit.c | 62 +++++++++++++++++++++++++++++++++++++++++++---------- libbb/unicode.c | 12 +++-------- testsuite/ash.tests | 24 +++++++++++++++++++++ 4 files changed, 89 insertions(+), 20 deletions(-) diff --git a/Config.in b/Config.in index 40af9115d..a5d20038a 100644 --- a/Config.in +++ b/Config.in @@ -223,6 +223,17 @@ config UNICODE_NEUTRAL_TABLE With this option on, more extensive (and bigger) table of neutral chars will be used. +config UNICODE_PRESERVE_BROKEN + bool "Make it possible to enter sequences of chars which are not Unicode" + default n + depends on UNICODE_SUPPORT + help + With this option on, invalid UTF-8 bytes are not substituted + with the selected substitution character. + For example, this means that entering 'l', 's', ' ', 0xff, [Enter] + at shell prompt will list file named 0xff (single char name + with char value 255), not file named '?'. + config LONG_OPTS bool "Support for --long-options" default y diff --git a/libbb/lineedit.c b/libbb/lineedit.c index dc90846f9..622f9ddfc 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -68,7 +68,7 @@ #undef CHAR_T #if ENABLE_UNICODE_SUPPORT -# define BB_NUL L'\0' +# define BB_NUL ((wchar_t)0) # define CHAR_T wchar_t static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); } # if ENABLE_FEATURE_EDITING_VI @@ -92,6 +92,14 @@ static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } #endif +# if ENABLE_UNICODE_PRESERVE_BROKEN +# define unicode_mark_inv_wchar(wc) ((wc) | 0x20000000) +# define unicode_is_inv_wchar(wc) ((wc) & 0x20000000) +# else +# define unicode_is_inv_wchar(wc) 0 +# endif + + enum { /* We use int16_t for positions, need to limit line len */ MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN < 0x7ff0 @@ -208,24 +216,58 @@ static size_t load_string(const char *src, int maxsize) ssize_t len = mbstowcs(command_ps, src, maxsize - 1); if (len < 0) len = 0; - command_ps[len] = L'\0'; + command_ps[len] = 0; return len; } -static size_t save_string(char *dst, int maxsize) +static unsigned save_string(char *dst, unsigned maxsize) { +#if !ENABLE_UNICODE_PRESERVE_BROKEN ssize_t len = wcstombs(dst, command_ps, maxsize - 1); if (len < 0) len = 0; dst[len] = '\0'; return len; +#else + unsigned dstpos = 0; + unsigned srcpos = 0; + + maxsize--; + while (dstpos < maxsize) { + wchar_t wc; + int n = srcpos; + while ((wc = command_ps[srcpos]) != 0 + && !unicode_is_inv_wchar(wc) + ) { + srcpos++; + } + command_ps[srcpos] = 0; + n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos); + if (n < 0) /* should not happen */ + break; + dstpos += n; + if (wc == 0) /* usually is */ + break; + /* We do have invalid byte here! */ + command_ps[srcpos] = wc; /* restore it */ + srcpos++; + if (dstpos == maxsize) + break; + dst[dstpos++] = (char) wc; + } + dst[dstpos] = '\0'; + return dstpos; +#endif } /* I thought just fputwc(c, stdout) would work. But no... */ static void BB_PUTCHAR(wchar_t c) { char buf[MB_CUR_MAX + 1]; mbstate_t mbst = { 0 }; - ssize_t len = wcrtomb(buf, c, &mbst); + ssize_t len; + if (unicode_is_inv_wchar(c)) + c = CONFIG_SUBST_WCHAR; + len = wcrtomb(buf, c, &mbst); if (len > 0) { buf[len] = '\0'; fputs(buf, stdout); @@ -238,7 +280,7 @@ static size_t load_string(const char *src, int maxsize) return strlen(command_ps); } # if ENABLE_FEATURE_TAB_COMPLETION -static void save_string(char *dst, int maxsize) +static void save_string(char *dst, unsigned maxsize) { safe_strncpy(dst, command_ps, maxsize); } @@ -1719,13 +1761,11 @@ static int lineedit_read_key(char *read_key_buffer) pushback: /* Invalid sequence. Save all "bad bytes" except first */ read_key_ungets(read_key_buffer, unicode_buf + 1, unicode_idx - 1); - /* - * ic = unicode_buf[0] sounds even better, but currently - * this does not work: wchar_t[] -> char[] conversion - * when lineedit finishes mangles such "raw bytes" - * (by misinterpreting them as unicode chars): - */ +# if !ENABLE_UNICODE_PRESERVE_BROKEN ic = CONFIG_SUBST_WCHAR; +# else + ic = unicode_mark_inv_wchar(unicode_buf[0]); +# endif } else { /* Valid unicode char, return its code */ ic = wc; diff --git a/libbb/unicode.c b/libbb/unicode.c index 83e70b412..d1c6167c7 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c @@ -423,7 +423,6 @@ static int wcwidth(unsigned ucs) # if LAST_SUPPORTED_WCHAR >= 0x300 /* sorted list of non-overlapping intervals of non-spacing characters */ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ - static const struct interval combining[] = { # define BIG_(a,b) { a, b }, # define PAIR(a,b) # define ARRAY /* PAIR if < 0x4000 and no more than 4 chars big */ \ @@ -557,10 +556,9 @@ static int wcwidth(unsigned ucs) BIG_(0xFE20, 0xFE23) \ BIG_(0xFEFF, 0xFEFF) \ BIG_(0xFFF9, 0xFFFB) - ARRAY + static const struct interval combining[] = { ARRAY }; # undef BIG_ # undef PAIR - }; # define BIG_(a,b) # define PAIR(a,b) (a << 2) | (b-a), static const uint16_t combining1[] = { ARRAY }; @@ -668,7 +666,6 @@ int FAST_FUNC unicode_bidi_isrtl(wint_t wc) * http://www.unicode.org/Public/5.2.0/ucd/extracted/DerivedBidiClass.txt * Bidi_Class=Left_To_Right | Bidi_Class=Arabic_Letter */ - static const struct interval rtl_b[] = { # define BIG_(a,b) { a, b }, # define PAIR(a,b) # define ARRAY \ @@ -723,10 +720,9 @@ int FAST_FUNC unicode_bidi_isrtl(wint_t wc) {0x10E7F, 0x10FFF}, {0x1E800, 0x1EFFF} */ - ARRAY + static const struct interval rtl_b[] = { ARRAY }; # undef BIG_ # undef PAIR - }; # define BIG_(a,b) # define PAIR(a,b) (a << 2) | (b-a), static const uint16_t rtl_p[] = { ARRAY }; @@ -755,7 +751,6 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc) * White_Space, Other_Neutral, European_Number, European_Separator, * European_Terminator, Arabic_Number, Common_Separator */ - static const struct interval neutral_b[] = { # define BIG_(a,b) { a, b }, # define PAIR(a,b) # define ARRAY \ @@ -929,10 +924,9 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc) {0x1F030, 0x1F093}, {0x1F100, 0x1F10A} */ - ARRAY + static const struct interval neutral_b[] = { ARRAY }; # undef BIG_ # undef PAIR - }; # define BIG_(a,b) # define PAIR(a,b) (a << 2) | (b-a), static const uint16_t neutral_p[] = { ARRAY }; diff --git a/testsuite/ash.tests b/testsuite/ash.tests index 6b2caf316..ce585beb1 100755 --- a/testsuite/ash.tests +++ b/testsuite/ash.tests @@ -7,8 +7,30 @@ . ./testing.sh +test -f "$bindir/.config" && . "$bindir/.config" + # testing "test name" "options" "expected result" "file input" "stdin" +if test x"$CONFIG_UNICODE_PRESERVE_BROKEN" = x"y"; then +testing "One byte which is not valid unicode char followed by valid input" \ + "script -q -c 'ash' /dev/null >/dev/null; cat ash.output" \ + "\ +00000000 ff 2d 0a |.-.| +00000003 +" \ + "" \ + "echo \xff- | hexdump -C >ash.output; exit; exit; exit; exit\n" + +testing "30 bytes which are not valid unicode chars followed by valid input" \ + "script -q -c 'ash' /dev/null >/dev/null; cat ash.output" \ + "\ +00000000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| +00000010 ff ff ff ff ff ff ff ff ff ff ff ff ff ff 2d 0a |..............-.| +00000020 +" \ + "" \ + "echo \xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff- | hexdump -C >ash.output; exit; exit; exit; exit\n" +else testing "One byte which is not valid unicode char followed by valid input" \ "script -q -c 'ash' /dev/null >/dev/null; cat ash.output" \ "\ @@ -27,6 +49,8 @@ testing "30 bytes which are not valid unicode chars followed by valid input" \ " \ "" \ "echo \xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff- | hexdump -C >ash.output; exit; exit; exit; exit\n" +fi + # Not sure this behavior is perfect: we lose all invalid input which precedes # arrow keys and such. In this example, \xff\xff are lost -- cgit v1.2.3-55-g6feb From d2844fcb6862c080177aaf314cc98d03e65b05ac Mon Sep 17 00:00:00 2001 From: Lauri Kasanen Date: Thu, 29 Apr 2010 22:20:57 +0200 Subject: swapon: skip noauto entries Signed-off-by: Lauri Kasanen Signed-off-by: Denys Vlasenko --- util-linux/swaponoff.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c index f647a32bc..f2f52fb88 100644 --- a/util-linux/swaponoff.c +++ b/util-linux/swaponoff.c @@ -66,11 +66,20 @@ static int do_em_all(void) bb_perror_msg_and_die("/etc/fstab"); err = 0; - while ((m = getmntent(f)) != NULL) - if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) - err += swap_enable_disable(m->mnt_fsname); + while ((m = getmntent(f)) != NULL) { + if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) { + /* swapon -a should ignore entries with noauto, + * but swapoff -a should process them */ + if (applet_name[5] != 'n' + || hasmntopt(m, MNTOPT_NOAUTO) == NULL + ) { + err += swap_enable_disable(m->mnt_fsname); + } + } + } - endmntent(f); + if (ENABLE_FEATURE_CLEAN_UP) + endmntent(f); return err; } -- cgit v1.2.3-55-g6feb From 0a2c793bd61540629d5686adb5afd2ada19d624f Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Fri, 30 Apr 2010 09:32:10 +0200 Subject: grep: fix -Fi function old new delta grep_file 1151 1169 +18 Signed-off-by: Ian Wienand Signed-off-by: Denys Vlasenko --- findutils/grep.c | 5 ++++- testsuite/grep.tests | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/findutils/grep.c b/findutils/grep.c index 40caef423..0f1c11abb 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -254,7 +254,10 @@ static int grep_file(FILE *file) while (pattern_ptr) { gl = (grep_list_data_t *)pattern_ptr->data; if (FGREP_FLAG) { - found |= (strstr(line, gl->pattern) != NULL); + found |= (((option_mask32 & OPT_i) + ? strcasestr(line, gl->pattern) + : strstr(line, gl->pattern) + ) != NULL); } else { if (!(gl->flg_mem_alocated_compiled & COMPILED)) { gl->flg_mem_alocated_compiled |= COMPILED; diff --git a/testsuite/grep.tests b/testsuite/grep.tests index 8692307dd..d4bf80d83 100755 --- a/testsuite/grep.tests +++ b/testsuite/grep.tests @@ -75,6 +75,8 @@ testing "grep handles multiple regexps" "grep -e one -e two input ; echo \$?" \ "one\ntwo\n0\n" "one\ntwo\n" "" testing "grep -F handles multiple expessions" "grep -F -e one -e two input ; echo \$?" \ "one\ntwo\n0\n" "one\ntwo\n" "" +testing "grep -F handles -i" "grep -F -i foo input ; echo \$?" \ + "FOO\n0\n" "FOO\n" "" # -f file/- testing "grep can read regexps from stdin" "grep -f - input ; echo \$?" \ -- cgit v1.2.3-55-g6feb From fde3fb3009765b273d4d717a7e4609ff7f9461ae Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 May 2010 14:17:07 +0200 Subject: udhcpd: fix hostname truncation bug 1663 Signed-off-by: Denys Vlasenko --- networking/udhcp/leases.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c index 4999d8079..fad71ec6c 100644 --- a/networking/udhcp/leases.c +++ b/networking/udhcp/leases.c @@ -60,6 +60,8 @@ struct dyn_lease* FAST_FUNC add_lease( memset(oldest, 0, sizeof(*oldest)); if (hostname) { char *p; + + hostname_len++; /* include NUL */ if (hostname_len > sizeof(oldest->hostname)) hostname_len = sizeof(oldest->hostname); p = safe_strncpy(oldest->hostname, hostname, hostname_len); -- cgit v1.2.3-55-g6feb From 43afd75ea8de1c891c3c0a520cbb117e3f1ad49e Mon Sep 17 00:00:00 2001 From: Souf Oued Date: Sun, 2 May 2010 18:45:02 +0200 Subject: rfkill: new applet function old new delta rfkill_main - 683 +683 packed_usage 26824 26966 +142 static.rfkill_types - 42 +42 applet_names 2216 2223 +7 applet_main 1300 1304 +4 applet_nameofs 650 652 +2 Signed-off-by: Souf Oued Signed-off-by: Denys Vlasenko --- include/applets.h | 1 + include/usage.h | 12 ++++++ miscutils/Config.in | 11 +++++ miscutils/Kbuild | 1 + miscutils/rfkill.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 miscutils/rfkill.c diff --git a/include/applets.h b/include/applets.h index 83c1792ac..ef5dd781d 100644 --- a/include/applets.h +++ b/include/applets.h @@ -321,6 +321,7 @@ IF_RENICE(APPLET(renice, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_RESET(APPLET(reset, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_RESIZE(APPLET(resize, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_RESTORECON(APPLET_ODDNAME(restorecon, setfiles, _BB_DIR_SBIN, _BB_SUID_DROP, restorecon)) +IF_RFKILL(APPLET(rfkill, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_RM(APPLET_NOFORK(rm, rm, _BB_DIR_BIN, _BB_SUID_DROP, rm)) IF_RMDIR(APPLET_NOFORK(rmdir, rmdir, _BB_DIR_BIN, _BB_SUID_DROP, rmdir)) IF_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_DROP)) diff --git a/include/usage.h b/include/usage.h index 38594811e..2c2a90d16 100644 --- a/include/usage.h +++ b/include/usage.h @@ -3738,6 +3738,18 @@ "\n for customizable files, or the user section," \ "\n if it has changed" \ +#define rfkill_trivial_usage \ + "COMMAND [INDEX|TYPE]" +#define rfkill_full_usage "\n\n" \ + "Enable/disable wireless devices\n" \ + "\nCommands:" \ + "\n list [INDEX|TYPE] List current state" \ + "\n block INDEX|TYPE Disable device" \ + "\n unblock INDEX|TYPE Enable device" \ + "\n" \ + "\n TYPE: all, wlan(wifi), bluetooth, uwb(ultrawideband)," \ + "\n wimax, wwan, gps, fm" \ + #define rm_trivial_usage \ "[OPTIONS] FILE..." #define rm_full_usage "\n\n" \ diff --git a/miscutils/Config.in b/miscutils/Config.in index 0469b6399..7a69dd10f 100644 --- a/miscutils/Config.in +++ b/miscutils/Config.in @@ -545,6 +545,17 @@ config READAHEAD As readahead(2) blocks until each file has been read, it is best to run this applet as a background job. +config RFKILL + bool "rfkill" + default n + help + Enable/disable wireless devices. + + rfkill list : list all wireless devices + rfkill list bluetooth : list all bluetooth devices + rfkill list 1 : list device corresponding to the given index + rfkill block|unblock wlan : block/unblock all wlan(wifi) devices + config RUNLEVEL bool "runlevel" default n diff --git a/miscutils/Kbuild b/miscutils/Kbuild index bbfa93dc7..3c8ce42ba 100644 --- a/miscutils/Kbuild +++ b/miscutils/Kbuild @@ -34,6 +34,7 @@ lib-$(CONFIG_MOUNTPOINT) += mountpoint.o lib-$(CONFIG_MT) += mt.o lib-$(CONFIG_RAIDAUTORUN) += raidautorun.o lib-$(CONFIG_READAHEAD) += readahead.o +lib-$(CONFIG_RFKILL) += rfkill.o lib-$(CONFIG_RUNLEVEL) += runlevel.o lib-$(CONFIG_RX) += rx.o lib-$(CONFIG_SETSID) += setsid.o diff --git a/miscutils/rfkill.c b/miscutils/rfkill.c new file mode 100644 index 000000000..0f5817b76 --- /dev/null +++ b/miscutils/rfkill.c @@ -0,0 +1,120 @@ +/* vi: set sw=4 ts=4: */ +/* +* rfkill implementation for busybox +* +* Copyright (C) 2010 Malek Degachi +* +* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. +*/ +#include "libbb.h" +#include + +enum { + OPT_b = (1 << 0), /* must be = 1 */ + OPT_u = (1 << 1), + OPT_l = (1 << 2), +}; + +int rfkill_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int rfkill_main(int argc UNUSED_PARAM, char **argv) +{ + struct rfkill_event event; + const char *rf_name; + int rf_fd; + int mode; + int rf_type; + int rf_idx; + unsigned rf_opt = 0; + + argv++; + /* Must have one or two params */ + if (!argv[0] || (argv[1] && argv[2])) + bb_show_usage(); + + mode = O_RDWR | O_NONBLOCK; + rf_name = argv[1]; + if (strcmp(argv[0], "list") == 0) { + rf_opt |= OPT_l; + mode = O_RDONLY | O_NONBLOCK; + } else if (strcmp(argv[0], "block") == 0 && rf_name) { + rf_opt |= OPT_b; + } else if (strcmp(argv[0], "unblock") == 0 && rf_name) { + rf_opt |= OPT_u; + } else + bb_show_usage(); + + rf_type = RFKILL_TYPE_ALL; + rf_idx = -1; + if (rf_name) { + static const char rfkill_types[] ALIGN1 = "all\0wlan\0bluetooth\0uwb\0wimax\0wwan\0gps\0fm\0"; + if (strcmp(rf_name, "wifi") == 0) + rf_name = "wlan"; + if (strcmp(rf_name, "ultrawideband") == 0) + rf_name = "uwb"; + rf_type = index_in_strings(rfkill_types, rf_name); + if (rf_type < 0) { + rf_idx = xatoi_u(rf_name); + } + } + + rf_fd = device_open("/dev/rfkill", mode); + if (rf_fd < 0) + bb_perror_msg_and_die("/dev/rfkill"); + + if (rf_opt & OPT_l) { + while (full_read(rf_fd, &event, sizeof(event)) == RFKILL_EVENT_SIZE_V1) { + parser_t *parser; + char *tokens[2]; + char rf_sysfs[sizeof("/sys/class/rfkill/rfkill%u/uevent") + sizeof(int)*3]; + char *name, *type; + + if (rf_type && rf_type != event.type && rf_idx < 0) { + continue; + } + + if (rf_idx >= 0 && event.idx != rf_idx) { + continue; + } + + name = NULL; + type = NULL; + sprintf(rf_sysfs, "/sys/class/rfkill/rfkill%u/uevent", event.idx); + parser = config_open2(rf_sysfs, fopen_for_read); + while (config_read(parser, tokens, 2, 2, "\n=", PARSE_NORMAL)) { + if (strcmp(tokens[0], "RFKILL_NAME") == 0) { + name = xstrdup(tokens[1]); + continue; + } + if (strcmp(tokens[0], "RFKILL_TYPE") == 0) { + type = xstrdup(tokens[1]); + continue; + } + } + config_close(parser); + + printf("%u: %s: %s\n", event.idx, name, type); + printf("\tSoft blocked: %s\n", event.soft ? "yes" : "no"); + printf("\tHard blocked: %s\n", event.hard ? "yes" : "no"); + free(name); + free(type); + } + } else { + memset(&event, 0, sizeof(event)); + if (rf_type >= 0) { + event.type = rf_type; + event.op = RFKILL_OP_CHANGE_ALL; + } + + if (rf_idx >= 0) { + event.idx = rf_idx; + event.op = RFKILL_OP_CHANGE; + } + + /* Note: OPT_b == 1 */ + event.soft = (rf_opt & OPT_b); + + xwrite(rf_fd, &event, sizeof(event)); + } + + return EXIT_SUCCESS; +} -- cgit v1.2.3-55-g6feb From 78abf88dcc5d39ef3a36477300ed00a730ce6daa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 May 2010 20:30:28 +0200 Subject: ifdown: use /var/run/udhcpc.%iface%.pid only if it exists Signed-off-by: Denys Vlasenko --- networking/ifupdown.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/networking/ifupdown.c b/networking/ifupdown.c index bf88b1c19..2f3dd1d7b 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -573,8 +573,10 @@ static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) { int result; - result = execute("kill " - "`cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec); + result = execute( + "test -f /var/run/udhcpc.%iface%.pid && " + "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", + ifd, exec); /* Also bring the hardware interface down since killing the dhcp client alone doesn't do it. This enables consecutive ifup->ifdown->ifup */ -- cgit v1.2.3-55-g6feb From fe360480aa30adf776a06dc9f09c704abcfa9000 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 May 2010 14:59:01 +0200 Subject: fix typo in commented-out code Signed-off-by: Denys Vlasenko --- procps/ps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/procps/ps.c b/procps/ps.c index b82c126d2..c3b200866 100644 --- a/procps/ps.c +++ b/procps/ps.c @@ -142,7 +142,7 @@ static unsigned get_kernel_HZ(void) if (kernel_HZ == (unsigned)-1) kernel_HZ = get_HZ_by_waiting(); - //if (open_read_close("/proc/uptime", buf, sizeof(buf) <= 0) + //if (open_read_close("/proc/uptime", buf, sizeof(buf)) <= 0) // bb_perror_msg_and_die("can't read %s", "/proc/uptime"); //buf[sizeof(buf)-1] = '\0'; ///sscanf(buf, "%llu", &seconds_since_boot); -- cgit v1.2.3-55-g6feb From ff027d6f50bfa24228e230b84a3297c51d37d000 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 May 2010 15:45:25 +0200 Subject: bootchartd: new applet Usage: bootchartd start [PROG ARGS]|init|stop Create /var/log/bootchart.tgz with boot chart data Options: start: start background logging; with PROG, run PROG, then kill logging with USR1 stop: send USR1 to all bootchartd processes init: start background logging; stop when getty/gdm is seen (for init scripts) Under PID 1: as init, then exec $bootchart_init, /init, /sbin/init function old new delta bootchartd_main - 907 +907 dump_procs - 353 +353 packed_usage 26566 26735 +169 dump_file - 91 +91 static.dirs - 23 +23 applet_names 2176 2187 +11 applet_main 1284 1288 +4 applet_nameofs 642 644 +2 ------------------------------------------------------------------------------ (add/remove: 5/0 grow/shrink: 4/0 up/down: 1560/0) Total: 1560 bytes Signed-off-by: Denys Vlasenko --- include/applets.h | 1 + include/usage.h | 34 ++++-- init/Config.in | 14 +++ init/Kbuild | 7 +- init/bootchartd.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 396 insertions(+), 15 deletions(-) create mode 100644 init/bootchartd.c diff --git a/include/applets.h b/include/applets.h index ef5dd781d..dfb20b9be 100644 --- a/include/applets.h +++ b/include/applets.h @@ -83,6 +83,7 @@ IF_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_DROP)) //IF_BBSH(APPLET(bbsh, _BB_DIR_BIN, _BB_SUID_DROP)) IF_BEEP(APPLET(beep, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_BLKID(APPLET(blkid, _BB_DIR_SBIN, _BB_SUID_DROP)) +IF_BOOTCHARTD(APPLET(bootchartd, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_BRCTL(APPLET(brctl, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_BUNZIP2(APPLET(bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP, bzcat)) diff --git a/include/usage.h b/include/usage.h index 2c2a90d16..636d01943 100644 --- a/include/usage.h +++ b/include/usage.h @@ -154,18 +154,15 @@ "\n -r Repetitions" \ "\n -n Start new tone" \ -#define fbsplash_trivial_usage \ - "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD]" -#define fbsplash_full_usage "\n\n" \ - "Options:" \ - "\n -s Image" \ - "\n -c Hide cursor" \ - "\n -d Framebuffer device (default /dev/fb0)" \ - "\n -i Config file (var=value):" \ - "\n BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT" \ - "\n BAR_R,BAR_G,BAR_B" \ - "\n -f Control pipe (else exit after drawing image)" \ - "\n commands: 'NN' (% for progress bar) or 'exit'" \ +#define bootchartd_trivial_usage \ + "start [PROG ARGS]|stop|init" +#define bootchartd_full_usage "\n\n" \ + "Create /var/log/bootchart.tgz with boot chart data\n" \ + "\nOptions:" \ + "\nstart: start background logging; with PROG, run PROG, then kill logging with USR1" \ + "\nstop: send USR1 to all bootchartd processes" \ + "\ninit: start background logging; stop when getty/xdm is seen (for init scripts)" \ + "\nUnder PID 1: as init, then exec $bootchart_init, /init, /sbin/init" \ #define brctl_trivial_usage \ "COMMAND [BRIDGE [INTERFACE]]" @@ -1174,6 +1171,19 @@ "$ echo $?\n" \ "1\n" +#define fbsplash_trivial_usage \ + "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD]" +#define fbsplash_full_usage "\n\n" \ + "Options:" \ + "\n -s Image" \ + "\n -c Hide cursor" \ + "\n -d Framebuffer device (default /dev/fb0)" \ + "\n -i Config file (var=value):" \ + "\n BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT" \ + "\n BAR_R,BAR_G,BAR_B" \ + "\n -f Control pipe (else exit after drawing image)" \ + "\n commands: 'NN' (% for progress bar) or 'exit'" \ + #define fbset_trivial_usage \ "[OPTIONS] [MODE]" #define fbset_full_usage "\n\n" \ diff --git a/init/Config.in b/init/Config.in index 3d99d4792..76d509207 100644 --- a/init/Config.in +++ b/init/Config.in @@ -120,4 +120,18 @@ config MESG Mesg controls access to your terminal by others. It is typically used to allow or disallow other users to write to your terminal +config BOOTCHARTD + bool "bootchartd" + default n + help + bootchartd is commonly used to profile the boot process + for the purpose of speeding it up. In this case, it is started + by the kernel as the init process. This is configured by adding + the init=/sbin/bootchartd option to the kernel command line. + + It can also be used to monitor the resource usage of a specific + application or the running system in general. In this case, + bootchartd is started interactively by running bootchartd start + and stopped using bootchartd stop. + endmenu diff --git a/init/Kbuild b/init/Kbuild index c060f3af4..ce3f30256 100644 --- a/init/Kbuild +++ b/init/Kbuild @@ -5,6 +5,7 @@ # Licensed under the GPL v2, see the file LICENSE in this tarball. lib-y:= -lib-$(CONFIG_HALT) += halt.o -lib-$(CONFIG_INIT) += init.o -lib-$(CONFIG_MESG) += mesg.o +lib-$(CONFIG_HALT) += halt.o +lib-$(CONFIG_INIT) += init.o +lib-$(CONFIG_MESG) += mesg.o +lib-$(CONFIG_BOOTCHARTD) += bootchartd.o diff --git a/init/bootchartd.c b/init/bootchartd.c new file mode 100644 index 000000000..fccaaceb4 --- /dev/null +++ b/init/bootchartd.c @@ -0,0 +1,355 @@ +/* vi: set sw=4 ts=4: */ +/* + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + */ +#include "libbb.h" +#include +#ifndef MS_SILENT +# define MS_SILENT (1 << 15) +#endif +#ifndef MNT_DETACH +# define MNT_DETACH 0x00000002 +#endif + +#define BC_VERSION_STR "0.8" + +/* For debugging, set to 0: + * strace won't work with DO_SIGNAL_SYNC set to 1. + */ +#define DO_SIGNAL_SYNC 1 + + +//Not supported: $PWD/bootchartd.conf and /etc/bootchartd.conf + +//# tmpfs size +//# (32 MB should suffice for ~20 minutes worth of log data, but YMMV) +//TMPFS_SIZE=32m +// +//# Sampling period (in seconds) +//SAMPLE_PERIOD=0.2 +// +//# Whether to enable and store BSD process accounting information. The +//# kernel needs to be configured to enable v3 accounting +//# (CONFIG_BSD_PROCESS_ACCT_V3). accton from the GNU accounting utilities +//# is also required. +//PROCESS_ACCOUNTING="no" +// +//# Tarball for the various boot log files +//BOOTLOG_DEST=/var/log/bootchart.tgz +// +//# Whether to automatically stop logging as the boot process completes. +//# The logger will look for known processes that indicate bootup completion +//# at a specific runlevel (e.g. gdm-binary, mingetty, etc.). +//AUTO_STOP_LOGGER="yes" +// +//# Whether to automatically generate the boot chart once the boot logger +//# completes. The boot chart will be generated in $AUTO_RENDER_DIR. +//# Note that the bootchart package must be installed. +//AUTO_RENDER="no" +// +//# Image format to use for the auto-generated boot chart +//# (choose between png, svg and eps). +//AUTO_RENDER_FORMAT="png" +// +//# Output directory for auto-generated boot charts +//AUTO_RENDER_DIR="/var/log" + + +/* Globals */ +struct globals { + char jiffy_line[sizeof(bb_common_bufsiz1)]; +} FIX_ALIASING; +#define G (*(struct globals*)&bb_common_bufsiz1) +#define INIT_G() do { } while (0) + +static void dump_file(FILE *fp, const char *filename) +{ + int fd = open(filename, O_RDONLY); + if (fd >= 0) { + fputs(G.jiffy_line, fp); + fflush(fp); + bb_copyfd_eof(fd, fileno(fp)); + close(fd); + fputc('\n', fp); + } +} + +static int dump_procs(FILE *fp, int look_for_login_process) +{ + struct dirent *entry; + DIR *dir = opendir("/proc"); + int found_login_process = 0; + + fputs(G.jiffy_line, fp); + while ((entry = readdir(dir)) != NULL) { + char name[sizeof("/proc/%u/cmdline") + sizeof(int)*3]; + int stat_fd; + unsigned pid = bb_strtou(entry->d_name, NULL, 10); + if (errno) + continue; + + /* Android's version reads /proc/PID/cmdline and extracts + * non-truncated process name. Do we want to do that? */ + + sprintf(name, "/proc/%u/stat", pid); + stat_fd = open(name, O_RDONLY); + if (stat_fd >= 0) { + char *p; + char stat_line[4*1024]; + int rd = safe_read(stat_fd, stat_line, sizeof(stat_line)-2); + + close(stat_fd); + if (rd < 0) + continue; + stat_line[rd] = '\0'; + p = strchrnul(stat_line, '\n'); + *p++ = '\n'; + *p = '\0'; + fputs(stat_line, fp); + if (!look_for_login_process) + continue; + p = strchr(stat_line, '('); + if (!p) + continue; + p++; + strchrnul(p, ')')[0] = '\0'; + /* If is gdm, kdm or a getty? */ + if (((p[0] == 'g' || p[0] == 'k' || p[0] == 'x') && p[1] == 'd' && p[2] == 'm') + || strstr(p, "getty") + ) { + found_login_process = 1; + } + } + } + closedir(dir); + fputc('\n', fp); + return found_login_process; +} + +static char *make_tempdir(const char *prog) +{ + char template[] = "/tmp/bootchart.XXXXXX"; + char *tempdir = xstrdup(mkdtemp(template)); + if (!tempdir) { + /* /tmp is not writable (happens when we are used as init). + * Try to mount a tmpfs, them cd and lazily unmount it. + * Since we unmount it at once, we can mount it anywhere. + * Try a few locations which are likely ti exist. + */ + static const char dirs[] = "/mnt\0""/tmp\0""/boot\0""/proc\0"; + const char *try_dir = dirs; + while (mount("none", try_dir, "tmpfs", MS_SILENT, "size=16m") != 0) { + try_dir += strlen(try_dir) + 1; + if (!try_dir[0]) + bb_perror_msg_and_die("can't %smount tmpfs", ""); + } + //bb_error_msg("mounted tmpfs on %s", try_dir); + xchdir(try_dir); + if (umount2(try_dir, MNT_DETACH) != 0) { + bb_perror_msg_and_die("can't %smount tmpfs", "un"); + } + } else { + xchdir(tempdir); + } + { + FILE *header_fp = xfopen("header", "w"); + if (prog) + fprintf(header_fp, "profile.process = %s\n", prog); + fputs("version = "BC_VERSION_STR"\n", header_fp); + fclose(header_fp); + } + + return tempdir; +} + +static void do_logging(void) +{ + //# Enable process accounting if configured + //if [ "$PROCESS_ACCOUNTING" = "yes" ]; then + // [ -e kernel_pacct ] || : > kernel_pacct + // accton kernel_pacct + //fi + + FILE *proc_stat = xfopen("proc_stat.log", "w"); + FILE *proc_diskstats = xfopen("proc_diskstats.log", "w"); + //FILE *proc_netdev = xfopen("proc_netdev.log", "w"); + FILE *proc_ps = xfopen("proc_ps.log", "w"); + int look_for_login_process = (getppid() == 1); + unsigned count = 60*1000*1000 / 200*1000; /* ~1 minute */ + + while (--count && !bb_got_signal) { + char *p; + int len = open_read_close("/proc/uptime", G.jiffy_line, sizeof(G.jiffy_line)-2); + if (len < 0) + goto wait_more; + /* /proc/uptime has format "NNNNNN.MM NNNNNNN.MM" */ + /* we convert it to "NNNNNNMM\n" (using first value) */ + G.jiffy_line[len] = '\0'; + p = strchr(G.jiffy_line, '.'); + if (!p) + goto wait_more; + while (isdigit(*++p)) + p[-1] = *p; + p[-1] = '\n'; + p[0] = '\0'; + + dump_file(proc_stat, "/proc/stat"); + dump_file(proc_diskstats, "/proc/diskstats"); + //dump_file(proc_netdev, "/proc/net/dev"); + if (dump_procs(proc_ps, look_for_login_process)) { + /* dump_procs saw a getty or {g,k,x}dm + * stop logging in 2 seconds: + */ + if (count > 2*1000*1000 / 200*1000) + count = 2*1000*1000 / 200*1000; + } + fflush_all(); + wait_more: + usleep(200*1000); + } + + // [ -e kernel_pacct ] && accton off +} + +static void finalize(char *tempdir) +{ + //# Stop process accounting if configured + //local pacct= + //[ -e kernel_pacct ] && pacct=kernel_pacct + + //( + // echo "version = $VERSION" + // echo "title = Boot chart for $( hostname | sed q ) ($( date ))" + // echo "system.uname = $( uname -srvm | sed q )" + // echo "system.release = $( sed q /etc/SuSE-release )" + // echo "system.cpu = $( grep '^model name' /proc/cpuinfo | sed q ) ($cpucount)" + // echo "system.kernel.options = $( sed q /proc/cmdline )" + //) >> header + + /* Package log files */ + system("tar -zcf /var/log/bootchart.tgz header *.log"); // + $pacct + /* Clean up (if we are not in detached tmpfs) */ + if (tempdir) { + unlink("header"); + unlink("proc_stat.log"); + unlink("proc_diskstats.log"); + //unlink("proc_netdev.log"); + unlink("proc_ps.log"); + rmdir(tempdir); + } + + /* shell-based bootchartd tries to run /usr/bin/bootchart if $AUTO_RENDER=yes: + * /usr/bin/bootchart -o "$AUTO_RENDER_DIR" -f $AUTO_RENDER_FORMAT "$BOOTLOG_DEST" + */ +} + +/* Usage: + * bootchartd start [PROG ARGS]: start logging in background, USR1 stops it. + * With PROG, runs PROG, then kills background logging. + * bootchartd stop: same as "killall -USR1 bootchartd" + * bootchartd init: start logging in background + * Stop when getty/gdm is seen (if AUTO_STOP_LOGGER = yes). + * Meant to be used from init scripts. + * bootchartd (pid==1): as init, but then execs $bootchart_init, /init, /sbin/init + * Meant to be used as kernel's init process. + */ +int bootchartd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int bootchartd_main(int argc UNUSED_PARAM, char **argv) +{ + pid_t parent_pid, logger_pid; + smallint cmd; + enum { + CMD_STOP = 0, + CMD_START, + CMD_INIT, + CMD_PID1, /* used to mark pid 1 case */ + }; + + INIT_G(); + + parent_pid = getpid(); + if (argv[1]) { + cmd = index_in_strings("stop\0""start\0""init\0", argv[1]); + if (cmd < 0) + bb_show_usage(); + if (cmd == CMD_STOP) { + pid_t *pidList = find_pid_by_name("bootchartd"); + while (*pidList != 0) { + if (*pidList != parent_pid) + kill(*pidList, SIGUSR1); + pidList++; + } + return EXIT_SUCCESS; + } + } else { + if (parent_pid != 1) + bb_show_usage(); + cmd = CMD_PID1; + } + + /* Here we are in START or INIT state. Create logger child: */ + logger_pid = fork_or_rexec(argv); + + if (logger_pid == 0) { /* child */ + char *tempdir; + + bb_signals(0 + + (1 << SIGUSR1) + + (1 << SIGUSR2) + + (1 << SIGTERM) + + (1 << SIGQUIT) + + (1 << SIGINT) + + (1 << SIGHUP) + , record_signo); + + if (DO_SIGNAL_SYNC) + /* Inform parent that we are ready */ + raise(SIGSTOP); + + /* If we started by kernel, PATH might be not set. + * And in order to run tar we may need PATH to be set: + */ + if (cmd == CMD_PID1 && !getenv("PATH")) + putenv((char*)bb_PATH_root_path); + tempdir = make_tempdir(cmd == CMD_START ? argv[2] : NULL); + do_logging(); + finalize(tempdir); + return EXIT_SUCCESS; + } + + /* parent */ + + if (DO_SIGNAL_SYNC) { + /* Wait for logger child to set handlers, then unpause it. + * Otherwise with short-lived PROG (e.g. "bootchartd start true") + * we might send SIGUSR1 before logger sets its handler. + */ + waitpid(logger_pid, NULL, WUNTRACED); + kill(logger_pid, SIGCONT); + } + + if (cmd == CMD_PID1) { + char *bootchart_init = getenv("bootchart_init"); + if (bootchart_init) + execl(bootchart_init, bootchart_init, NULL); + execl("/init", "init", NULL); + execl("/sbin/init", "init", NULL); + bb_perror_msg_and_die("can't exec '%s'", "/sbin/init"); + } + + if (cmd == CMD_START && argv[2]) { /* "start PROG ARGS" */ + pid_t pid = vfork(); + if (pid < 0) + bb_perror_msg_and_die("vfork"); + if (pid == 0) { /* child */ + argv += 2; + execvp(argv[0], argv); + bb_perror_msg_and_die("can't exec '%s'", argv[0]); + } + /* parent */ + waitpid(pid, NULL, 0); + kill(logger_pid, SIGUSR1); + } + + return EXIT_SUCCESS; +} -- cgit v1.2.3-55-g6feb From e7f1e5ca1de60db1336f0ec85b1c9df55f6402b7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 May 2010 17:34:37 +0200 Subject: bootchartd: add missing parenthesis Signed-off-by: Denys Vlasenko --- init/bootchartd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/init/bootchartd.c b/init/bootchartd.c index fccaaceb4..9c43e3388 100644 --- a/init/bootchartd.c +++ b/init/bootchartd.c @@ -175,7 +175,7 @@ static void do_logging(void) //FILE *proc_netdev = xfopen("proc_netdev.log", "w"); FILE *proc_ps = xfopen("proc_ps.log", "w"); int look_for_login_process = (getppid() == 1); - unsigned count = 60*1000*1000 / 200*1000; /* ~1 minute */ + unsigned count = 60*1000*1000 / (200*1000); /* ~1 minute */ while (--count && !bb_got_signal) { char *p; @@ -200,8 +200,8 @@ static void do_logging(void) /* dump_procs saw a getty or {g,k,x}dm * stop logging in 2 seconds: */ - if (count > 2*1000*1000 / 200*1000) - count = 2*1000*1000 / 200*1000; + if (count > 2*1000*1000 / (200*1000)) + count = 2*1000*1000 / (200*1000); } fflush_all(); wait_more: -- cgit v1.2.3-55-g6feb From b8ba6b66f5d730efcf13dbbb3f9362dd6840d93b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 May 2010 00:40:15 +0200 Subject: bootchartd: better wording in comment Signed-off-by: Denys Vlasenko --- init/bootchartd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/init/bootchartd.c b/init/bootchartd.c index 9c43e3388..9faf14d36 100644 --- a/init/bootchartd.c +++ b/init/bootchartd.c @@ -306,11 +306,12 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv) /* Inform parent that we are ready */ raise(SIGSTOP); - /* If we started by kernel, PATH might be not set. - * And in order to run tar we may need PATH to be set: + /* If we are started by kernel, PATH might be unset. + * In order to find "tar", let's set some sane PATH: */ if (cmd == CMD_PID1 && !getenv("PATH")) putenv((char*)bb_PATH_root_path); + tempdir = make_tempdir(cmd == CMD_START ? argv[2] : NULL); do_logging(); finalize(tempdir); -- cgit v1.2.3-55-g6feb From 27653adc8b7ebe44bd357511de53d0c14eef0894 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 May 2010 14:19:19 +0000 Subject: rpm: code shrink. Now uses open_zipped's logic (factored out into setup_unzip_on_fd()) function old new delta setup_unzip_on_fd - 80 +80 open_zipped 176 113 -63 rpm_main 1672 1355 -317 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/2 up/down: 80/-380) Total: -300 bytes Signed-off-by: Denys Vlasenko --- archival/rpm.c | 97 +++++++++++++++++------------------------------------ archival/rpm.h | 38 +++++++++++++++++++++ archival/rpm2cpio.c | 69 ++++++++++++++++--------------------- include/libbb.h | 9 +++++ libbb/read.c | 97 ++++++++++++++++++++++++++++++----------------------- 5 files changed, 161 insertions(+), 149 deletions(-) create mode 100644 archival/rpm.h diff --git a/archival/rpm.c b/archival/rpm.c index 6c1e341cd..77679c275 100644 --- a/archival/rpm.c +++ b/archival/rpm.c @@ -9,8 +9,8 @@ #include "libbb.h" #include "unarchive.h" +#include "rpm.h" -#define RPM_HEADER_MAGIC "\216\255\350" #define RPM_CHAR_TYPE 1 #define RPM_INT8_TYPE 2 #define RPM_INT16_TYPE 3 @@ -46,6 +46,7 @@ #define TAG_DIRINDEXES 1116 #define TAG_BASENAMES 1117 #define TAG_DIRNAMES 1118 + #define RPMFILE_CONFIG (1 << 0) #define RPMFILE_DOC (1 << 1) @@ -147,8 +148,14 @@ int rpm_main(int argc, char **argv) time_t bdate_time; struct tm *bdate_ptm; char bdatestring[50]; - printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_PREFIXS, 0) ? rpm_getstr(TAG_PREFIXS, 0) : "(not relocateable)"); - printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_VENDOR, 0) ? rpm_getstr(TAG_VENDOR, 0) : "(none)"); + const char *p; + + p = rpm_getstr(TAG_PREFIXS, 0); + if (!p) p = "(not relocateable)"; + printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), p); + p = rpm_getstr(TAG_VENDOR, 0); + if (!p) p = "(none)"; + printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), p); bdate_time = rpm_getint(TAG_BUILDTIME, 0); bdate_ptm = localtime(&bdate_time); strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); @@ -190,20 +197,15 @@ int rpm_main(int argc, char **argv) static void extract_cpio_gz(int fd) { archive_handle_t *archive_handle; - unsigned char magic[2]; -#if BB_MMU - IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); - enum { xformer_prog = 0 }; -#else - enum { xformer = 0 }; - const char *xformer_prog; -#endif /* Initialize */ archive_handle = init_handle(); archive_handle->seek = seek_by_read; - //archive_handle->action_header = header_list; archive_handle->action_data = data_extract_all; +#if 0 /* For testing (rpm -i only lists the files in internal cpio): */ + archive_handle->action_header = header_list; + archive_handle->action_data = data_skip; +#endif archive_handle->ah_flags = ARCHIVE_RESTORE_DATE | ARCHIVE_CREATE_LEADING_DIRS /* compat: overwrite existing files. * try "rpm -i foo.src.rpm" few times in a row - @@ -213,46 +215,15 @@ static void extract_cpio_gz(int fd) archive_handle->src_fd = fd; /*archive_handle->offset = 0; - init_handle() did it */ -// TODO: open_zipped does the same - - xread(archive_handle->src_fd, &magic, 2); -#if BB_MMU - xformer = unpack_gz_stream; -#else - xformer_prog = "gunzip"; -#endif - if (magic[0] != 0x1f || magic[1] != 0x8b) { - if (!ENABLE_FEATURE_SEAMLESS_BZ2 - || magic[0] != 'B' || magic[1] != 'Z' - ) { - bb_error_msg_and_die("no gzip" - IF_FEATURE_SEAMLESS_BZ2("/bzip2") - " magic"); - } -#if BB_MMU - xformer = unpack_bz2_stream; -#else - xformer_prog = "bunzip2"; -#endif - } else { -#if !BB_MMU - /* NOMMU version of open_transformer execs an external unzipper that should - * have the file position at the start of the file */ - xlseek(archive_handle->src_fd, 0, SEEK_SET); -#endif - } - xchdir("/"); /* Install RPM's to root */ - open_transformer(archive_handle->src_fd, xformer, xformer_prog); - archive_handle->offset = 0; + setup_unzip_on_fd(archive_handle->src_fd /*, fail_if_not_detected: 1*/); while (get_header_cpio(archive_handle) == EXIT_SUCCESS) continue; } - static rpm_index **rpm_gettags(int fd, int *num_tags) { - /* We should never need mode than 200, and realloc later */ + /* We should never need more than 200 (shrink via realloc later) */ rpm_index **tags = xzalloc(200 * sizeof(tags[0])); int pass, tagindex = 0; @@ -260,27 +231,16 @@ static rpm_index **rpm_gettags(int fd, int *num_tags) /* 1st pass is the signature headers, 2nd is the main stuff */ for (pass = 0; pass < 2; pass++) { - struct { - char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */ - uint8_t version; /* 1 byte version number */ - uint32_t reserved; /* 4 bytes reserved */ - uint32_t entries; /* Number of entries in header (4 bytes) */ - uint32_t size; /* Size of store (4 bytes) */ - } header; - struct BUG_header { - char BUG_header[sizeof(header) == 16 ? 1 : -1]; - }; + struct rpm_header header; rpm_index *tmpindex; int storepos; xread(fd, &header, sizeof(header)); - if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) - return NULL; /* Invalid magic */ - if (header.version != 1) - return NULL; /* This program only supports v1 headers */ + if (header.magic_and_ver != htonl(RPM_HEADER_MAGICnVER)) + return NULL; /* Invalid magic, or not version 1 */ header.size = ntohl(header.size); header.entries = ntohl(header.entries); - storepos = xlseek(fd,0,SEEK_CUR) + header.entries * 16; + storepos = xlseek(fd, 0, SEEK_CUR) + header.entries * 16; while (header.entries--) { tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); @@ -292,14 +252,16 @@ static rpm_index **rpm_gettags(int fd, int *num_tags) if (pass == 0) tmpindex->tag -= 743; } - xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ + storepos = xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ /* Skip padding to 8 byte boundary after reading signature headers */ if (pass == 0) - xlseek(fd, (8 - (xlseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); + xlseek(fd, (-storepos) & 0x7, SEEK_CUR); } - tags = xrealloc(tags, tagindex * sizeof(tags[0])); /* realloc tags to save space */ + /* realloc tags to save space */ + tags = xrealloc(tags, tagindex * sizeof(tags[0])); *num_tags = tagindex; - return tags; /* All done, leave the file at the start of the gzipped cpio archive */ + /* All done, leave the file at the start of the gzipped cpio archive */ + return tags; } static int bsearch_rpmtag(const void *key, const void *item) @@ -324,10 +286,13 @@ static char *rpm_getstr(int tag, int itemindex) found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); if (!found || itemindex >= found[0]->count) return NULL; - if (found[0]->type == RPM_STRING_TYPE || found[0]->type == RPM_I18NSTRING_TYPE || found[0]->type == RPM_STRING_ARRAY_TYPE) { + if (found[0]->type == RPM_STRING_TYPE + || found[0]->type == RPM_I18NSTRING_TYPE + || found[0]->type == RPM_STRING_ARRAY_TYPE + ) { int n; char *tmpstr = (char *) map + found[0]->offset; - for (n=0; n < itemindex; n++) + for (n = 0; n < itemindex; n++) tmpstr = tmpstr + strlen(tmpstr) + 1; return tmpstr; } diff --git a/archival/rpm.h b/archival/rpm.h new file mode 100644 index 000000000..f7c6fc2fa --- /dev/null +++ b/archival/rpm.h @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * RPM structs and consts + * + * Copyright (C) 2001 by Laurence Anderson + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + */ + +/* RPM file starts with this struct: */ +struct rpm_lead { + uint32_t magic; + uint8_t major, minor; + uint16_t type; + uint16_t archnum; + char name[66]; + uint16_t osnum; + uint16_t signature_type; + char reserved[16]; +}; +struct BUG_rpm_lead { + char bug[sizeof(struct rpm_lead) == 96 ? 1 : -1]; +}; +#define RPM_LEAD_MAGIC 0xedabeedb +#define RPM_LEAD_MAGIC_STR "\355\253\356\333" + +/* Then follows the header: */ +struct rpm_header { + uint32_t magic_and_ver; /* 3 byte magic: 0x8e 0xad 0xe8; 1 byte version: 0x01 */ + uint32_t reserved; /* 4 bytes reserved */ + uint32_t entries; /* Number of entries in header (4 bytes) */ + uint32_t size; /* Size of store (4 bytes) */ +}; +struct BUG_rpm_header { + char bug[sizeof(struct rpm_header) == 16 ? 1 : -1]; +}; +#define RPM_HEADER_MAGICnVER 0x8eade801 +#define RPM_HEADER_MAGIC_STR "\216\255\350" diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c index 5403aee02..4ed5b023b 100644 --- a/archival/rpm2cpio.c +++ b/archival/rpm2cpio.c @@ -8,30 +8,7 @@ */ #include "libbb.h" #include "unarchive.h" - -#define RPM_MAGIC 0xedabeedb -#define RPM_MAGIC_STR "\355\253\356\333" - -struct rpm_lead { - uint32_t magic; - uint8_t major, minor; - uint16_t type; - uint16_t archnum; - char name[66]; - uint16_t osnum; - uint16_t signature_type; - char reserved[16]; -}; - -#define RPM_HEADER_MAGICnVER 0x8eade801 -#define RPM_HEADER_MAGIC_STR "\216\255\350" - -struct rpm_header { - uint32_t magic_and_ver; /* 3 byte magic: 0x8e 0xad 0xe8; 1 byte version */ - uint32_t reserved; /* 4 bytes reserved */ - uint32_t entries; /* Number of entries in header (4 bytes) */ - uint32_t size; /* Size of store (4 bytes) */ -}; +#include "rpm.h" enum { rpm_fd = STDIN_FILENO }; @@ -65,8 +42,6 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) { struct rpm_lead lead; unsigned pos; - unsigned char magic[2]; - IF_DESKTOP(long long) int FAST_FUNC (*unpack)(int src_fd, int dst_fd); if (argv[1]) { xmove_fd(xopen(argv[1], O_RDONLY), rpm_fd); @@ -74,33 +49,45 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) xread(rpm_fd, &lead, sizeof(lead)); /* Just check the magic, the rest is irrelevant */ - if (lead.magic != htonl(RPM_MAGIC)) { + if (lead.magic != htonl(RPM_LEAD_MAGIC)) { bb_error_msg_and_die("invalid RPM magic"); } /* Skip the signature header, align to 8 bytes */ pos = skip_header(); - seek_by_jump(rpm_fd, (8 - pos) & 7); + seek_by_jump(rpm_fd, (-(int)pos) & 7); /* Skip the main header */ skip_header(); - xread(rpm_fd, &magic, 2); - unpack = unpack_gz_stream; - if (magic[0] != 0x1f || magic[1] != 0x8b) { - if (!ENABLE_FEATURE_SEAMLESS_BZ2 - || magic[0] != 'B' || magic[1] != 'Z' - ) { - bb_error_msg_and_die("invalid gzip" - IF_FEATURE_SEAMLESS_BZ2("/bzip2") - " magic"); +#if 0 + /* This works, but doesn't report uncompress errors (they happen in child) */ + setup_unzip_on_fd(rpm_fd /*fail_if_not_detected: 1*/); + if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0) + bb_error_msg_and_die("error unpacking"); +#else + /* BLOAT */ + { + unsigned char magic[2]; + IF_DESKTOP(long long) int FAST_FUNC (*unpack)(int src_fd, int dst_fd); + + xread(rpm_fd, &magic, 2); + unpack = unpack_gz_stream; + if (magic[0] != 0x1f || magic[1] != 0x8b) { + if (!ENABLE_FEATURE_SEAMLESS_BZ2 + || magic[0] != 'B' || magic[1] != 'Z' + ) { + bb_error_msg_and_die("invalid gzip" + IF_FEATURE_SEAMLESS_BZ2("/bzip2") + " magic"); + } + unpack = unpack_bz2_stream; } - unpack = unpack_bz2_stream; - } - if (unpack(rpm_fd, STDOUT_FILENO) < 0) { - bb_error_msg_and_die("error unpacking"); + if (unpack(rpm_fd, STDOUT_FILENO) < 0) + bb_error_msg_and_die("error unpacking"); } +#endif if (ENABLE_FEATURE_CLEAN_UP) { close(rpm_fd); diff --git a/include/libbb.h b/include/libbb.h index 976120e72..2f67c7f72 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -651,6 +651,15 @@ extern char *xmalloc_reads(int fd, char *pfx, size_t *maxsz_p) FAST_FUNC; extern void *xmalloc_read(int fd, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; /* Returns NULL if file can't be opened (default max size: INT_MAX - 4095) */ extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; +/* Autodetects gzip/bzip2 formats. fd may be in the middle of the file! */ +#if ENABLE_FEATURE_SEAMLESS_LZMA \ + || ENABLE_FEATURE_SEAMLESS_BZ2 \ + || ENABLE_FEATURE_SEAMLESS_GZ \ + /* || ENABLE_FEATURE_SEAMLESS_Z */ +extern int setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) FAST_FUNC; +#else +# define setup_unzip_on_fd(...) ((void)0) +#endif /* Autodetects .gz etc */ extern int open_zipped(const char *fname) FAST_FUNC; extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; diff --git a/libbb/read.c b/libbb/read.c index 06ce29718..503216eb5 100644 --- a/libbb/read.c +++ b/libbb/read.c @@ -6,7 +6,6 @@ * * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ - #include "libbb.h" #define ZIPPED (ENABLE_FEATURE_SEAMLESS_LZMA \ @@ -16,7 +15,7 @@ ) #if ZIPPED -#include "unarchive.h" +# include "unarchive.h" #endif ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count) @@ -306,14 +305,11 @@ void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) return buf; } -int FAST_FUNC open_zipped(const char *fname) +#if ZIPPED +int FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) { -#if !ZIPPED - return open(fname, O_RDONLY); -#else + const int fail_if_not_detected = 1; unsigned char magic[2]; - char *sfx; - int fd; #if BB_MMU IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); enum { xformer_prog = 0 }; @@ -322,6 +318,56 @@ int FAST_FUNC open_zipped(const char *fname) const char *xformer_prog; #endif + /* .gz and .bz2 both have 2-byte signature, and their + * unpack_XXX_stream wants this header skipped. */ + xread(fd, &magic, 2); +#if ENABLE_FEATURE_SEAMLESS_GZ +# if BB_MMU + xformer = unpack_gz_stream; +# else + xformer_prog = "gunzip"; +# endif +#endif + if (!ENABLE_FEATURE_SEAMLESS_GZ + || magic[0] != 0x1f || magic[1] != 0x8b + ) { + if (!ENABLE_FEATURE_SEAMLESS_BZ2 + || magic[0] != 'B' || magic[1] != 'Z' + ) { + if (fail_if_not_detected) + bb_error_msg_and_die("no gzip" + IF_FEATURE_SEAMLESS_BZ2("/bzip2") + " magic"); + xlseek(fd, -2, SEEK_CUR); + return fd; + } +#if BB_MMU + xformer = unpack_bz2_stream; +#else + xformer_prog = "bunzip2"; +#endif + } else { +#if !BB_MMU + /* NOMMU version of open_transformer execs + * an external unzipper that wants + * file position at the start of the file */ + xlseek(fd, -2, SEEK_CUR); +#endif + } + open_transformer(fd, xformer, xformer_prog); + + return fd; +} +#endif /* ZIPPED */ + +int FAST_FUNC open_zipped(const char *fname) +{ +#if !ZIPPED + return open(fname, O_RDONLY); +#else + char *sfx; + int fd; + fd = open(fname, O_RDONLY); if (fd < 0) return fd; @@ -335,40 +381,7 @@ int FAST_FUNC open_zipped(const char *fname) if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, ".gz") == 0) || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, ".bz2") == 0) ) { - /* .gz and .bz2 both have 2-byte signature, and their - * unpack_XXX_stream wants this header skipped. */ - xread(fd, &magic, 2); -#if ENABLE_FEATURE_SEAMLESS_GZ -#if BB_MMU - xformer = unpack_gz_stream; -#else - xformer_prog = "gunzip"; -#endif -#endif - if (!ENABLE_FEATURE_SEAMLESS_GZ - || magic[0] != 0x1f || magic[1] != 0x8b - ) { - if (!ENABLE_FEATURE_SEAMLESS_BZ2 - || magic[0] != 'B' || magic[1] != 'Z' - ) { - bb_error_msg_and_die("no gzip" - IF_FEATURE_SEAMLESS_BZ2("/bzip2") - " magic"); - } -#if BB_MMU - xformer = unpack_bz2_stream; -#else - xformer_prog = "bunzip2"; -#endif - } else { -#if !BB_MMU - /* NOMMU version of open_transformer execs - * an external unzipper that wants - * file position at the start of the file */ - xlseek(fd, 0, SEEK_SET); -#endif - } - open_transformer(fd, xformer, xformer_prog); + setup_unzip_on_fd(fd /*, fail_if_not_detected: 1*/); } } -- cgit v1.2.3-55-g6feb From 5dfd9c4dbcc30d6d3f745316fd11a797c06f06d0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 May 2010 16:56:38 +0200 Subject: rpm: make rpm -i SRPM.rpm install it to surrent dir; better help text function old new delta rpm_main 1355 1358 +3 packed_usage 26732 26728 -4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 3/-4) Total: -1 bytes Signed-off-by: Denys Vlasenko --- archival/rpm.c | 18 +++++++++++++----- include/usage.h | 8 ++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/archival/rpm.c b/archival/rpm.c index 77679c275..38ec20ef5 100644 --- a/archival/rpm.c +++ b/archival/rpm.c @@ -71,7 +71,7 @@ static void *map; static rpm_index **mytags; static int tagcount; -static void extract_cpio_gz(int fd); +static void extract_cpio(int fd, const char *source_rpm); static rpm_index **rpm_gettags(int fd, int *num_tags); static int bsearch_rpmtag(const void *key, const void *item); static char *rpm_getstr(int tag, int itemindex); @@ -122,6 +122,8 @@ int rpm_main(int argc, char **argv) } while (*argv) { + const char *source_rpm; + rpm_fd = xopen(*argv++, O_RDONLY); mytags = rpm_gettags(rpm_fd, &tagcount); if (!mytags) @@ -130,11 +132,13 @@ int rpm_main(int argc, char **argv) /* Mimimum is one page */ map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); + source_rpm = rpm_getstr(TAG_SOURCERPM, 0); + if (func & rpm_install) { /* Backup any config files */ loop_through_files(TAG_BASENAMES, fileaction_dobackup); /* Extact the archive */ - extract_cpio_gz(rpm_fd); + extract_cpio(rpm_fd, source_rpm); /* Set the correct file uid/gid's */ loop_through_files(TAG_BASENAMES, fileaction_setowngrp); } @@ -161,7 +165,7 @@ int rpm_main(int argc, char **argv) strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring); printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0)); - printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), rpm_getstr(TAG_SOURCERPM, 0)); + printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), source_rpm); printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0)); printf("URL : %s\n", rpm_getstr(TAG_URL, 0)); printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0)); @@ -194,10 +198,15 @@ int rpm_main(int argc, char **argv) return 0; } -static void extract_cpio_gz(int fd) +static void extract_cpio(int fd, const char *source_rpm) { archive_handle_t *archive_handle; + if (source_rpm != NULL) { + /* Binary rpm (it was built from some SRPM), install to root */ + xchdir("/"); + } /* else: SRPM, install to current dir */ + /* Initialize */ archive_handle = init_handle(); archive_handle->seek = seek_by_read; @@ -215,7 +224,6 @@ static void extract_cpio_gz(int fd) archive_handle->src_fd = fd; /*archive_handle->offset = 0; - init_handle() did it */ - xchdir("/"); /* Install RPM's to root */ setup_unzip_on_fd(archive_handle->src_fd /*, fail_if_not_detected: 1*/); while (get_header_cpio(archive_handle) == EXIT_SUCCESS) continue; diff --git a/include/usage.h b/include/usage.h index 636d01943..d619d9ed7 100644 --- a/include/usage.h +++ b/include/usage.h @@ -3810,13 +3810,13 @@ "\n -A inet" IF_FEATURE_IPV6("{6}") " Select address family" \ #define rpm_trivial_usage \ - "-i -q[ildc]p PACKAGE.rpm" + "-i PACKAGE.rpm; rpm -qp[ildc] PACKAGE.rpm" #define rpm_full_usage "\n\n" \ "Manipulate RPM packages\n" \ - "\nOptions:" \ + "\nCommands:" \ "\n -i Install package" \ - "\n -q Query package" \ - "\n -p Query uninstalled package" \ + "\n -qp Query package" \ + "\nOptions:" \ "\n -i Show information" \ "\n -l List contents" \ "\n -d List documents" \ -- cgit v1.2.3-55-g6feb From c2345fa2d410a3b1bc2797dae246fcbcb23ef17e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 May 2010 17:05:22 +0200 Subject: add comment about xz format support Signed-off-by: Denys Vlasenko --- libbb/read.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libbb/read.c b/libbb/read.c index 503216eb5..21e005c6f 100644 --- a/libbb/read.c +++ b/libbb/read.c @@ -334,6 +334,11 @@ int FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) if (!ENABLE_FEATURE_SEAMLESS_BZ2 || magic[0] != 'B' || magic[1] != 'Z' ) { + +// TODO: xz format support. rpm adopted it, "rpm -i FILE.rpm" badly needs this. +// Signature: 0xFD, '7', 'z', 'X', 'Z', 0x00 +// More info at: http://tukaani.org/xz/xz-file-format.txt + if (fail_if_not_detected) bb_error_msg_and_die("no gzip" IF_FEATURE_SEAMLESS_BZ2("/bzip2") -- cgit v1.2.3-55-g6feb From c7efd6441def53df0200d7cce24e2956ad96aa02 Mon Sep 17 00:00:00 2001 From: Gustavo Zacarias Date: Thu, 6 May 2010 11:57:14 -0300 Subject: install lspci and lsusb to /usr/bin Both can be run (to some degree) by mere users. Signed-off-by: Gustavo Zacarias Signed-off-by: Bernhard Reutner-Fischer --- include/applets.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/applets.h b/include/applets.h index dfb20b9be..6d7af5253 100644 --- a/include/applets.h +++ b/include/applets.h @@ -248,8 +248,8 @@ IF_LS(APPLET_NOEXEC(ls, ls, _BB_DIR_BIN, _BB_SUID_DROP, ls)) IF_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_DROP)) IF_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) -IF_LSPCI(APPLET(lspci, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_LSUSB(APPLET(lsusb, _BB_DIR_SBIN, _BB_SUID_DROP)) +IF_LSPCI(APPLET(lspci, _BB_DIR_USR_BIN, _BB_SUID_DROP)) +IF_LSUSB(APPLET(lsusb, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_UNLZMA(APPLET_ODDNAME(lzmacat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_DROP, lzmacat)) IF_LZOP(APPLET(lzop, _BB_DIR_BIN, _BB_SUID_DROP)) IF_LZOP(APPLET_ODDNAME(lzopcat, lzop, _BB_DIR_USR_BIN, _BB_SUID_DROP, lzopcat)) -- cgit v1.2.3-55-g6feb From 7b48eb4372c0b639bcb1eaedd63795c2dc0d9820 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 May 2010 20:08:14 +0200 Subject: tar: support GNU 256-bit encoding in all numeric fields function old new delta getOctal 63 125 +62 get_header_tar 1572 1496 -76 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 62/-76) Total: -14 bytes Signed-off-by: Denys Vlasenko --- archival/libunarchive/get_header_tar.c | 111 +++++++++------------------------ 1 file changed, 31 insertions(+), 80 deletions(-) diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c index adb4c157b..fcddcb834 100644 --- a/archival/libunarchive/get_header_tar.c +++ b/archival/libunarchive/get_header_tar.c @@ -18,87 +18,45 @@ typedef uint32_t aliased_uint32_t FIX_ALIASING; typedef off_t aliased_off_t FIX_ALIASING; -/* - * GNU tar uses "base-256 encoding" for very large numbers (>8 billion). - * Encoding is binary, with highest bit always set as a marker - * and sign in next-highest bit: - * 80 00 .. 00 - zero - * bf ff .. ff - largest positive number - * ff ff .. ff - minus 1 - * c0 00 .. 00 - smallest negative number - * - * We expect it only in size field, where negative numbers don't make sense. - */ -static off_t getBase256_len12(const char *str) -{ - off_t value; - int len; - - /* if (*str & 0x40) error; - caller prevents this */ - - if (sizeof(off_t) >= 12) { - /* Probably 128-bit (16 byte) off_t. Can be optimized. */ - len = 12; - value = *str++ & 0x3f; - while (--len) - value = (value << 8) + (unsigned char) *str++; - return value; - } - -#ifdef CHECK_FOR_OVERFLOW - /* Can be optimized to eat 32-bit chunks */ - char c = *str++ & 0x3f; - len = 12; - while (1) { - if (c) - bb_error_msg_and_die("overflow in base-256 encoded file size"); - if (--len == sizeof(off_t)) - break; - c = *str++; - } -#else - str += (12 - sizeof(off_t)); -#endif - -/* Now str points to sizeof(off_t) least significant bytes. - * - * Example of tar file with 8914993153 (0x213600001) byte file. - * Field starts at offset 7c: - * 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....| - * 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336| - * - * str is at offset 80 or 84 now (64-bit or 32-bit off_t). - * We (ab)use the fact that value happens to be aligned, - * and fetch it in one go: - */ - if (sizeof(off_t) == 8) { - value = *(aliased_off_t*)str; - value = SWAP_BE64(value); - } else if (sizeof(off_t) == 4) { - value = *(aliased_off_t*)str; - value = SWAP_BE32(value); - } else { - value = 0; - len = sizeof(off_t); - while (--len) - value = (value << 8) + (unsigned char) *str++; - } - return value; -} - /* NB: _DESTROYS_ str[len] character! */ static unsigned long long getOctal(char *str, int len) { unsigned long long v; + char *end; /* NB: leading spaces are allowed. Using strtoull to handle that. * The downside is that we accept e.g. "-123" too :( */ str[len] = '\0'; - v = strtoull(str, &str, 8); + v = strtoull(str, &end, 8); /* std: "Each numeric field is terminated by one or more * or NUL characters". We must support ' '! */ - if (*str != '\0' && *str != ' ') - bb_error_msg_and_die("corrupted octal value in tar header"); + if (*end != '\0' && *end != ' ') { + int8_t first = str[0]; + if (!(first & 0x80)) + bb_error_msg_and_die("corrupted octal value in tar header"); + /* + * GNU tar uses "base-256 encoding" for very large numbers. + * Encoding is binary, with highest bit always set as a marker + * and sign in next-highest bit: + * 80 00 .. 00 - zero + * bf ff .. ff - largest positive number + * ff ff .. ff - minus 1 + * c0 00 .. 00 - smallest negative number + * + * Example of tar file with 8914993153 (0x213600001) byte file. + * Field starts at offset 7c: + * 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....| + * 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336| + * + * NB: tarballs with NEGATIVE unix times encoded that way were seen! + */ + v = first; + /* Sign-extend using 6th bit: */ + v <<= sizeof(unsigned long long)*8 - 7; + v = (long long)v >> (sizeof(unsigned long long)*8 - 7); + while (--len != 0) + v = (v << 8) + (unsigned char) *str++; + } return v; } #define GET_OCTAL(a) getOctal((a), sizeof(a)) @@ -358,15 +316,8 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) file_header->tar__uname = tar.uname[0] ? xstrndup(tar.uname, sizeof(tar.uname)) : NULL; file_header->tar__gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL; #endif - /* mtime: rudimentally handle GNU tar's "base256 encoding" - * People report tarballs with NEGATIVE unix times encoded that way */ - file_header->mtime = (tar.mtime[0] & 0x80) /* base256? */ - ? 0 /* bogus */ - : GET_OCTAL(tar.mtime); - /* size: handle GNU tar's "base256 encoding" */ - file_header->size = (tar.size[0] & 0xc0) == 0x80 /* positive base256? */ - ? getBase256_len12(tar.size) - : GET_OCTAL(tar.size); + file_header->mtime = GET_OCTAL(tar.mtime); + file_header->size = GET_OCTAL(tar.size); file_header->gid = GET_OCTAL(tar.gid); file_header->uid = GET_OCTAL(tar.uid); /* Set bits 0-11 of the files mode */ -- cgit v1.2.3-55-g6feb From 19afe848eca8d3baf149cd7ed715489403360287 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 May 2010 23:26:16 +0200 Subject: ifplugd: replace potentially-leaking setenv with malloc/putenv/free text data bss dec hex filename 842657 453 6828 849938 cf812 busybox_old 842722 453 6828 850003 cf853 busybox_unstripped Signed-off-by: Denys Vlasenko --- networking/ifplugd.c | 103 ++++++++++----------------------------------------- 1 file changed, 20 insertions(+), 83 deletions(-) diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 41b04c4ed..01a7a49e5 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c @@ -93,6 +93,7 @@ enum { // constant fds struct globals { smallint iface_last_status; + smallint iface_prev_status; smallint iface_exists; /* Used in getopt32, must have sizeof == sizeof(int) */ @@ -121,97 +122,42 @@ struct globals { } while (0) +static const char *strstatus(int status) +{ + if (status == IFSTATUS_ERR) + return "error"; + return "down\0up" + (status * 5); +} + static int run_script(const char *action) { + char *env_PREVIOUS, *env_CURRENT; char *argv[5]; int r; bb_error_msg("executing '%s %s %s'", G.script_name, G.iface, action); -#if 1 - argv[0] = (char*) G.script_name; argv[1] = (char*) G.iface; argv[2] = (char*) action; argv[3] = (char*) G.extra_arg; argv[4] = NULL; + env_PREVIOUS = xasprintf("%s=%s", IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_prev_status)); + putenv(env_PREVIOUS); + env_CURRENT = xasprintf("%s=%s", IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_last_status)); + putenv(env_CURRENT); + /* r < 0 - can't exec, 0 <= r < 0x180 - exited, >=0x180 - killed by sig (r-0x180) */ r = spawn_and_wait(argv); + unsetenv(IFPLUGD_ENV_PREVIOUS); + unsetenv(IFPLUGD_ENV_CURRENT); + free(env_PREVIOUS); + free(env_CURRENT); + bb_error_msg("exit code: %d", r & 0xff); return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r; - -#else /* insanity */ - - struct fd_pair pipe_pair; - char buf[256]; - int i = 0; - - xpiped_pair(pipe_pair); - - pid = vfork(); - if (pid < 0) { - bb_perror_msg("fork"); - return -1; - } - - /* child */ - if (pid == 0) { - xmove_fd(pipe_pair.wr, 1); - xdup2(1, 2); - if (pipe_pair.rd > 2) - close(pipe_pair.rd); - - // umask(0022); // Set up a sane umask - - execlp(G.script_name, G.script_name, G.iface, action, G.extra_arg, NULL); - _exit(EXIT_FAILURE); - } - - /* parent */ - close(pipe_pair.wr); - - while (1) { - if (bb_got_signal && bb_got_signal != SIGCHLD) { - bb_error_msg("killing child"); - kill(pid, SIGTERM); - bb_got_signal = 0; - break; - } - - r = read(pipe_pair.rd, &buf[i], 1); - - if (buf[i] == '\n' || i == sizeof(buf)-2 || r != 1) { - if (r == 1 && buf[i] != '\n') - i++; - - buf[i] = '\0'; - - if (i > 0) - bb_error_msg("client: %s", buf); - - i = 0; - } else { - i++; - } - - if (r != 1) - break; - } - - close(pipe_pair.rd); - - wait(&r); - - if (!WIFEXITED(r) || WEXITSTATUS(r) != 0) { - bb_error_msg("program execution failed, return value is %i", - WEXITSTATUS(r)); - return option_mask32 & FLAG_IGNORE_RETVAL ? 0 : WEXITSTATUS(r); - } - bb_error_msg("program executed successfully"); - return 0; -#endif } static int network_ioctl(int request, void* data, const char *errmsg) @@ -228,13 +174,6 @@ static void set_ifreq_to_ifname(struct ifreq *ifreq) strncpy_IFNAMSIZ(ifreq->ifr_name, G.iface); } -static const char *strstatus(int status) -{ - if (status == IFSTATUS_ERR) - return "error"; - return "down\0up" + (status * 5); -} - static void up_iface(void) { struct ifreq ifrequest; @@ -474,9 +413,7 @@ static smallint detect_link(void) } if (status != G.iface_last_status) { -//TODO: is it safe to repeatedly do this? - setenv(IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_last_status), 1); - setenv(IFPLUGD_ENV_CURRENT, strstatus(status), 1); + G.iface_prev_status = G.iface_last_status; G.iface_last_status = status; } -- cgit v1.2.3-55-g6feb From 6774386d95cec54258f23f69bc287c99e205ebdf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 May 2010 00:13:40 +0200 Subject: tune2fs: move to e2fsprogs Signed-off-by: Denys Vlasenko --- e2fsprogs/Config.in | 12 ++++---- e2fsprogs/Kbuild | 3 +- e2fsprogs/tune2fs.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++ include/applets.h | 2 +- util-linux/Kbuild | 1 - util-linux/mkfs_ext2.c | 7 ++--- util-linux/mkfs_reiser.c | 7 ++--- util-linux/mkfs_vfat.c | 7 ++--- util-linux/tune2fs.c | 71 ------------------------------------------------ 9 files changed, 88 insertions(+), 92 deletions(-) create mode 100644 e2fsprogs/tune2fs.c delete mode 100644 util-linux/tune2fs.c diff --git a/e2fsprogs/Config.in b/e2fsprogs/Config.in index 9a0088ab5..964d08e4c 100644 --- a/e2fsprogs/Config.in +++ b/e2fsprogs/Config.in @@ -41,12 +41,12 @@ config LSATTR ### mke2fs is used to create an ext2/ext3 filesystem. The normal compat ### symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided. -### config TUNE2FS -### bool "tune2fs" -### default n -### help -### tune2fs allows the system administrator to adjust various tunable -### filesystem parameters on Linux ext2/ext3 filesystems. +config TUNE2FS + bool "tune2fs" + default n + help + tune2fs allows the system administrator to adjust various tunable + filesystem parameters on Linux ext2/ext3 filesystems. ### config E2LABEL ### bool "e2label" diff --git a/e2fsprogs/Kbuild b/e2fsprogs/Kbuild index 9f58ce092..0fdc9d215 100644 --- a/e2fsprogs/Kbuild +++ b/e2fsprogs/Kbuild @@ -9,4 +9,5 @@ lib-y:= lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o -lib-$(CONFIG_FSCK) += fsck.o +lib-$(CONFIG_FSCK) += fsck.o +lib-$(CONFIG_TUNE2FS) += tune2fs.o diff --git a/e2fsprogs/tune2fs.c b/e2fsprogs/tune2fs.c new file mode 100644 index 000000000..00ede4f1e --- /dev/null +++ b/e2fsprogs/tune2fs.c @@ -0,0 +1,70 @@ +/* vi: set sw=4 ts=4: */ +/* + * tune2fs: utility to modify EXT2 filesystem + * + * Busybox'ed (2009) by Vladimir Dronnikov + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ +#include "libbb.h" +#include +#include + +// storage helpers +char BUG_wrong_field_size(void); +#define STORE_LE(field, value) \ +do { \ + if (sizeof(field) == 4) \ + field = SWAP_LE32(value); \ + else if (sizeof(field) == 2) \ + field = SWAP_LE16(value); \ + else if (sizeof(field) == 1) \ + field = (value); \ + else \ + BUG_wrong_field_size(); \ +} while (0) + +#define FETCH_LE32(field) \ + (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size()) + +enum { + OPT_L = 1 << 0, // label +}; + +int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int tune2fs_main(int argc UNUSED_PARAM, char **argv) +{ + unsigned opts; + const char *label; + struct ext2_super_block *sb; + int fd; + + opt_complementary = "=1"; + opts = getopt32(argv, "L:", &label); + argv += optind; // argv[0] -- device + + if (!opts) + bb_show_usage(); + + // read superblock + fd = xopen(argv[0], O_RDWR); + xlseek(fd, 1024, SEEK_SET); + sb = xzalloc(1024); + xread(fd, sb, 1024); + + // mangle superblock + //STORE_LE(sb->s_wtime, time(NULL)); - why bother? + // set the label + if (1 /*opts & OPT_L*/) + safe_strncpy((char *)sb->s_volume_name, label, sizeof(sb->s_volume_name)); + // write superblock + xlseek(fd, 1024, SEEK_SET); + xwrite(fd, sb, 1024); + + if (ENABLE_FEATURE_CLEAN_UP) { + free(sb); + } + + xclose(fd); + return EXIT_SUCCESS; +} diff --git a/include/applets.h b/include/applets.h index 6d7af5253..36b24856a 100644 --- a/include/applets.h +++ b/include/applets.h @@ -405,7 +405,7 @@ IF_TRUE(APPLET_NOFORK(true, true, _BB_DIR_BIN, _BB_SUID_DROP, true)) IF_TTY(APPLET(tty, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_TTYSIZE(APPLET(ttysize, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_TUNCTL(APPLET(tunctl, _BB_DIR_SBIN, _BB_SUID_DROP)) -IF_MKFS_EXT2(APPLET(tune2fs, _BB_DIR_SBIN, _BB_SUID_DROP)) +IF_TUNE2FS(APPLET(tune2fs, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_UDHCPC(APPLET(udhcpc, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_UDHCPD(APPLET(udhcpd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_UDPSVD(APPLET_ODDNAME(udpsvd, tcpudpsvd, _BB_DIR_USR_BIN, _BB_SUID_DROP, udpsvd)) diff --git a/util-linux/Kbuild b/util-linux/Kbuild index 99e3efea3..4fa392398 100644 --- a/util-linux/Kbuild +++ b/util-linux/Kbuild @@ -42,5 +42,4 @@ lib-$(CONFIG_SCRIPTREPLAY) += scriptreplay.o lib-$(CONFIG_SETARCH) += setarch.o lib-$(CONFIG_SWAPONOFF) += swaponoff.o lib-$(CONFIG_SWITCH_ROOT) += switch_root.o -lib-$(CONFIG_MKFS_EXT2) += tune2fs.o lib-$(CONFIG_UMOUNT) += umount.o diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c index cf40c20eb..fd54734fc 100644 --- a/util-linux/mkfs_ext2.c +++ b/util-linux/mkfs_ext2.c @@ -10,7 +10,6 @@ #include "libbb.h" #include #include -#include "volume_id/volume_id_internal.h" #define ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT 0 #define ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX 1 @@ -29,9 +28,9 @@ char BUG_wrong_field_size(void); #define STORE_LE(field, value) \ do { \ if (sizeof(field) == 4) \ - field = cpu_to_le32(value); \ + field = SWAP_LE32(value); \ else if (sizeof(field) == 2) \ - field = cpu_to_le16(value); \ + field = SWAP_LE16(value); \ else if (sizeof(field) == 1) \ field = (value); \ else \ @@ -39,7 +38,7 @@ do { \ } while (0) #define FETCH_LE32(field) \ - (sizeof(field) == 4 ? cpu_to_le32(field) : BUG_wrong_field_size()) + (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size()) // All fields are little-endian struct ext2_dir { diff --git a/util-linux/mkfs_reiser.c b/util-linux/mkfs_reiser.c index eb2c94d02..f9a0ca82a 100644 --- a/util-linux/mkfs_reiser.c +++ b/util-linux/mkfs_reiser.c @@ -8,15 +8,14 @@ */ #include "libbb.h" #include -#include "volume_id/volume_id_internal.h" char BUG_wrong_field_size(void); #define STORE_LE(field, value) \ do { \ if (sizeof(field) == 4) \ - field = cpu_to_le32(value); \ + field = SWAP_LE32(value); \ else if (sizeof(field) == 2) \ - field = cpu_to_le16(value); \ + field = SWAP_LE16(value); \ else if (sizeof(field) == 1) \ field = (value); \ else \ @@ -24,7 +23,7 @@ do { \ } while (0) #define FETCH_LE32(field) \ - (sizeof(field) == 4 ? cpu_to_le32(field) : BUG_wrong_field_size()) + (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size()) struct journal_params { uint32_t jp_journal_1st_block; /* where does journal start from on its device */ diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c index 1363612f2..ff3e4165a 100644 --- a/util-linux/mkfs_vfat.c +++ b/util-linux/mkfs_vfat.c @@ -16,7 +16,6 @@ # define BLKSSZGET _IO(0x12, 104) #endif //#include -#include "volume_id/volume_id_internal.h" #define SECTOR_SIZE 512 @@ -168,15 +167,15 @@ static const char boot_code[] ALIGN1 = #define MARK_CLUSTER(cluster, value) \ - ((uint32_t *)fat)[cluster] = cpu_to_le32(value) + ((uint32_t *)fat)[cluster] = SWAP_LE32(value) void BUG_unsupported_field_size(void); #define STORE_LE(field, value) \ do { \ if (sizeof(field) == 4) \ - field = cpu_to_le32(value); \ + field = SWAP_LE32(value); \ else if (sizeof(field) == 2) \ - field = cpu_to_le16(value); \ + field = SWAP_LE16(value); \ else if (sizeof(field) == 1) \ field = (value); \ else \ diff --git a/util-linux/tune2fs.c b/util-linux/tune2fs.c deleted file mode 100644 index 3b8f3d8ef..000000000 --- a/util-linux/tune2fs.c +++ /dev/null @@ -1,71 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * tune2fs: utility to modify EXT2 filesystem - * - * Busybox'ed (2009) by Vladimir Dronnikov - * - * Licensed under GPLv2, see file LICENSE in this tarball for details. - */ -#include "libbb.h" -#include -#include -#include "volume_id/volume_id_internal.h" - -// storage helpers -char BUG_wrong_field_size(void); -#define STORE_LE(field, value) \ -do { \ - if (sizeof(field) == 4) \ - field = cpu_to_le32(value); \ - else if (sizeof(field) == 2) \ - field = cpu_to_le16(value); \ - else if (sizeof(field) == 1) \ - field = (value); \ - else \ - BUG_wrong_field_size(); \ -} while (0) - -#define FETCH_LE32(field) \ - (sizeof(field) == 4 ? cpu_to_le32(field) : BUG_wrong_field_size()) - -enum { - OPT_L = 1 << 0, // label -}; - -int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int tune2fs_main(int argc UNUSED_PARAM, char **argv) -{ - unsigned opts; - const char *label; - struct ext2_super_block *sb; - int fd; - - opt_complementary = "=1"; - opts = getopt32(argv, "L:", &label); - argv += optind; // argv[0] -- device - - if (!opts) - bb_show_usage(); - - // read superblock - fd = xopen(argv[0], O_RDWR); - xlseek(fd, 1024, SEEK_SET); - sb = xzalloc(1024); - xread(fd, sb, 1024); - - // mangle superblock - //STORE_LE(sb->s_wtime, time(NULL)); - why bother? - // set the label - if (1 /*opts & OPT_L*/) - safe_strncpy((char *)sb->s_volume_name, label, sizeof(sb->s_volume_name)); - // write superblock - xlseek(fd, 1024, SEEK_SET); - xwrite(fd, sb, 1024); - - if (ENABLE_FEATURE_CLEAN_UP) { - free(sb); - } - - xclose(fd); - return EXIT_SUCCESS; -} -- cgit v1.2.3-55-g6feb From 7fb68f199f037cb69363c8df5c934a27adc699f7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 May 2010 04:22:48 +0200 Subject: make it possible to keep Config/Kbuild snippets in *.c files Signed-off-by: Denys Vlasenko --- Makefile | 9 +- findutils/Config.in | 253 --------------------------------------------- findutils/Config.src | 10 ++ findutils/Kbuild | 10 -- findutils/Kbuild.src | 9 ++ findutils/find.c | 175 +++++++++++++++++++++++++++++++ findutils/grep.c | 35 +++++++ findutils/xargs.c | 41 ++++++++ scripts/gen_build_files.sh | 55 ++++++++++ 9 files changed, 332 insertions(+), 265 deletions(-) delete mode 100644 findutils/Config.in create mode 100644 findutils/Config.src delete mode 100644 findutils/Kbuild create mode 100644 findutils/Kbuild.src create mode 100644 scripts/gen_build_files.sh diff --git a/Makefile b/Makefile index 1481f0100..da8f7d7b6 100644 --- a/Makefile +++ b/Makefile @@ -377,6 +377,11 @@ ifneq ($(KBUILD_SRC),) $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) endif +# This target generates Kbuild's and Config.in's from *.c files +PHONY += gen_build_files +gen_build_files: + $(Q)$(srctree)/scripts/gen_build_files.sh $(srctree) $(objtree) + # To make sure we do not include .config for any of the *config targets # catch them early, and hand them over to scripts/kconfig/Makefile # It is allowed to specify more targets when calling make, including @@ -428,7 +433,7 @@ ifeq ($(config-targets),1) -include $(srctree)/arch/$(ARCH)/Makefile export KBUILD_DEFCONFIG -config %config: scripts_basic outputmakefile FORCE +config %config: scripts_basic outputmakefile gen_build_files FORCE $(Q)mkdir -p include $(Q)$(MAKE) $(build)=scripts/kconfig $@ $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease @@ -443,7 +448,7 @@ ifeq ($(KBUILD_EXTMOD),) # Carefully list dependencies so we do not try to build scripts twice # in parrallel PHONY += scripts -scripts: scripts_basic include/config/MARKER +scripts: gen_build_files scripts_basic include/config/MARKER $(Q)$(MAKE) $(build)=$(@) scripts_basic: include/autoconf.h diff --git a/findutils/Config.in b/findutils/Config.in deleted file mode 100644 index 8582d6446..000000000 --- a/findutils/Config.in +++ /dev/null @@ -1,253 +0,0 @@ -# -# For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. -# - -menu "Finding Utilities" - -config FIND - bool "find" - default n - help - find is used to search your system to find specified files. - -config FEATURE_FIND_PRINT0 - bool "Enable -print0: NUL-terminated output" - default y - depends on FIND - help - Causes output names to be separated by a NUL character - rather than a newline. This allows names that contain - newlines and other whitespace to be more easily - interpreted by other programs. - -config FEATURE_FIND_MTIME - bool "Enable -mtime: modified time matching" - default y - depends on FIND - help - Allow searching based on the modification time of - files, in days. - -config FEATURE_FIND_MMIN - bool "Enable -mmin: modified time matching by minutes" - default y - depends on FIND - help - Allow searching based on the modification time of - files, in minutes. - -config FEATURE_FIND_PERM - bool "Enable -perm: permissions matching" - default y - depends on FIND - help - Enable searching based on file permissions. - -config FEATURE_FIND_TYPE - bool "Enable -type: file type matching (file/dir/link/...)" - default y - depends on FIND - help - Enable searching based on file type (file, - directory, socket, device, etc.). - -config FEATURE_FIND_XDEV - bool "Enable -xdev: 'stay in filesystem'" - default y - depends on FIND - help - This option allows find to restrict searches to a single filesystem. - -config FEATURE_FIND_MAXDEPTH - bool "Enable -maxdepth N" - default y - depends on FIND - help - This option enables -maxdepth N option. - -config FEATURE_FIND_NEWER - bool "Enable -newer: compare file modification times" - default y - depends on FIND - help - Support the 'find -newer' option for finding any files which have - a modified time that is more recent than the specified FILE. - -config FEATURE_FIND_INUM - bool "Enable -inum: inode number matching" - default y - depends on FIND - help - Support the 'find -inum' option for searching by inode number. - -config FEATURE_FIND_EXEC - bool "Enable -exec: execute commands" - default y - depends on FIND - help - Support the 'find -exec' option for executing commands based upon - the files matched. - -config FEATURE_FIND_USER - bool "Enable -user: username/uid matching" - default y - depends on FIND - help - Support the 'find -user' option for searching by username or uid. - -config FEATURE_FIND_GROUP - bool "Enable -group: group/gid matching" - default y - depends on FIND - help - Support the 'find -group' option for searching by group name or gid. - -config FEATURE_FIND_NOT - bool "Enable the 'not' (!) operator" - default y - depends on FIND - help - Support the '!' operator to invert the test results. - If 'Enable full-blown desktop' is enabled, then will also support - the non-POSIX notation '-not'. - -config FEATURE_FIND_DEPTH - bool "Enable -depth" - default y - depends on FIND - help - Process each directory's contents before the directory itself. - -config FEATURE_FIND_PAREN - bool "Enable parens in options" - default y - depends on FIND - help - Enable usage of parens '(' to specify logical order of arguments. - -config FEATURE_FIND_SIZE - bool "Enable -size: file size matching" - default y - depends on FIND - help - Support the 'find -size' option for searching by file size. - -config FEATURE_FIND_PRUNE - bool "Enable -prune: exclude subdirectories" - default y - depends on FIND - help - If the file is a directory, dont descend into it. Useful for - exclusion .svn and CVS directories. - -config FEATURE_FIND_DELETE - bool "Enable -delete: delete files/dirs" - default n - depends on FIND && FEATURE_FIND_DEPTH - help - Support the 'find -delete' option for deleting files and directories. - WARNING: This option can do much harm if used wrong. Busybox will not - try to protect the user from doing stupid things. Use with care. - -config FEATURE_FIND_PATH - bool "Enable -path: match pathname with shell pattern" - default y - depends on FIND - help - The -path option matches whole pathname instead of just filename. - -config FEATURE_FIND_REGEX - bool "Enable -regex: match pathname with regex" - default y - depends on FIND - help - The -regex option matches whole pathname against regular expression. - -config FEATURE_FIND_CONTEXT - bool "Enable -context: security context matching" - default n - depends on FIND && SELINUX - help - Support the 'find -context' option for matching security context. - -config FEATURE_FIND_LINKS - bool "Enable -links: link count matching" - default n - depends on FIND - help - Support the 'find -links' option for matching number of links. - -config GREP - bool "grep" - default n - help - grep is used to search files for a specified pattern. - -config FEATURE_GREP_EGREP_ALIAS - bool "Enable extended regular expressions (egrep & grep -E)" - default y - depends on GREP - help - Enabled support for extended regular expressions. Extended - regular expressions allow for alternation (foo|bar), grouping, - and various repetition operators. - -config FEATURE_GREP_FGREP_ALIAS - bool "Alias fgrep to grep -F" - default y - depends on GREP - help - fgrep sees the search pattern as a normal string rather than - regular expressions. - grep -F always works, this just creates the fgrep alias. - -config FEATURE_GREP_CONTEXT - bool "Enable before and after context flags (-A, -B and -C)" - default y - depends on GREP - help - Print the specified number of leading (-B) and/or trailing (-A) - context surrounding our matching lines. - Print the specified number of context lines (-C). - -config XARGS - bool "xargs" - default n - help - xargs is used to execute a specified command for - every item from standard input. - -config FEATURE_XARGS_SUPPORT_CONFIRMATION - bool "Enable -p: prompt and confirmation" - default n - depends on XARGS - help - Support -p: prompt the user whether to run each command - line and read a line from the terminal. - -config FEATURE_XARGS_SUPPORT_QUOTES - bool "Enable single and double quotes and backslash" - default n - depends on XARGS - help - Support quoting in the input. - -config FEATURE_XARGS_SUPPORT_TERMOPT - bool "Enable -x: exit if -s or -n is exceeded" - default n - depends on XARGS - help - Support -x: exit if the command size (see the -s or -n option) - is exceeded. - -config FEATURE_XARGS_SUPPORT_ZERO_TERM - bool "Enable -0: NUL-terminated input" - default n - depends on XARGS - help - Support -0: input items are terminated by a NUL character - instead of whitespace, and the quotes and backslash - are not special. - -endmenu diff --git a/findutils/Config.src b/findutils/Config.src new file mode 100644 index 000000000..9ee71a845 --- /dev/null +++ b/findutils/Config.src @@ -0,0 +1,10 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Finding Utilities" + +INSERT + +endmenu diff --git a/findutils/Kbuild b/findutils/Kbuild deleted file mode 100644 index 7b504bacf..000000000 --- a/findutils/Kbuild +++ /dev/null @@ -1,10 +0,0 @@ -# Makefile for busybox -# -# Copyright (C) 1999-2005 by Erik Andersen -# -# Licensed under the GPL v2, see the file LICENSE in this tarball. - -lib-y:= -lib-$(CONFIG_FIND) += find.o -lib-$(CONFIG_GREP) += grep.o -lib-$(CONFIG_XARGS) += xargs.o diff --git a/findutils/Kbuild.src b/findutils/Kbuild.src new file mode 100644 index 000000000..771789ff5 --- /dev/null +++ b/findutils/Kbuild.src @@ -0,0 +1,9 @@ +# Makefile for busybox +# +# Copyright (C) 1999-2005 by Erik Andersen +# +# Licensed under the GPL v2, see the file LICENSE in this tarball. + +lib-y:= + +INSERT diff --git a/findutils/find.c b/findutils/find.c index 30fb03dd1..9022867a2 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -53,6 +53,181 @@ * diff -u /tmp/std_find /tmp/bb_find && echo Identical */ +//kbuild:lib-$(CONFIG_FIND) += find.o +//config: +//config:config FIND +//config: bool "find" +//config: default n +//config: help +//config: find is used to search your system to find specified files. +//config: +//config:config FEATURE_FIND_PRINT0 +//config: bool "Enable -print0: NUL-terminated output" +//config: default y +//config: depends on FIND +//config: help +//config: Causes output names to be separated by a NUL character +//config: rather than a newline. This allows names that contain +//config: newlines and other whitespace to be more easily +//config: interpreted by other programs. +//config: +//config:config FEATURE_FIND_MTIME +//config: bool "Enable -mtime: modified time matching" +//config: default y +//config: depends on FIND +//config: help +//config: Allow searching based on the modification time of +//config: files, in days. +//config: +//config:config FEATURE_FIND_MMIN +//config: bool "Enable -mmin: modified time matching by minutes" +//config: default y +//config: depends on FIND +//config: help +//config: Allow searching based on the modification time of +//config: files, in minutes. +//config: +//config:config FEATURE_FIND_PERM +//config: bool "Enable -perm: permissions matching" +//config: default y +//config: depends on FIND +//config: help +//config: Enable searching based on file permissions. +//config: +//config:config FEATURE_FIND_TYPE +//config: bool "Enable -type: file type matching (file/dir/link/...)" +//config: default y +//config: depends on FIND +//config: help +//config: Enable searching based on file type (file, +//config: directory, socket, device, etc.). +//config: +//config:config FEATURE_FIND_XDEV +//config: bool "Enable -xdev: 'stay in filesystem'" +//config: default y +//config: depends on FIND +//config: help +//config: This option allows find to restrict searches to a single filesystem. +//config: +//config:config FEATURE_FIND_MAXDEPTH +//config: bool "Enable -maxdepth N" +//config: default y +//config: depends on FIND +//config: help +//config: This option enables -maxdepth N option. +//config: +//config:config FEATURE_FIND_NEWER +//config: bool "Enable -newer: compare file modification times" +//config: default y +//config: depends on FIND +//config: help +//config: Support the 'find -newer' option for finding any files which have +//config: a modified time that is more recent than the specified FILE. +//config: +//config:config FEATURE_FIND_INUM +//config: bool "Enable -inum: inode number matching" +//config: default y +//config: depends on FIND +//config: help +//config: Support the 'find -inum' option for searching by inode number. +//config: +//config:config FEATURE_FIND_EXEC +//config: bool "Enable -exec: execute commands" +//config: default y +//config: depends on FIND +//config: help +//config: Support the 'find -exec' option for executing commands based upon +//config: the files matched. +//config: +//config:config FEATURE_FIND_USER +//config: bool "Enable -user: username/uid matching" +//config: default y +//config: depends on FIND +//config: help +//config: Support the 'find -user' option for searching by username or uid. +//config: +//config:config FEATURE_FIND_GROUP +//config: bool "Enable -group: group/gid matching" +//config: default y +//config: depends on FIND +//config: help +//config: Support the 'find -group' option for searching by group name or gid. +//config: +//config:config FEATURE_FIND_NOT +//config: bool "Enable the 'not' (!) operator" +//config: default y +//config: depends on FIND +//config: help +//config: Support the '!' operator to invert the test results. +//config: If 'Enable full-blown desktop' is enabled, then will also support +//config: the non-POSIX notation '-not'. +//config: +//config:config FEATURE_FIND_DEPTH +//config: bool "Enable -depth" +//config: default y +//config: depends on FIND +//config: help +//config: Process each directory's contents before the directory itself. +//config: +//config:config FEATURE_FIND_PAREN +//config: bool "Enable parens in options" +//config: default y +//config: depends on FIND +//config: help +//config: Enable usage of parens '(' to specify logical order of arguments. +//config: +//config:config FEATURE_FIND_SIZE +//config: bool "Enable -size: file size matching" +//config: default y +//config: depends on FIND +//config: help +//config: Support the 'find -size' option for searching by file size. +//config: +//config:config FEATURE_FIND_PRUNE +//config: bool "Enable -prune: exclude subdirectories" +//config: default y +//config: depends on FIND +//config: help +//config: If the file is a directory, dont descend into it. Useful for +//config: exclusion .svn and CVS directories. +//config: +//config:config FEATURE_FIND_DELETE +//config: bool "Enable -delete: delete files/dirs" +//config: default n +//config: depends on FIND && FEATURE_FIND_DEPTH +//config: help +//config: Support the 'find -delete' option for deleting files and directories. +//config: WARNING: This option can do much harm if used wrong. Busybox will not +//config: try to protect the user from doing stupid things. Use with care. +//config: +//config:config FEATURE_FIND_PATH +//config: bool "Enable -path: match pathname with shell pattern" +//config: default y +//config: depends on FIND +//config: help +//config: The -path option matches whole pathname instead of just filename. +//config: +//config:config FEATURE_FIND_REGEX +//config: bool "Enable -regex: match pathname with regex" +//config: default y +//config: depends on FIND +//config: help +//config: The -regex option matches whole pathname against regular expression. +//config: +//config:config FEATURE_FIND_CONTEXT +//config: bool "Enable -context: security context matching" +//config: default n +//config: depends on FIND && SELINUX +//config: help +//config: Support the 'find -context' option for matching security context. +//config: +//config:config FEATURE_FIND_LINKS +//config: bool "Enable -links: link count matching" +//config: default n +//config: depends on FIND +//config: help +//config: Support the 'find -links' option for matching number of links. + #include #include "libbb.h" #if ENABLE_FEATURE_FIND_REGEX diff --git a/findutils/grep.c b/findutils/grep.c index 0f1c11abb..be290118f 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -19,6 +19,41 @@ * (C) 2006 Jac Goudsmit added -o option */ +//kbuild:lib-$(CONFIG_GREP) += grep.o +//config: +//config:config GREP +//config: bool "grep" +//config: default n +//config: help +//config: grep is used to search files for a specified pattern. +//config: +//config:config FEATURE_GREP_EGREP_ALIAS +//config: bool "Enable extended regular expressions (egrep & grep -E)" +//config: default y +//config: depends on GREP +//config: help +//config: Enabled support for extended regular expressions. Extended +//config: regular expressions allow for alternation (foo|bar), grouping, +//config: and various repetition operators. +//config: +//config:config FEATURE_GREP_FGREP_ALIAS +//config: bool "Alias fgrep to grep -F" +//config: default y +//config: depends on GREP +//config: help +//config: fgrep sees the search pattern as a normal string rather than +//config: regular expressions. +//config: grep -F always works, this just creates the fgrep alias. +//config: +//config:config FEATURE_GREP_CONTEXT +//config: bool "Enable before and after context flags (-A, -B and -C)" +//config: default y +//config: depends on GREP +//config: help +//config: Print the specified number of leading (-B) and/or trailing (-A) +//config: context surrounding our matching lines. +//config: Print the specified number of context lines (-C). + #include "libbb.h" #include "xregex.h" diff --git a/findutils/xargs.c b/findutils/xargs.c index 3785f1ec0..c55ac5724 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -17,6 +17,47 @@ * */ +//kbuild:lib-$(CONFIG_XARGS) += xargs.o +//config: +//config:config XARGS +//config: bool "xargs" +//config: default n +//config: help +//config: xargs is used to execute a specified command for +//config: every item from standard input. +//config: +//config:config FEATURE_XARGS_SUPPORT_CONFIRMATION +//config: bool "Enable -p: prompt and confirmation" +//config: default n +//config: depends on XARGS +//config: help +//config: Support -p: prompt the user whether to run each command +//config: line and read a line from the terminal. +//config: +//config:config FEATURE_XARGS_SUPPORT_QUOTES +//config: bool "Enable single and double quotes and backslash" +//config: default n +//config: depends on XARGS +//config: help +//config: Support quoting in the input. +//config: +//config:config FEATURE_XARGS_SUPPORT_TERMOPT +//config: bool "Enable -x: exit if -s or -n is exceeded" +//config: default n +//config: depends on XARGS +//config: help +//config: Support -x: exit if the command size (see the -s or -n option) +//config: is exceeded. +//config: +//config:config FEATURE_XARGS_SUPPORT_ZERO_TERM +//config: bool "Enable -0: NUL-terminated input" +//config: default n +//config: depends on XARGS +//config: help +//config: Support -0: input items are terminated by a NUL character +//config: instead of whitespace, and the quotes and backslash +//config: are not special. + #include "libbb.h" /* This is a NOEXEC applet. Be very careful! */ diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh new file mode 100644 index 000000000..300d90c2a --- /dev/null +++ b/scripts/gen_build_files.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +test $# -ge 2 || exit 1 + +# cd to objtree +cd "$2" || exit 1 + +srctree="$1" + +find -type d \ +| while read; do + d="$REPLY" + + src="$srctree/$d/Kbuild.src" + dst="$d/Kbuild" + if test -f "$src"; then + echo " CHK $dst" + + s=`grep -h '^//kbuild:' "$srctree/$d"/*.c | sed 's^//kbuild:^^'` + while read; do + test x"$REPLY" = x"INSERT" && REPLY="$s" + printf "%s\n" "$REPLY" + done <"$src" >"$dst.$$.tmp" + + if test -f "$dst" && cmp -s "$dst.$$.tmp" "$dst"; then + rm "$dst.$$.tmp" + else + echo " GEN $dst" + mv "$dst.$$.tmp" "$dst" + fi + fi + + src="$srctree/$d/Config.src" + dst="$d/Config.in" + if test -f "$src"; then + echo " CHK $dst" + + s=`grep -h '^//config:' "$srctree/$d"/*.c | sed 's^//config:^^'` + while read; do + test x"$REPLY" = x"INSERT" && REPLY="$s" + printf "%s\n" "$REPLY" + done <"$src" >"$dst.$$.tmp" + + if test -f "$dst" && cmp -s "$dst.$$.tmp" "$dst"; then + rm "$dst.$$.tmp" + else + echo " GEN $dst" + mv "$dst.$$.tmp" "$dst" + fi + fi + +done + +# Last read failed. This is normal. Don't exit with its error code: +exit 0 -- cgit v1.2.3-55-g6feb From 65ebbc54d3344a7ab7318b37b85293b4a1848a6e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 May 2010 04:38:22 +0200 Subject: trim help text function old new delta packed_usage 27006 26988 -18 Signed-off-by: Denys Vlasenko --- include/usage.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/usage.h b/include/usage.h index d619d9ed7..9d9ad008b 100644 --- a/include/usage.h +++ b/include/usage.h @@ -501,9 +501,9 @@ "Clear screen" #define cmp_trivial_usage \ - "[-l] [-s] FILE1 [FILE2" IF_DESKTOP(" [SKIP1 [SKIP2]") "]]" + "[-l] [-s] FILE1 [FILE2" IF_DESKTOP(" [SKIP1 [SKIP2]]") "]" #define cmp_full_usage "\n\n" \ - "Compares FILE1 vs stdin if FILE2 is not specified\n" \ + "Compare FILE1 with FILE2 (or stdin)\n" \ "\nOptions:" \ "\n -l Write the byte numbers (decimal) and values (octal)" \ "\n for all differing bytes" \ @@ -512,7 +512,7 @@ #define comm_trivial_usage \ "[-123] FILE1 FILE2" #define comm_full_usage "\n\n" \ - "Compare FILE1 to FILE2, or to stdin if - is specified\n" \ + "Compare FILE1 with FILE2\n" \ "\nOptions:" \ "\n -1 Suppress lines unique to FILE1" \ "\n -2 Suppress lines unique to FILE2" \ -- cgit v1.2.3-55-g6feb From 572b9a3019caf0929a41a45e1f3a8c7e59ec141c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 May 2010 16:20:52 +0200 Subject: tweak scripts/gen_build_files.sh Signed-off-by: Denys Vlasenko --- scripts/gen_build_files.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index 300d90c2a..3d757500c 100644 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -1,14 +1,13 @@ #!/bin/sh -test $# -ge 2 || exit 1 +test $# -ge 2 || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } # cd to objtree -cd "$2" || exit 1 +cd "$2" || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } srctree="$1" -find -type d \ -| while read; do +find -type d | while read; do d="$REPLY" src="$srctree/$d/Kbuild.src" @@ -16,11 +15,12 @@ find -type d \ if test -f "$src"; then echo " CHK $dst" - s=`grep -h '^//kbuild:' "$srctree/$d"/*.c | sed 's^//kbuild:^^'` + s=`sed -n 's@^//kbuild:@@p' "$srctree/$d"/*.c` + echo "# DO NOT EDIT. This file is generated from Kbuild.src" >"$dst.$$.tmp" while read; do test x"$REPLY" = x"INSERT" && REPLY="$s" printf "%s\n" "$REPLY" - done <"$src" >"$dst.$$.tmp" + done <"$src" >>"$dst.$$.tmp" if test -f "$dst" && cmp -s "$dst.$$.tmp" "$dst"; then rm "$dst.$$.tmp" @@ -35,11 +35,12 @@ find -type d \ if test -f "$src"; then echo " CHK $dst" - s=`grep -h '^//config:' "$srctree/$d"/*.c | sed 's^//config:^^'` + s=`sed -n 's@^//config:@@p' "$srctree/$d"/*.c` + echo "# DO NOT EDIT. This file is generated from Config.src" >"$dst.$$.tmp" while read; do test x"$REPLY" = x"INSERT" && REPLY="$s" printf "%s\n" "$REPLY" - done <"$src" >"$dst.$$.tmp" + done <"$src" >>"$dst.$$.tmp" if test -f "$dst" && cmp -s "$dst.$$.tmp" "$dst"; then rm "$dst.$$.tmp" -- cgit v1.2.3-55-g6feb From ff0e875e02487b61dcc520b295feb6477b859065 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 May 2010 04:16:43 +0200 Subject: work on adding testsuite runs to randomconfig test builds Signed-off-by: Denys Vlasenko --- archival/cpio.c | 1 + coreutils/Kbuild | 1 + networking/telnetd.c | 2 +- scripts/randomtest | 130 ++++++++++++++++++++++++------------------------ scripts/randomtest.loop | 36 ++++++++++++-- testsuite/ash.tests | 4 ++ testsuite/cpio.tests | 4 ++ 7 files changed, 109 insertions(+), 69 deletions(-) diff --git a/archival/cpio.c b/archival/cpio.c index 2698f0791..e0ca7fa5c 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -311,6 +311,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) /* no parameters */ opt_complementary = "=0"; opt = getopt32(argv, OPTION_STR, &cpio_filename); + argv += optind; if (opt & CPIO_OPT_FILE) { /* -F */ xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); } diff --git a/coreutils/Kbuild b/coreutils/Kbuild index 460d62d3f..ee22a3f7b 100644 --- a/coreutils/Kbuild +++ b/coreutils/Kbuild @@ -17,6 +17,7 @@ lib-$(CONFIG_CATV) += catv.o lib-$(CONFIG_CHGRP) += chgrp.o chown.o lib-$(CONFIG_CHMOD) += chmod.o lib-$(CONFIG_CHOWN) += chown.o +lib-$(CONFIG_ADDUSER) += chown.o # used by adduser lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser lib-$(CONFIG_CHROOT) += chroot.o lib-$(CONFIG_CKSUM) += cksum.o diff --git a/networking/telnetd.c b/networking/telnetd.c index a8c86b62f..ea66a25c0 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c @@ -227,7 +227,7 @@ make_new_session( IF_NOT_FEATURE_TELNETD_STANDALONE(void) ) { #if !ENABLE_FEATURE_TELNETD_STANDALONE - enum { sock = 0 ); + enum { sock = 0 }; #endif const char *login_argv[2]; struct termios termbuf; diff --git a/scripts/randomtest b/scripts/randomtest index 6b7db9239..8d0d79e64 100755 --- a/scripts/randomtest +++ b/scripts/randomtest @@ -1,86 +1,88 @@ #!/bin/sh -# Select which libc to build against -libc="glibc" # assumed native -# static, cross-compilation -libc="uclibc" +# If not specified in environment... +if ! test "$LIBC"; then + # Select which libc to build against + LIBC="glibc" + LIBC="uclibc" +fi # x86 32-bit: -uclibc_cross="i486-linux-uclibc-" +#CROSS_COMPILER_PREFIX="i486-linux-uclibc-" # My system has strange prefix for x86 64-bit uclibc: -#uclibc_cross="x86_64-pc-linux-gnu-" +#CROSS_COMPILER_PREFIX="x86_64-pc-linux-gnu-" -test -d tree || exit 1 +if test $# -lt 2 || ! test -d "$1" || test -e "$2"; then + echo "Usage: $0 SRC_DIR TMP_DIR" + echo + echo "SRC_DIR will be copied to TMP_DIR directory." + echo "Then a random build will be performed." + echo + echo "Useful variables:" + echo "\$LIBC, \$CROSS_COMPILER_PREFIX, \$MAKEOPTS" + exit 1 +fi -dir=test.$$ -while test -e "$dir" -o -e failed."$dir"; do - dir=test."$RANDOM" -done +cp -dpr -- "$1" "$2" || { echo "copy error"; exit 1; } +cd -- "$2" || { echo "cd $dir error"; exit 1; } -cp -dpr tree "$dir" || exit 1 -cd "$dir" || exit 1 - -echo "Running randconfig test in $dir..." >&2 - -make randconfig >/dev/null || exit 1 +# Generate random config +make randconfig >/dev/null || { echo "randconfig error"; exit 1; } +# Tweak resulting config cat .config \ -| grep -v ^CONFIG_DEBUG_PESSIMIZE= \ +| grep -v CONFIG_DEBUG_PESSIMIZE \ | grep -v CONFIG_WERROR \ -| cat >.config.new -mv .config.new .config -#echo CONFIG_WERROR=y >>.config -echo '# CONFIG_WERROR is not set' >>.config - -test "$libc" = glibc && { -cat .config \ -| grep -v CONFIG_STATIC \ +| grep -v CONFIG_CROSS_COMPILER_PREFIX \ | grep -v CONFIG_SELINUX \ | grep -v CONFIG_EFENCE \ | grep -v CONFIG_DMALLOC \ -| cat >.config.new +\ +| grep -v CONFIG_RFKILL \ +>.config.new mv .config.new .config -echo '# CONFIG_STATIC is not set' >>.config -} +echo '# CONFIG_DEBUG_PESSIMIZE is not set' >>.config +echo '# CONFIG_WERROR is not set' >>.config +echo "CONFIG_CROSS_COMPILER_PREFIX=\"${CROSS_COMPILER_PREFIX}\"" >>.config -test "$libc" = uclibc && { -cat .config \ -| grep -v ^CONFIG_SELINUX= \ -| grep -v ^CONFIG_EFENCE= \ -| grep -v ^CONFIG_DMALLOC= \ -| grep -v ^CONFIG_BUILD_LIBBUSYBOX= \ -| grep -v ^CONFIG_PAM= \ -| grep -v ^CONFIG_TASKSET= \ -| grep -v ^CONFIG_UNICODE_SUPPORT= \ -| grep -v ^CONFIG_PIE= \ -| grep -v CONFIG_STATIC \ -| grep -v CONFIG_CROSS_COMPILER_PREFIX \ -| cat >.config.new -mv .config.new .config -echo 'CONFIG_CROSS_COMPILER_PREFIX="'"$uclibc_cross"'"' >>.config -echo 'CONFIG_STATIC=y' >>.config -} +# If glibc, don't build static +if test x"$LIBC" = x"glibc"; then + cat .config \ + | grep -v CONFIG_STATIC \ + >.config.new + mv .config.new .config + echo '# CONFIG_STATIC is not set' >>.config +fi + +# If glibc, build static, and remove some things +# likely to not work on uclibc. +if test x"$LIBC" = x"uclibc"; then + cat .config \ + | grep -v CONFIG_STATIC \ + | grep -v CONFIG_BUILD_LIBBUSYBOX \ + | grep -v CONFIG_TASKSET \ + | grep -v CONFIG_UNICODE_SUPPORT \ + | grep -v CONFIG_PIE \ + >.config.new + mv .config.new .config + echo 'CONFIG_STATIC=y' >>.config +fi -# If STATIC, remove some things +# If STATIC, remove some things. # PAM with static linking is probably pointless # (but I need to try - now I don't have libpam.a on my system, only libpam.so) -grep -q ^CONFIG_STATIC= .config && { -cat .config \ -| grep -v ^CONFIG_PAM= \ -| cat >.config.new -mv .config.new .config -} +if grep -q "^CONFIG_STATIC=y" .config; then + cat .config \ + | grep -v CONFIG_PAM \ + >.config.new + mv .config.new .config +fi # Regenerate .config with default answers for yanked-off options -{ yes "" | make oldconfig >/dev/null; } || exit 1 - -nice -n 10 make $MAKEOPTS 2>&1 | tee -a make.log +# (most of default answers are "no"). +{ yes "" | make oldconfig >/dev/null; } || { echo "oldconfig error"; exit 1; } -test -x busybox && { - cd .. - rm -rf "$dir" - exit 0 -} +# Build! +nice -n 10 make $MAKEOPTS 2>&1 | tee make.log -cd .. -mv "$dir" "failed.$dir" -exit 1 +# Return exitcode 1 if busybox executable does not exist +test -x busybox diff --git a/scripts/randomtest.loop b/scripts/randomtest.loop index 28edb6732..311536df8 100755 --- a/scripts/randomtest.loop +++ b/scripts/randomtest.loop @@ -1,10 +1,38 @@ #!/bin/sh +test -d "$1" || { echo "'$1' is not a directory"; exit 1; } +test -x "$1/scripts/randomtest" || { echo "No scripts/randomtest in '$1'"; exit 1; } + +export LIBC="uclibc" +export CROSS_COMPILER_PREFIX="i486-linux-uclibc-" +export MAKEOPTS="-j9" + cnt=0 fail=0 - while sleep 1; do - echo "Passes: $cnt Failures: $fail" - ./randomtest >/dev/null || exit #let fail++ - let cnt++ + echo "Passes: $cnt Failures: $fail" + dir="test.$$" + while test -e "$dir" -o -e "failed.$dir"; do + dir="test.$$.$RANDOM" + done + echo "Running randconfig test in $dir..." + if ! "$1/scripts/randomtest" "$1" "$dir" >/dev/null; then + mv -- "$dir" "failed.$dir" + echo "Failed build in: failed.$dir" + exit 1 # you may comment this out... + let fail++ + else + ( + cd -- "$dir/testsuite" || exit 1 + echo "Running testsuite in $dir..." + SKIP_KNOWN_BUGS=1 SKIP_INTERNET_TESTS=1 ./runtest -v >runtest.log 2>&1 + ) + if test $? != 0; then + echo "Failed runtest in $dir" + exit 1 + fi + tail -n10 -- "$dir/testsuite/runtest.log" + rm -rf -- "$dir" + fi + let cnt++ done diff --git a/testsuite/ash.tests b/testsuite/ash.tests index ce585beb1..183394a20 100755 --- a/testsuite/ash.tests +++ b/testsuite/ash.tests @@ -9,6 +9,10 @@ test -f "$bindir/.config" && . "$bindir/.config" +test x"CONFIG_SCRIPT" = x"y" || exit 0 +test x"CONFIG_HEXDUMP" = x"y" || exit 0 +test x"CONFIG_FEATURE_DEVPTS" = x"y" || exit 0 + # testing "test name" "options" "expected result" "file input" "stdin" if test x"$CONFIG_UNICODE_PRESERVE_BROKEN" = x"y"; then diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index 325664d71..2b8f0d030 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests @@ -69,6 +69,7 @@ ln cpio.testdir/empty cpio.testdir/empty1 ln cpio.testdir/nonempty cpio.testdir/nonempty1 mkdir cpio.testdir2 +optional FEATURE_CPIO_O testing "cpio extracts zero-sized hardlinks 2" \ "find cpio.testdir | cpio -H newc --create | (cd cpio.testdir2 && cpio -i 2>&1); echo \$?; ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ @@ -82,10 +83,12 @@ ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ -rw-r--r-- 1 $user $group 0 solo " \ "" "" +SKIP= # Was trying to create "/usr/bin", correct is "usr/bin". rm -rf cpio.testdir +optional FEATURE_CPIO_P testing "cpio -p with absolute paths" \ "echo /usr/bin | cpio -dp cpio.testdir 2>&1; echo \$?; ls cpio.testdir" \ @@ -95,6 +98,7 @@ ls cpio.testdir" \ usr " \ "" "" +SKIP= # Clean up -- cgit v1.2.3-55-g6feb From 1602a5cdb9b68aec34389961b1c1d134d8b59d07 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 May 2010 04:18:42 +0200 Subject: gen_build_files.sh should be executable Signed-off-by: Denys Vlasenko --- scripts/gen_build_files.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/gen_build_files.sh diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh old mode 100644 new mode 100755 -- cgit v1.2.3-55-g6feb From e3d90a90d43b857a5305808560d485b030a15c0a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 May 2010 05:53:16 +0200 Subject: randomconfig testsuite fixes Signed-off-by: Denys Vlasenko --- testsuite/awk.tests | 6 ++++-- testsuite/expand.tests | 7 +++++-- testsuite/expand/expand-works-like-GNU | 2 ++ testsuite/fold.tests | 4 +++- testsuite/makedevs.tests | 2 ++ testsuite/mdev.tests | 14 ++++++++++++++ testsuite/tar.tests | 6 ++++++ testsuite/tar/tar_with_link_with_size | 2 ++ testsuite/tar/tar_with_prefix_fields | 2 ++ testsuite/unexpand.tests | 4 +++- 10 files changed, 43 insertions(+), 6 deletions(-) diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 3a7c8f4d0..5dea2e983 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests @@ -33,12 +33,14 @@ testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ testing "awk gsub falls back to non-extended-regex" \ "awk 'gsub(\"@(samp|code|file)\{\",\"\");'; echo \$?" "0\n" "" "Hi\n" -tar xjf awk_t1.tar.bz2 +optional FEATURE_SEAMLESS_BZ2 +test x"$SKIP" != x"1" && tar xjf awk_t1.tar.bz2 testing "awk 'gcc build bug'" \ "awk -f awk_t1_opt-functions.awk -f awk_t1_opth-gen.awk /dev/null +SKIP= Q='":"' diff --git a/testsuite/expand.tests b/testsuite/expand.tests index 996631450..357a9ad6b 100755 --- a/testsuite/expand.tests +++ b/testsuite/expand.tests @@ -10,12 +10,15 @@ testing "expand" \ "expand" \ " 12345678 12345678\n" \ "" \ - "\t12345678\t12345678\n" \ + "\t12345678\t12345678\n" +optional UNICODE_SUPPORT testing "expand with unicode characher 0x394" \ "expand" \ "Δ 12345ΔΔΔ 12345678\n" \ "" \ - "Δ\t12345ΔΔΔ\t12345678\n" \ + "Δ\t12345ΔΔΔ\t12345678\n" +SKIP= + exit $FAILCOUNT diff --git a/testsuite/expand/expand-works-like-GNU b/testsuite/expand/expand-works-like-GNU index ee8c793ed..843111275 100644 --- a/testsuite/expand/expand-works-like-GNU +++ b/testsuite/expand/expand-works-like-GNU @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_UNEXPAND + rm -f foo bar echo -e "\ty" | expand -t 3 ../../busybox > foo echo -e "\ty" | busybox unexpand -t 3 ../../busybox > bar diff --git a/testsuite/fold.tests b/testsuite/fold.tests index 17721a180..0197d024d 100755 --- a/testsuite/fold.tests +++ b/testsuite/fold.tests @@ -28,6 +28,7 @@ be preserved is here:>\0< - they must be preserved " \ +optional UNICODE_SUPPORT # The text was taken from English and Ukrainian wikipedia pages testing "fold -sw66 with unicode input" "fold -sw66" \ "\ @@ -54,6 +55,7 @@ Way. каталогом Мессьє та NGC224 за Новим загальним каталогом) — \ спіральна галактика, що знаходиться на відстані приблизно у 2,5 \ мільйони світлових років від нашої планети у сузір'ї Андромеди. \ -На початку ХХІ ст. в центрі галактики виявлено чорну дірку." \ +На початку ХХІ ст. в центрі галактики виявлено чорну дірку." +SKIP= exit $FAILCOUNT diff --git a/testsuite/makedevs.tests b/testsuite/makedevs.tests index b41614f13..5d6b0f248 100755 --- a/testsuite/makedevs.tests +++ b/testsuite/makedevs.tests @@ -16,6 +16,7 @@ FILTER_LS2="sed -e 's/, */,/g' -e 's/ */ /g' | cut -d' ' -f 1-4,9-" rm -rf makedevs.testdir mkdir makedevs.testdir +optional FEATURE_LS_RECURSIVE testing "makedevs -d ../makedevs.device_table.txt ." \ "(cd makedevs.testdir && makedevs -d ../makedevs.device_table.txt . 2>&1); find makedevs.testdir ! -type d | sort | xargs ls -lnR | $FILTER_LS" \ @@ -132,6 +133,7 @@ crw-rw-rw- 1 0 0 1,9 makedevs.testdir/dev/urandom crw-rw-rw- 1 0 0 1,5 makedevs.testdir/dev/zero " \ "" "" +SKIP= # clean up rm -rf makedevs.testdir diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests index 036738e52..a21d9bd0c 100755 --- a/testsuite/mdev.tests +++ b/testsuite/mdev.tests @@ -75,6 +75,7 @@ br--r--r-- 1 2 2 8,0 sda # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 444 >disk/scsiA" >mdev.testdir/etc/mdev.conf +optional FEATURE_LS_RECURSIVE testing "mdev move/symlink rule '>bar/baz'" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -87,10 +88,12 @@ mdev.testdir/dev/disk: br--r--r-- 1 0 0 scsiA " \ "" "" +SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 444 >disk/" >mdev.testdir/etc/mdev.conf +optional FEATURE_LS_RECURSIVE testing "mdev move/symlink rule '>bar/'" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -103,11 +106,13 @@ mdev.testdir/dev/disk: br--r--r-- 1 0 0 sda " \ "" "" +SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* # here we complicate things by having non-matching group 1 and using %0 echo "s([0-9])*d([a-z]+) 0:0 644 >sd/%2_%0" >mdev.testdir/etc/mdev.conf +optional FEATURE_LS_RECURSIVE testing "mdev regexp substring match + replace" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -120,10 +125,12 @@ mdev.testdir/dev/sd: brw-r--r-- 1 0 0 a_sda " \ "" "" +SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf +optional FEATURE_LS_RECURSIVE testing "mdev command" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS" \ @@ -133,10 +140,12 @@ mdev.testdir/dev: brw-r--r-- 1 0 0 8,0 sda " \ "" "" +SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 644 =block/ @echo @echo TEST:\$MDEV" >mdev.testdir/etc/mdev.conf +optional FEATURE_LS_RECURSIVE testing "mdev move and command" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -149,10 +158,12 @@ mdev.testdir/dev/block: brw-r--r-- 1 0 0 sda " \ "" "" +SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "@8,0 0:1 644" >mdev.testdir/etc/mdev.conf +optional FEATURE_LS_RECURSIVE testing "mdev #maj,min and no explicit uid" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS" \ @@ -161,6 +172,7 @@ mdev.testdir/dev: brw-r--r-- 1 0 1 8,0 sda " \ "" "" +SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* @@ -174,6 +186,7 @@ echo "capi 0:0 0660 =capi20" >mdev.testdir/etc/mdev.conf echo "capi([0-9]) 0:0 0660 =capi20.0%1" >>mdev.testdir/etc/mdev.conf echo "capi([0-9]*) 0:0 0660 =capi20.%1" >>mdev.testdir/etc/mdev.conf # mdev invocation with DEVPATH=/class/tty/capi20 was deleting /dev/capi20 +optional FEATURE_LS_RECURSIVE testing "move rule does not delete node with name == device_name" \ "\ env - PATH=$PATH ACTION=add DEVPATH=/class/tty/capi chroot mdev.testdir /mdev 2>&1; @@ -187,6 +200,7 @@ crw-rw---- 1 0 0 191,1 capi20.01 crw-rw---- 1 0 0 191,20 capi20.20 " \ "" "" +SKIP= # clean up rm -rf mdev.testdir diff --git a/testsuite/tar.tests b/testsuite/tar.tests index a96382932..ecd212fbf 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -9,6 +9,7 @@ mkdir tar.tempdir && cd tar.tempdir || exit 1 # testing "test name" "script" "expected result" "file input" "stdin" +optional FEATURE_TAR_CREATE testing "tar hardlinks and repeated files" '\ rm -rf input_* test.tar 2>/dev/null >input_hard1 @@ -39,7 +40,9 @@ drwxr-xr-x input_dir -rw-r--r-- input_hard2 " \ "" "" +SKIP= +optional FEATURE_TAR_CREATE testing "tar hardlinks mode" '\ rm -rf input_* test.tar 2>/dev/null >input_hard1 @@ -68,7 +71,9 @@ dr-xr-x--- input_dir -rwxr----x input_hard2 " \ "" "" +SKIP= +optional FEATURE_TAR_CREATE testing "tar symlinks mode" '\ rm -rf input_* test.tar 2>/dev/null >input_file @@ -97,6 +102,7 @@ dr-xr-x--- input_dir lrwxrwxrwx input_file " \ "" "" +SKIP= optional FEATURE_TAR_LONG_OPTIONS testing "tar --overwrite" "\ diff --git a/testsuite/tar/tar_with_link_with_size b/testsuite/tar/tar_with_link_with_size index 5b61cc70b..774cd5698 100644 --- a/testsuite/tar/tar_with_link_with_size +++ b/testsuite/tar/tar_with_link_with_size @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_TAR_UNAME_GNAME + # This tarball contains a softlink with size field != 0. # If not ignored, it makes hext header to be skipped # and data to be read as a header. diff --git a/testsuite/tar/tar_with_prefix_fields b/testsuite/tar/tar_with_prefix_fields index 1c7124d52..56dcac59d 100644 --- a/testsuite/tar/tar_with_prefix_fields +++ b/testsuite/tar/tar_with_prefix_fields @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_TAR_UNAME_GNAME + tar1_bz2() { $ECHO -ne "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\x12\xd1\x86\x30\x00\x0c" diff --git a/testsuite/unexpand.tests b/testsuite/unexpand.tests index 1af2fdc5f..a48e3214e 100755 --- a/testsuite/unexpand.tests +++ b/testsuite/unexpand.tests @@ -30,7 +30,9 @@ testing "unexpand case 7" "unexpand" \ testing "unexpand case 8" "unexpand" \ "a b\n" "" "a b\n" \ +optional UNICODE_SUPPORT testing "unexpand with unicode characher 0x394" "unexpand" \ - "1ΔΔΔ5\t99999\n" "" "1ΔΔΔ5 99999\n" \ + "1ΔΔΔ5\t99999\n" "" "1ΔΔΔ5 99999\n" +SKIP= exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 8e3aff0ce03cbc44b2fa80fb62fa2378a5212a5a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 May 2010 11:00:11 +0200 Subject: more randomconfig testsuite fixes Signed-off-by: Denys Vlasenko --- scripts/gen_build_files.sh | 80 +++++++++++++++++++++++----------------------- testsuite/awk.tests | 2 +- testsuite/cpio.tests | 2 +- testsuite/makedevs.tests | 2 +- testsuite/mdev.tests | 22 +++++++++---- testsuite/testing.sh | 16 +++++----- 6 files changed, 66 insertions(+), 58 deletions(-) diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index 3d757500c..2baefa2ee 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -3,52 +3,52 @@ test $# -ge 2 || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } # cd to objtree -cd "$2" || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } +cd -- "$2" || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } srctree="$1" find -type d | while read; do - d="$REPLY" - - src="$srctree/$d/Kbuild.src" - dst="$d/Kbuild" - if test -f "$src"; then - echo " CHK $dst" - - s=`sed -n 's@^//kbuild:@@p' "$srctree/$d"/*.c` - echo "# DO NOT EDIT. This file is generated from Kbuild.src" >"$dst.$$.tmp" - while read; do - test x"$REPLY" = x"INSERT" && REPLY="$s" - printf "%s\n" "$REPLY" - done <"$src" >>"$dst.$$.tmp" - - if test -f "$dst" && cmp -s "$dst.$$.tmp" "$dst"; then - rm "$dst.$$.tmp" - else - echo " GEN $dst" - mv "$dst.$$.tmp" "$dst" + d="$REPLY" + + src="$srctree/$d/Kbuild.src" + dst="$d/Kbuild" + if test -f "$src"; then + echo " CHK $dst" + + s=`sed -n 's@^//kbuild:@@p' -- "$srctree/$d"/*.c` + echo "# DO NOT EDIT. This file is generated from Kbuild.src" >"$dst.$$.tmp" + while read; do + test x"$REPLY" = x"INSERT" && REPLY="$s" + printf "%s\n" "$REPLY" + done <"$src" >>"$dst.$$.tmp" + + if test -f "$dst" && cmp -s "$dst.$$.tmp" "$dst"; then + rm -- "$dst.$$.tmp" + else + echo " GEN $dst" + mv -- "$dst.$$.tmp" "$dst" + fi fi - fi - - src="$srctree/$d/Config.src" - dst="$d/Config.in" - if test -f "$src"; then - echo " CHK $dst" - - s=`sed -n 's@^//config:@@p' "$srctree/$d"/*.c` - echo "# DO NOT EDIT. This file is generated from Config.src" >"$dst.$$.tmp" - while read; do - test x"$REPLY" = x"INSERT" && REPLY="$s" - printf "%s\n" "$REPLY" - done <"$src" >>"$dst.$$.tmp" - - if test -f "$dst" && cmp -s "$dst.$$.tmp" "$dst"; then - rm "$dst.$$.tmp" - else - echo " GEN $dst" - mv "$dst.$$.tmp" "$dst" + + src="$srctree/$d/Config.src" + dst="$d/Config.in" + if test -f "$src"; then + echo " CHK $dst" + + s=`sed -n 's@^//config:@@p' -- "$srctree/$d"/*.c` + echo "# DO NOT EDIT. This file is generated from Config.src" >"$dst.$$.tmp" + while read; do + test x"$REPLY" = x"INSERT" && REPLY="$s" + printf "%s\n" "$REPLY" + done <"$src" >>"$dst.$$.tmp" + + if test -f "$dst" && cmp -s "$dst.$$.tmp" "$dst"; then + rm -- "$dst.$$.tmp" + else + echo " GEN $dst" + mv -- "$dst.$$.tmp" "$dst" + fi fi - fi done diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 5dea2e983..efa03a79a 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests @@ -33,7 +33,7 @@ testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ testing "awk gsub falls back to non-extended-regex" \ "awk 'gsub(\"@(samp|code|file)\{\",\"\");'; echo \$?" "0\n" "" "Hi\n" -optional FEATURE_SEAMLESS_BZ2 +optional TAR BUNZIP2 FEATURE_SEAMLESS_BZ2 test x"$SKIP" != x"1" && tar xjf awk_t1.tar.bz2 testing "awk 'gcc build bug'" \ "awk -f awk_t1_opt-functions.awk -f awk_t1_opth-gen.awk &1); echo \$?; ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ diff --git a/testsuite/makedevs.tests b/testsuite/makedevs.tests index 5d6b0f248..72fc933d3 100755 --- a/testsuite/makedevs.tests +++ b/testsuite/makedevs.tests @@ -16,7 +16,7 @@ FILTER_LS2="sed -e 's/, */,/g' -e 's/ */ /g' | cut -d' ' -f 1-4,9-" rm -rf makedevs.testdir mkdir makedevs.testdir -optional FEATURE_LS_RECURSIVE +optional FEATURE_MAKEDEVS_TABLE FEATURE_FIND_NOT FEATURE_FIND_TYPE FEATURE_LS_RECURSIVE testing "makedevs -d ../makedevs.device_table.txt ." \ "(cd makedevs.testdir && makedevs -d ../makedevs.device_table.txt . 2>&1); find makedevs.testdir ! -type d | sort | xargs ls -lnR | $FILTER_LS" \ diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests index a21d9bd0c..270f6292e 100755 --- a/testsuite/mdev.tests +++ b/testsuite/mdev.tests @@ -27,6 +27,7 @@ echo "8:0" >mdev.testdir/sys/block/sda/dev # env - PATH=$PATH: on some systems chroot binary won't otherwise be found +optional STATIC testing "mdev add /block/sda" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -ln mdev.testdir/dev | $FILTER_LS" \ @@ -34,11 +35,13 @@ testing "mdev add /block/sda" \ brw-rw---- 1 0 0 8,0 sda " \ "" "" +SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo ".* 1:1 666" >mdev.testdir/etc/mdev.conf echo "sda 2:2 444" >>mdev.testdir/etc/mdev.conf +optional STATIC FEATURE_MDEV_CONF testing "mdev stops on first rule" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -ln mdev.testdir/dev | $FILTER_LS" \ @@ -46,11 +49,13 @@ testing "mdev stops on first rule" \ brw-rw-rw- 1 1 1 8,0 sda " \ "" "" +SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "-.* 1:1 666" >mdev.testdir/etc/mdev.conf echo "sda 2:2 444" >>mdev.testdir/etc/mdev.conf +optional STATIC FEATURE_MDEV_CONF testing "mdev does not stop on dash-rule" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -ln mdev.testdir/dev | $FILTER_LS" \ @@ -58,12 +63,14 @@ testing "mdev does not stop on dash-rule" \ br--r--r-- 1 2 2 8,0 sda " \ "" "" +SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "\$MODALIAS=qw 1:1 666" >mdev.testdir/etc/mdev.conf echo "\$MODALIAS=qw. 2:2 444" >>mdev.testdir/etc/mdev.conf echo "\$MODALIAS=qw. 3:3 400" >>mdev.testdir/etc/mdev.conf +optional STATIC FEATURE_MDEV_CONF testing "mdev \$ENVVAR=regex match" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda MODALIAS=qwe chroot mdev.testdir /mdev 2>&1; ls -ln mdev.testdir/dev | $FILTER_LS" \ @@ -71,11 +78,12 @@ testing "mdev \$ENVVAR=regex match" \ br--r--r-- 1 2 2 8,0 sda " \ "" "" +SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 444 >disk/scsiA" >mdev.testdir/etc/mdev.conf -optional FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE testing "mdev move/symlink rule '>bar/baz'" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -93,7 +101,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 444 >disk/" >mdev.testdir/etc/mdev.conf -optional FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE testing "mdev move/symlink rule '>bar/'" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -112,7 +120,7 @@ SKIP= rm -rf mdev.testdir/dev/* # here we complicate things by having non-matching group 1 and using %0 echo "s([0-9])*d([a-z]+) 0:0 644 >sd/%2_%0" >mdev.testdir/etc/mdev.conf -optional FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE testing "mdev regexp substring match + replace" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -130,7 +138,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf -optional FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE testing "mdev command" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS" \ @@ -145,7 +153,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 644 =block/ @echo @echo TEST:\$MDEV" >mdev.testdir/etc/mdev.conf -optional FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE testing "mdev move and command" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -163,7 +171,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "@8,0 0:1 644" >mdev.testdir/etc/mdev.conf -optional FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE testing "mdev #maj,min and no explicit uid" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS" \ @@ -186,7 +194,7 @@ echo "capi 0:0 0660 =capi20" >mdev.testdir/etc/mdev.conf echo "capi([0-9]) 0:0 0660 =capi20.0%1" >>mdev.testdir/etc/mdev.conf echo "capi([0-9]*) 0:0 0660 =capi20.%1" >>mdev.testdir/etc/mdev.conf # mdev invocation with DEVPATH=/class/tty/capi20 was deleting /dev/capi20 -optional FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE testing "move rule does not delete node with name == device_name" \ "\ env - PATH=$PATH ACTION=add DEVPATH=/class/tty/capi chroot mdev.testdir /mdev 2>&1; diff --git a/testsuite/testing.sh b/testsuite/testing.sh index 22c640faf..65a0f6529 100755 --- a/testsuite/testing.sh +++ b/testsuite/testing.sh @@ -54,14 +54,14 @@ test x"$ECHO" != x"" || { optional() { - option=`echo ":$OPTIONFLAGS:" | grep ":$1:"` - # Not set? - if [ -z "$1" ] || [ -z "$OPTIONFLAGS" ] || [ ${#option} -ne 0 ] - then - SKIP= - return - fi - SKIP=1 + SKIP= + while test "$1"; do + if test x"${OPTIONFLAGS/*:$1:*/y}" != x"y"; then + SKIP=1 + return + fi + shift + done } # The testing function -- cgit v1.2.3-55-g6feb From 6334390aef2eb52cc827a6d18f942b2b8a04ef59 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 May 2010 12:25:36 +0200 Subject: remove duplicate comment Signed-off-by: Denys Vlasenko --- debianutils/run_parts.c | 1 - 1 file changed, 1 deletion(-) diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c index 37e8487e1..ba05897f9 100644 --- a/debianutils/run_parts.c +++ b/debianutils/run_parts.c @@ -121,7 +121,6 @@ int run_parts_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS applet_long_options = runparts_longopts; #endif - /* We require exactly one argument: the directory name */ /* We require exactly one argument: the directory name */ opt_complementary = "=1:a::"; getopt32(argv, "ra:u:t"IF_FEATURE_RUN_PARTS_FANCY("l"), &arg_list, &umask_p); -- cgit v1.2.3-55-g6feb From bfa1b2e8e8aaddcf849011a12cb2ac634b27f339 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 May 2010 03:53:57 +0200 Subject: randomtest fixes Signed-off-by: Denys Vlasenko --- libbb/read.c | 61 ++++++++++++------------ testsuite/ar.tests | 4 +- testsuite/awk.tests | 2 + testsuite/busybox.tests | 7 +-- testsuite/cpio.tests | 2 + testsuite/diff.tests | 10 ++++ testsuite/du/du-h-works | 2 + testsuite/du/du-l-works | 2 + testsuite/du/du-m-works | 2 + testsuite/du/du-s-works | 2 + testsuite/du/du-works | 2 + testsuite/echo/echo-does-not-print-newline | 2 + testsuite/echo/echo-prints-slash-zero | 2 + testsuite/find/find-supports-minus-xdev | 2 + testsuite/ls/ls-1-works | 2 + testsuite/ls/ls-h-works | 2 + testsuite/makedevs.tests | 2 +- testsuite/md5sum/md5sum-verifies-non-binary-file | 2 + testsuite/mdev.tests | 22 ++++----- testsuite/mount.tests | 15 +++--- testsuite/od.tests | 2 + testsuite/patch.tests | 2 + testsuite/pidof.tests | 4 +- testsuite/sort.tests | 2 +- testsuite/tail/tail-works | 2 + testsuite/tar.tests | 6 +-- testsuite/tar/tar_with_prefix_fields | 1 + testsuite/tr.tests | 6 +++ testsuite/tr/tr-d-alnum-works | 2 + testsuite/tr/tr-rejects-wrong-class | 2 + testsuite/tr/tr-works | 2 + 31 files changed, 120 insertions(+), 58 deletions(-) diff --git a/libbb/read.c b/libbb/read.c index 21e005c6f..f3af144f0 100644 --- a/libbb/read.c +++ b/libbb/read.c @@ -321,44 +321,45 @@ int FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) /* .gz and .bz2 both have 2-byte signature, and their * unpack_XXX_stream wants this header skipped. */ xread(fd, &magic, 2); -#if ENABLE_FEATURE_SEAMLESS_GZ + if (ENABLE_FEATURE_SEAMLESS_GZ + && magic[0] == 0x1f && magic[1] == 0x8b + ) { # if BB_MMU - xformer = unpack_gz_stream; + xformer = unpack_gz_stream; # else - xformer_prog = "gunzip"; + xformer_prog = "gunzip"; # endif -#endif - if (!ENABLE_FEATURE_SEAMLESS_GZ - || magic[0] != 0x1f || magic[1] != 0x8b + goto found_magic; + } + if (ENABLE_FEATURE_SEAMLESS_BZ2 + && magic[0] == 'B' && magic[1] == 'Z' ) { - if (!ENABLE_FEATURE_SEAMLESS_BZ2 - || magic[0] != 'B' || magic[1] != 'Z' - ) { - +# if BB_MMU + xformer = unpack_bz2_stream; +# else + xformer_prog = "bunzip2"; +# endif + goto found_magic; + } // TODO: xz format support. rpm adopted it, "rpm -i FILE.rpm" badly needs this. // Signature: 0xFD, '7', 'z', 'X', 'Z', 0x00 // More info at: http://tukaani.org/xz/xz-file-format.txt - if (fail_if_not_detected) - bb_error_msg_and_die("no gzip" - IF_FEATURE_SEAMLESS_BZ2("/bzip2") - " magic"); - xlseek(fd, -2, SEEK_CUR); - return fd; - } -#if BB_MMU - xformer = unpack_bz2_stream; -#else - xformer_prog = "bunzip2"; -#endif - } else { -#if !BB_MMU - /* NOMMU version of open_transformer execs - * an external unzipper that wants - * file position at the start of the file */ - xlseek(fd, -2, SEEK_CUR); -#endif - } + /* No known magic seen */ + if (fail_if_not_detected) + bb_error_msg_and_die("no gzip" + IF_FEATURE_SEAMLESS_BZ2("/bzip2") + " magic"); + xlseek(fd, -2, SEEK_CUR); + return fd; + + found_magic: +# if !BB_MMU + /* NOMMU version of open_transformer execs + * an external unzipper that wants + * file position at the start of the file */ + xlseek(fd, -2, SEEK_CUR); +# endif open_transformer(fd, xformer, xformer_prog); return fd; diff --git a/testsuite/ar.tests b/testsuite/ar.tests index f112eb64a..4630d08a4 100755 --- a/testsuite/ar.tests +++ b/testsuite/ar.tests @@ -18,10 +18,10 @@ testing "ar creates archives" \ rm test.a testing "ar replaces things in archives" \ - "echo 'blah!' >file1 && echo 'blast!'> file2 && ar cr test.a README file1 file2 && mv file2 file1 && ar cr test.a file1 && ar p test.a file1" \ + "echo 'blah!' >file1 && echo 'blast!' >file2 && ar cr test.a README file1 file2 && mv file2 file1 && ar cr test.a file1 && ar p test.a file1" \ "blast!\n" \ "" \ "" -rm test.a +rm test.a file1 file1 2>/dev/null exit $FAILCOUNT diff --git a/testsuite/awk.tests b/testsuite/awk.tests index efa03a79a..0691a7972 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests @@ -18,9 +18,11 @@ testing "awk -F case 7" "awk -F '[#]' '{ print NF }'" "5\n" "" "z##abc##zz\n" # 4294967295 = 0xffffffff testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n" +optional DESKTOP testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n" testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n" testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" +SKIP= # long field seps requiring regex testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ diff --git a/testsuite/busybox.tests b/testsuite/busybox.tests index 6eeb3251d..18ac36fc4 100755 --- a/testsuite/busybox.tests +++ b/testsuite/busybox.tests @@ -10,8 +10,9 @@ HELPDUMP=`true | busybox 2>&1 | cat` # We need to test under calling the binary under other names. - +optional SHOW_USAGE testing "busybox --help busybox" "true | busybox --help busybox 2>&1 | cat" "$HELPDUMP\n\n" "" "" +SKIP= ln -s `which busybox` busybox-suffix for i in busybox ./busybox-suffix @@ -26,11 +27,11 @@ do testing "$i --help" "$i --help 2>&1" "$HELPDUMP\n\n" "" "" - optional CAT + optional SHOW_USAGE CAT testing "" "$i cat" "moo" "" "moo" testing "$i --help cat" "$i --help cat 2>&1 | grep print" \ "Concatenate FILEs and print them to stdout\n" "" "" - optional "" + SKIP= testing "$i --help unknown" "$i --help unknown 2>&1" \ "unknown: applet not found\n" "" "" diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index b4c41dd9a..8cb8b787b 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests @@ -31,6 +31,7 @@ rm -rf cpio.testdir cpio.testdir2 2>/dev/null # testing "test name" "command" "expected result" "file input" "stdin" +optional FEATURE_LS_SORTFILES testing "cpio extracts zero-sized hardlinks" \ "$ECHO -ne '$hexdump' | bzcat | cpio -i 2>&1; echo \$?; ls -ln cpio.testdir | $FILTER_LS" \ @@ -41,6 +42,7 @@ ls -ln cpio.testdir | $FILTER_LS" \ -rw-r--r-- 2 $user $group 0 y " \ "" "" +SKIP= test x"$SKIP_KNOWN_BUGS" = x"" && { diff --git a/testsuite/diff.tests b/testsuite/diff.tests index 72ebb6c4c..06d5a4fd7 100755 --- a/testsuite/diff.tests +++ b/testsuite/diff.tests @@ -106,6 +106,7 @@ rm -rf diff1 diff2 mkdir diff1 diff2 diff2/subdir echo qwe >diff1/- echo asd >diff2/subdir/- +optional FEATURE_DIFF_DIR testing "diff diff1 diff2/subdir" \ "diff -ur diff1 diff2/subdir | $TRIM_TAB" \ "\ @@ -116,8 +117,10 @@ testing "diff diff1 diff2/subdir" \ +asd " \ "" "" +SKIP= # using directory structure from prev test... +optional FEATURE_DIFF_DIR testing "diff dir dir2/file/-" \ "diff -ur diff1 diff2/subdir/- | $TRIM_TAB" \ "\ @@ -128,10 +131,12 @@ testing "diff dir dir2/file/-" \ +asd " \ "" "" +SKIP= # using directory structure from prev test... mkdir diff1/test mkfifo diff2/subdir/test +optional FEATURE_DIFF_DIR testing "diff of dir and fifo" \ "diff -ur diff1 diff2/subdir | $TRIM_TAB" \ "\ @@ -143,10 +148,12 @@ testing "diff of dir and fifo" \ Only in diff2/subdir: test " \ "" "" +SKIP= # using directory structure from prev test... rmdir diff1/test echo >diff1/test +optional FEATURE_DIFF_DIR testing "diff of file and fifo" \ "diff -ur diff1 diff2/subdir | $TRIM_TAB" \ "\ @@ -158,9 +165,11 @@ testing "diff of file and fifo" \ File diff2/subdir/test is not a regular file or directory and was skipped " \ "" "" +SKIP= # using directory structure from prev test... mkfifo diff1/test2 +optional FEATURE_DIFF_DIR testing "diff -rN does not read non-regular files" \ "diff -urN diff1 diff2/subdir | $TRIM_TAB" \ "\ @@ -173,6 +182,7 @@ File diff2/subdir/test is not a regular file or directory and was skipped File diff1/test2 is not a regular file or directory and was skipped " \ "" "" +SKIP= # clean up rm -rf diff1 diff2 diff --git a/testsuite/du/du-h-works b/testsuite/du/du-h-works index 3f8ff3d0b..a1b4b4905 100644 --- a/testsuite/du/du-h-works +++ b/testsuite/du/du-h-works @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_HUMAN_READABLE + d=/bin du -h "$d" > logfile.gnu busybox du -h "$d" > logfile.bb diff --git a/testsuite/du/du-l-works b/testsuite/du/du-l-works index c3d2ec0c1..64dcf8726 100644 --- a/testsuite/du/du-l-works +++ b/testsuite/du/du-l-works @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K + d=/bin du -l "$d" > logfile.gnu busybox du -l "$d" > logfile.bb diff --git a/testsuite/du/du-m-works b/testsuite/du/du-m-works index bf0a90e1b..6e733c016 100644 --- a/testsuite/du/du-m-works +++ b/testsuite/du/du-m-works @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_HUMAN_READABLE + d=/bin du -m "$d" > logfile.gnu busybox du -m "$d" > logfile.bb diff --git a/testsuite/du/du-s-works b/testsuite/du/du-s-works index ae970772a..0c870ceb5 100644 --- a/testsuite/du/du-s-works +++ b/testsuite/du/du-s-works @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K + d=/bin du -s "$d" > logfile.gnu busybox du -s "$d" > logfile.bb diff --git a/testsuite/du/du-works b/testsuite/du/du-works index 46a336dc3..4db684a9b 100644 --- a/testsuite/du/du-works +++ b/testsuite/du/du-works @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K + d=/bin du "$d" > logfile.gnu busybox du "$d" > logfile.bb diff --git a/testsuite/echo/echo-does-not-print-newline b/testsuite/echo/echo-does-not-print-newline index 2ed03caf5..2857c0d13 100644 --- a/testsuite/echo/echo-does-not-print-newline +++ b/testsuite/echo/echo-does-not-print-newline @@ -1 +1,3 @@ +# FEATURE: CONFIG_FEATURE_FANCY_ECHO + test `busybox echo -n word | wc -c` -eq 4 diff --git a/testsuite/echo/echo-prints-slash-zero b/testsuite/echo/echo-prints-slash-zero index d2466326f..d97ed8e66 100644 --- a/testsuite/echo/echo-prints-slash-zero +++ b/testsuite/echo/echo-prints-slash-zero @@ -1 +1,3 @@ +# FEATURE: CONFIG_FEATURE_FANCY_ECHO + test "`busybox echo -e -n 'msg\n\0' | od -t x1 | head -n 1`" = "0000000 6d 73 67 0a 00" diff --git a/testsuite/find/find-supports-minus-xdev b/testsuite/find/find-supports-minus-xdev index 4c559a1f4..c807fc8f2 100644 --- a/testsuite/find/find-supports-minus-xdev +++ b/testsuite/find/find-supports-minus-xdev @@ -1 +1,3 @@ +# FEATURE: CONFIG_FEATURE_FIND_XDEV + busybox find . -xdev >/dev/null 2>&1 diff --git a/testsuite/ls/ls-1-works b/testsuite/ls/ls-1-works index 885694920..71ab9a66b 100644 --- a/testsuite/ls/ls-1-works +++ b/testsuite/ls/ls-1-works @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_LS_SORTFILES + [ -n "$d" ] || d=.. LC_ALL=C ls -1 "$d" > logfile.gnu LC_ALL=C busybox ls -1 "$d" > logfile.bb diff --git a/testsuite/ls/ls-h-works b/testsuite/ls/ls-h-works index 0c83f7cc5..60016bac1 100644 --- a/testsuite/ls/ls-h-works +++ b/testsuite/ls/ls-h-works @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_LS_SORTFILES CONFIG_FEATURE_HUMAN_READABLE + [ -n "$d" ] || d=.. LC_ALL=C ls -h "$d" > logfile.gnu LC_ALL=C busybox ls -h "$d" > logfile.bb diff --git a/testsuite/makedevs.tests b/testsuite/makedevs.tests index 72fc933d3..f69b4a6b1 100755 --- a/testsuite/makedevs.tests +++ b/testsuite/makedevs.tests @@ -16,7 +16,7 @@ FILTER_LS2="sed -e 's/, */,/g' -e 's/ */ /g' | cut -d' ' -f 1-4,9-" rm -rf makedevs.testdir mkdir makedevs.testdir -optional FEATURE_MAKEDEVS_TABLE FEATURE_FIND_NOT FEATURE_FIND_TYPE FEATURE_LS_RECURSIVE +optional FEATURE_MAKEDEVS_TABLE FEATURE_FIND_NOT FEATURE_FIND_TYPE FEATURE_LS_RECURSIVE FEATURE_LS_SORTFILES testing "makedevs -d ../makedevs.device_table.txt ." \ "(cd makedevs.testdir && makedevs -d ../makedevs.device_table.txt . 2>&1); find makedevs.testdir ! -type d | sort | xargs ls -lnR | $FILTER_LS" \ diff --git a/testsuite/md5sum/md5sum-verifies-non-binary-file b/testsuite/md5sum/md5sum-verifies-non-binary-file index 8566a234d..1df818eb5 100644 --- a/testsuite/md5sum/md5sum-verifies-non-binary-file +++ b/testsuite/md5sum/md5sum-verifies-non-binary-file @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_MD5_SHA1_SUM_CHECK + touch foo md5sum foo > bar busybox md5sum -c bar diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests index 270f6292e..0b4525483 100755 --- a/testsuite/mdev.tests +++ b/testsuite/mdev.tests @@ -27,7 +27,7 @@ echo "8:0" >mdev.testdir/sys/block/sda/dev # env - PATH=$PATH: on some systems chroot binary won't otherwise be found -optional STATIC +optional STATIC FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "mdev add /block/sda" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -ln mdev.testdir/dev | $FILTER_LS" \ @@ -41,7 +41,7 @@ SKIP= rm -rf mdev.testdir/dev/* echo ".* 1:1 666" >mdev.testdir/etc/mdev.conf echo "sda 2:2 444" >>mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF +optional STATIC FEATURE_MDEV_CONF FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "mdev stops on first rule" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -ln mdev.testdir/dev | $FILTER_LS" \ @@ -55,7 +55,7 @@ SKIP= rm -rf mdev.testdir/dev/* echo "-.* 1:1 666" >mdev.testdir/etc/mdev.conf echo "sda 2:2 444" >>mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF +optional STATIC FEATURE_MDEV_CONF FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "mdev does not stop on dash-rule" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -ln mdev.testdir/dev | $FILTER_LS" \ @@ -70,7 +70,7 @@ rm -rf mdev.testdir/dev/* echo "\$MODALIAS=qw 1:1 666" >mdev.testdir/etc/mdev.conf echo "\$MODALIAS=qw. 2:2 444" >>mdev.testdir/etc/mdev.conf echo "\$MODALIAS=qw. 3:3 400" >>mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF +optional STATIC FEATURE_MDEV_CONF FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "mdev \$ENVVAR=regex match" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda MODALIAS=qwe chroot mdev.testdir /mdev 2>&1; ls -ln mdev.testdir/dev | $FILTER_LS" \ @@ -83,7 +83,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 444 >disk/scsiA" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "mdev move/symlink rule '>bar/baz'" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -101,7 +101,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 444 >disk/" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "mdev move/symlink rule '>bar/'" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -120,7 +120,7 @@ SKIP= rm -rf mdev.testdir/dev/* # here we complicate things by having non-matching group 1 and using %0 echo "s([0-9])*d([a-z]+) 0:0 644 >sd/%2_%0" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "mdev regexp substring match + replace" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -138,7 +138,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "mdev command" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS" \ @@ -153,7 +153,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 644 =block/ @echo @echo TEST:\$MDEV" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "mdev move and command" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -171,7 +171,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "@8,0 0:1 644" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "mdev #maj,min and no explicit uid" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS" \ @@ -194,7 +194,7 @@ echo "capi 0:0 0660 =capi20" >mdev.testdir/etc/mdev.conf echo "capi([0-9]) 0:0 0660 =capi20.0%1" >>mdev.testdir/etc/mdev.conf echo "capi([0-9]*) 0:0 0660 =capi20.%1" >>mdev.testdir/etc/mdev.conf # mdev invocation with DEVPATH=/class/tty/capi20 was deleting /dev/capi20 -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME testing "move rule does not delete node with name == device_name" \ "\ env - PATH=$PATH ACTION=add DEVPATH=/class/tty/capi chroot mdev.testdir /mdev 2>&1; diff --git a/testsuite/mount.tests b/testsuite/mount.tests index 043586f05..ee13ec285 100755 --- a/testsuite/mount.tests +++ b/testsuite/mount.tests @@ -4,16 +4,19 @@ . ./testing.sh +test -f "$bindir/.config" && . "$bindir/.config" + test "`id -u`" = 0 || { - echo "SKIPPED: must be root to test this" + echo "SKIPPED: mount (must be root to test this)" exit 0 } -optional MKFS_MINIX -if [ -n "$SKIP" ] -then - echo "SKIPPED: mount" - exit 0 +if test x"$CONFIG_MKFS_MINIX" != x"y" \ +|| test x"$CONFIG_FEATURE_MINIX2" != x"y" \ +|| test x"$CONFIG_FEATURE_DEVFS" = x"y" \ +; then + echo "SKIPPED: mount" + exit 0 fi testdir=$PWD/testdir diff --git a/testsuite/od.tests b/testsuite/od.tests index 0bf1f4c54..a2d015ad7 100755 --- a/testsuite/od.tests +++ b/testsuite/od.tests @@ -6,6 +6,7 @@ # testing "test name" "options" "expected result" "file input" "stdin" +optional DESKTOP testing "od -b" \ "od -b" \ "\ @@ -13,5 +14,6 @@ testing "od -b" \ 0000005 " \ "" "HELLO" +SKIP= exit $FAILCOUNT diff --git a/testsuite/patch.tests b/testsuite/patch.tests index f3e607186..749d936ea 100755 --- a/testsuite/patch.tests +++ b/testsuite/patch.tests @@ -123,4 +123,6 @@ abc +456 " \ +rm input.orig 2>/dev/null + exit $FAILCOUNT diff --git a/testsuite/pidof.tests b/testsuite/pidof.tests index 45df1a958..624b0a720 100755 --- a/testsuite/pidof.tests +++ b/testsuite/pidof.tests @@ -20,12 +20,14 @@ testing "pidof this" "pidof pidof.tests | grep -o -w $$" "$$\n" "" "" optional FEATURE_PIDOF_SINGLE testing "pidof -s" "pidof -s init" "1\n" "" "" +SKIP= -optional FEATURE_PIDOF_OMIT +optional FEATURE_PIDOF_OMIT FEATURE_PIDOF_SINGLE # This test fails now because process name matching logic has changed, # but new logic is not "wrong" either... see find_pid_by_name.c comments #testing "pidof -o %PPID" "pidof -o %PPID pidof.tests | grep -o -w $$" "" "" "" testing "pidof -o %PPID NOP" "pidof -o %PPID -s init" "1\n" "" "" testing "pidof -o init" "pidof -o 1 init | grep -o -w 1" "" "" "" +SKIP= exit $FAILCOUNT diff --git a/testsuite/sort.tests b/testsuite/sort.tests index 72df80b1f..8a810f8d4 100755 --- a/testsuite/sort.tests +++ b/testsuite/sort.tests @@ -118,7 +118,7 @@ testing "sort key doesn't strip leading blanks, disables fallback global sort" \ "sort -n -k2 -t ' '" " a \n 1 \n 2 \n" "" " 2 \n 1 \n a \n" testing "sort file in place" \ -"strace -oZZZ sort -o input input && cat input" "\ +"sort -o input input && cat input" "\ 111 222 " "\ diff --git a/testsuite/tail/tail-works b/testsuite/tail/tail-works index f3434d1a9..50eca136e 100644 --- a/testsuite/tail/tail-works +++ b/testsuite/tail/tail-works @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_INCLUDE_SUSv2 + $ECHO -ne "abc\ndef\n123\n" >input $ECHO -ne "def\n123\n" >logfile.ok busybox tail -2 input > logfile.bb diff --git a/testsuite/tar.tests b/testsuite/tar.tests index ecd212fbf..8599b79fc 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -9,7 +9,7 @@ mkdir tar.tempdir && cd tar.tempdir || exit 1 # testing "test name" "script" "expected result" "file input" "stdin" -optional FEATURE_TAR_CREATE +optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES testing "tar hardlinks and repeated files" '\ rm -rf input_* test.tar 2>/dev/null >input_hard1 @@ -42,7 +42,7 @@ drwxr-xr-x input_dir "" "" SKIP= -optional FEATURE_TAR_CREATE +optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES testing "tar hardlinks mode" '\ rm -rf input_* test.tar 2>/dev/null >input_hard1 @@ -73,7 +73,7 @@ dr-xr-x--- input_dir "" "" SKIP= -optional FEATURE_TAR_CREATE +optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES testing "tar symlinks mode" '\ rm -rf input_* test.tar 2>/dev/null >input_file diff --git a/testsuite/tar/tar_with_prefix_fields b/testsuite/tar/tar_with_prefix_fields index 56dcac59d..8c1fda795 100644 --- a/testsuite/tar/tar_with_prefix_fields +++ b/testsuite/tar/tar_with_prefix_fields @@ -1,4 +1,5 @@ # FEATURE: CONFIG_FEATURE_TAR_UNAME_GNAME +# FEATURE: CONFIG_DESKTOP tar1_bz2() { diff --git a/testsuite/tr.tests b/testsuite/tr.tests index 9706056c9..a1f83bfc6 100755 --- a/testsuite/tr.tests +++ b/testsuite/tr.tests @@ -15,17 +15,23 @@ testing "tr understands 0-9A-F" \ "tr -cd '[0-9A-F]'" \ "19AF" "" "19AFH\n" +optional CONFIG_FEATURE_TR_CLASSES testing "tr understands [:xdigit:]" \ "tr -cd '[:xdigit:]'" \ "19AF" "" "19AFH\n" +SKIP= +optional CONFIG_FEATURE_TR_CLASSES testing "tr does not stop after [:digit:]" \ "tr '[:digit:]y-z' 111111111123" \ "111abcx23\n" "" "789abcxyz\n" +SKIP= +optional CONFIG_FEATURE_TR_CLASSES testing "tr has correct xdigit sequence" \ "tr '[:xdigit:]Gg' 1111111151242222333330xX" \ "#1111111151242222x333330X\n" "" \ "#0123456789ABCDEFGabcdefg\n" +SKIP= exit $FAILCOUNT diff --git a/testsuite/tr/tr-d-alnum-works b/testsuite/tr/tr-d-alnum-works index d440f8f3b..6540ea527 100644 --- a/testsuite/tr/tr-d-alnum-works +++ b/testsuite/tr/tr-d-alnum-works @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_TR_CLASSES + echo testing | tr -d '[[:alnum:]]' > logfile.gnu echo testing | busybox tr -d '[[:alnum:]]' > logfile.bb diff --git a/testsuite/tr/tr-rejects-wrong-class b/testsuite/tr/tr-rejects-wrong-class index 97539360d..1d488a3df 100644 --- a/testsuite/tr/tr-rejects-wrong-class +++ b/testsuite/tr/tr-rejects-wrong-class @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_TR_CLASSES + echo t12esting | tr -d '[[:alpha:]]' > logfile.gnu echo t12esting | tr -d '[:alpha:]' >> logfile.gnu echo t12esting | tr -d '[[:alpha:]' >> logfile.gnu diff --git a/testsuite/tr/tr-works b/testsuite/tr/tr-works index 2c0a9d196..3783971ce 100644 --- a/testsuite/tr/tr-works +++ b/testsuite/tr/tr-works @@ -1,3 +1,5 @@ +# FEATURE: CONFIG_FEATURE_TR_CLASSES + run_tr () { echo -n "echo '$1' | tr '$2' '$3': " -- cgit v1.2.3-55-g6feb From c0211e907ba0db44adab2c210caa284e49241ba5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 May 2010 04:32:04 +0200 Subject: randomtest fixes Signed-off-by: Denys Vlasenko --- testsuite/busybox.tests | 4 ++-- testsuite/cpio.tests | 4 ++-- testsuite/mdev.tests | 4 ++-- testsuite/mount.tests | 1 + 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/testsuite/busybox.tests b/testsuite/busybox.tests index 18ac36fc4..0c740530d 100755 --- a/testsuite/busybox.tests +++ b/testsuite/busybox.tests @@ -10,7 +10,7 @@ HELPDUMP=`true | busybox 2>&1 | cat` # We need to test under calling the binary under other names. -optional SHOW_USAGE +optional FEATURE_VERBOSE_USAGE testing "busybox --help busybox" "true | busybox --help busybox 2>&1 | cat" "$HELPDUMP\n\n" "" "" SKIP= @@ -27,7 +27,7 @@ do testing "$i --help" "$i --help 2>&1" "$HELPDUMP\n\n" "" "" - optional SHOW_USAGE CAT + optional FEATURE_VERBOSE_USAGE CAT testing "" "$i cat" "moo" "" "moo" testing "$i --help cat" "$i --help cat 2>&1 | grep print" \ "Concatenate FILEs and print them to stdout\n" "" "" diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index 8cb8b787b..725e70eab 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests @@ -31,7 +31,7 @@ rm -rf cpio.testdir cpio.testdir2 2>/dev/null # testing "test name" "command" "expected result" "file input" "stdin" -optional FEATURE_LS_SORTFILES +optional FEATURE_LS_SORTFILES FEATURE_LS_TIMESTAMPS testing "cpio extracts zero-sized hardlinks" \ "$ECHO -ne '$hexdump' | bzcat | cpio -i 2>&1; echo \$?; ls -ln cpio.testdir | $FILTER_LS" \ @@ -71,7 +71,7 @@ ln cpio.testdir/empty cpio.testdir/empty1 ln cpio.testdir/nonempty cpio.testdir/nonempty1 mkdir cpio.testdir2 -optional FEATURE_CPIO_O LONG_OPTS +optional FEATURE_CPIO_O LONG_OPTS FEATURE_LS_SORTFILES FEATURE_LS_TIMESTAMPS testing "cpio extracts zero-sized hardlinks 2" \ "find cpio.testdir | cpio -H newc --create | (cd cpio.testdir2 && cpio -i 2>&1); echo \$?; ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests index 0b4525483..5bd720b9a 100755 --- a/testsuite/mdev.tests +++ b/testsuite/mdev.tests @@ -138,7 +138,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH testing "mdev command" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS" \ @@ -153,7 +153,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 644 =block/ @echo @echo TEST:\$MDEV" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH testing "mdev move and command" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ diff --git a/testsuite/mount.tests b/testsuite/mount.tests index ee13ec285..34988867d 100755 --- a/testsuite/mount.tests +++ b/testsuite/mount.tests @@ -13,6 +13,7 @@ test "`id -u`" = 0 || { if test x"$CONFIG_MKFS_MINIX" != x"y" \ || test x"$CONFIG_FEATURE_MINIX2" != x"y" \ +|| test x"$CONFIG_FEATURE_MOUNT_LOOP" != x"y" \ || test x"$CONFIG_FEATURE_DEVFS" = x"y" \ ; then echo "SKIPPED: mount" -- cgit v1.2.3-55-g6feb From 78d035f7964510cfa8e4b3f5381f40fd2e56437b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 May 2010 04:37:13 +0200 Subject: ifplugd: fix typo in prev commit Signed-off-by: Denys Vlasenko --- networking/ifplugd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 01a7a49e5..8cb07db5d 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c @@ -145,7 +145,7 @@ static int run_script(const char *action) env_PREVIOUS = xasprintf("%s=%s", IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_prev_status)); putenv(env_PREVIOUS); - env_CURRENT = xasprintf("%s=%s", IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_last_status)); + env_CURRENT = xasprintf("%s=%s", IFPLUGD_ENV_CURRENT, strstatus(G.iface_last_status)); putenv(env_CURRENT); /* r < 0 - can't exec, 0 <= r < 0x180 - exited, >=0x180 - killed by sig (r-0x180) */ -- cgit v1.2.3-55-g6feb From da1382410bbc0dccad0d3936774a9232509f7deb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 May 2010 12:02:48 +0200 Subject: randomtest fixes Signed-off-by: Denys Vlasenko --- testsuite/mdev.tests | 4 ++-- testsuite/mount.tests | 3 ++- testsuite/tar.tests | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests index 5bd720b9a..c375fc774 100755 --- a/testsuite/mdev.tests +++ b/testsuite/mdev.tests @@ -120,7 +120,7 @@ SKIP= rm -rf mdev.testdir/dev/* # here we complicate things by having non-matching group 1 and using %0 echo "s([0-9])*d([a-z]+) 0:0 644 >sd/%2_%0" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_LS_SORTFILES testing "mdev regexp substring match + replace" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS2" \ @@ -194,7 +194,7 @@ echo "capi 0:0 0660 =capi20" >mdev.testdir/etc/mdev.conf echo "capi([0-9]) 0:0 0660 =capi20.0%1" >>mdev.testdir/etc/mdev.conf echo "capi([0-9]*) 0:0 0660 =capi20.%1" >>mdev.testdir/etc/mdev.conf # mdev invocation with DEVPATH=/class/tty/capi20 was deleting /dev/capi20 -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_LS_SORTFILES testing "move rule does not delete node with name == device_name" \ "\ env - PATH=$PATH ACTION=add DEVPATH=/class/tty/capi chroot mdev.testdir /mdev 2>&1; diff --git a/testsuite/mount.tests b/testsuite/mount.tests index 34988867d..3c7405fbd 100755 --- a/testsuite/mount.tests +++ b/testsuite/mount.tests @@ -14,13 +14,14 @@ test "`id -u`" = 0 || { if test x"$CONFIG_MKFS_MINIX" != x"y" \ || test x"$CONFIG_FEATURE_MINIX2" != x"y" \ || test x"$CONFIG_FEATURE_MOUNT_LOOP" != x"y" \ +|| test x"$CONFIG_FEATURE_MOUNT_FLAGS" != x"y" \ || test x"$CONFIG_FEATURE_DEVFS" = x"y" \ ; then echo "SKIPPED: mount" exit 0 fi -testdir=$PWD/testdir +testdir=$PWD/mount.testdir dd if=/dev/zero of=mount.image1m count=1 bs=1M 2>/dev/null || { echo "dd error"; exit 1; } mkfs.minix -v mount.image1m >/dev/null 2>&1 || { echo "mkfs.minix error"; exit 1; } diff --git a/testsuite/tar.tests b/testsuite/tar.tests index 8599b79fc..d1d4165ca 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -104,7 +104,7 @@ lrwxrwxrwx input_file "" "" SKIP= -optional FEATURE_TAR_LONG_OPTIONS +optional FEATURE_TAR_CREATE FEATURE_TAR_LONG_OPTIONS testing "tar --overwrite" "\ rm -rf input_* test.tar 2>/dev/null ln input input_hard -- cgit v1.2.3-55-g6feb From 94043e8ad2d30cc2199b35d18c853314ade174a3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 May 2010 14:49:13 +0200 Subject: lineedit: change how cmdedit_set_out_char works Rename two badly names functions, use "clear to end of screen" to eliminate annoying problems with clearing wide/combining chars, and such. Run tested. function old new delta put_cur_glyph_and_inc_cursor - 124 +124 put_till_end_and_adv_cursor - 24 +24 input_delete 125 130 +5 Ceos 5 4 -1 Ceol 5 4 -1 input_end 24 - -24 cmdedit_set_out_char 122 - -122 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 1/2 up/down: 153/-148) Total: 5 bytes Signed-off-by: Denys Vlasenko --- editors/vi.c | 4 ++-- libbb/lineedit.c | 73 +++++++++++++++++++++++++++++++------------------------- 2 files changed, 43 insertions(+), 34 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index d3a35e781..b8cacb43f 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -65,8 +65,8 @@ static const char SOn[] ALIGN1 = "\033[0m"; /* terminal bell sequence */ static const char bell[] ALIGN1 = "\007"; /* Clear-end-of-line and Clear-end-of-screen ESC sequence */ -static const char Ceol[] ALIGN1 = "\033[0K"; -static const char Ceos[] ALIGN1 = "\033[0J"; +static const char Ceol[] ALIGN1 = "\033[K"; +static const char Ceos[] ALIGN1 = "\033[J"; /* Cursor motion arbitrary destination ESC sequence */ static const char CMrc[] ALIGN1 = "\033[%d;%dH"; /* Cursor motion up and down ESC sequence */ diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 622f9ddfc..7fffe7ba2 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -66,6 +66,10 @@ #endif +#define SEQ_CLEAR_TILL_END_OF_SCREEN "\033[J" +//#define SEQ_CLEAR_TILL_END_OF_LINE "\033[K" + + #undef CHAR_T #if ENABLE_UNICODE_SUPPORT # define BB_NUL ((wchar_t)0) @@ -221,13 +225,13 @@ static size_t load_string(const char *src, int maxsize) } static unsigned save_string(char *dst, unsigned maxsize) { -#if !ENABLE_UNICODE_PRESERVE_BROKEN +# if !ENABLE_UNICODE_PRESERVE_BROKEN ssize_t len = wcstombs(dst, command_ps, maxsize - 1); if (len < 0) len = 0; dst[len] = '\0'; return len; -#else +# else unsigned dstpos = 0; unsigned srcpos = 0; @@ -256,7 +260,7 @@ static unsigned save_string(char *dst, unsigned maxsize) } dst[dstpos] = '\0'; return dstpos; -#endif +# endif } /* I thought just fputwc(c, stdout) would work. But no... */ static void BB_PUTCHAR(wchar_t c) @@ -293,19 +297,19 @@ static void save_string(char *dst, unsigned maxsize) * Advance cursor on screen. If we reached right margin, scroll text up * and remove terminal margin effect by printing 'next_char' */ #define HACK_FOR_WRONG_WIDTH 1 -#if HACK_FOR_WRONG_WIDTH -static void cmdedit_set_out_char(void) -#define cmdedit_set_out_char(next_char) cmdedit_set_out_char() -#else -static void cmdedit_set_out_char(int next_char) -#endif +static void put_cur_glyph_and_inc_cursor(void) { CHAR_T c = command_ps[cursor]; if (c == BB_NUL) { /* erase character after end of input string */ c = ' '; + } else { + /* advance cursor only if we aren't at the end yet */ + cursor++; + cmdedit_x++; } + #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT /* Display non-printable characters in reverse */ if (!BB_isprint(c)) { @@ -321,7 +325,7 @@ static void cmdedit_set_out_char(int next_char) { BB_PUTCHAR(c); } - if (++cmdedit_x >= cmdedit_termw) { + if (cmdedit_x >= cmdedit_termw) { /* terminal is scrolled down */ cmdedit_y++; cmdedit_x = 0; @@ -335,27 +339,32 @@ static void cmdedit_set_out_char(int next_char) * this will break things: there will be one extra empty line */ puts("\r"); /* + implicit '\n' */ #else - /* Works ok only if cmdedit_termw is correct */ - /* destroy "(auto)margin" */ - bb_putchar(next_char); + /* VT-10x terminals don't wrap cursor to next line when last char + * on the line is printed - cursor stays "over" this char. + * Need to print _next_ char too (first one to appear on next line) + * to make cursor move down to next line. + */ + /* Works ok only if cmdedit_termw is correct. */ + c = command_ps[cursor]; + if (c == BB_NUL) + c = ' '; + BB_PUTCHAR(c); bb_putchar('\b'); #endif } -// Huh? What if command_ps[cursor] == BB_NUL (we are at the end already?) - cursor++; } /* Move to end of line (by printing all chars till the end) */ -static void input_end(void) +static void put_till_end_and_adv_cursor(void) { while (cursor < command_len) - cmdedit_set_out_char(' '); + put_cur_glyph_and_inc_cursor(); } /* Go to the next line */ static void goto_new_line(void) { - input_end(); + put_till_end_and_adv_cursor(); if (cmdedit_x) bb_putchar('\n'); } @@ -433,8 +442,8 @@ static void redraw(int y, int back_cursor) printf("\033[%uA", y); bb_putchar('\r'); put_prompt(); - input_end(); /* rewrite */ - printf("\033[J"); /* erase after cursor */ + put_till_end_and_adv_cursor(); + printf(SEQ_CLEAR_TILL_END_OF_SCREEN); input_backward(back_cursor); } @@ -468,8 +477,9 @@ static void input_delete(int save) * simplified into (command_len - j) */ (command_len - j) * sizeof(command_ps[0])); command_len--; - input_end(); /* rewrite new line */ - cmdedit_set_out_char(' '); /* erase char */ + put_till_end_and_adv_cursor(); + /* Last char is still visible, erase it (and more) */ + printf(SEQ_CLEAR_TILL_END_OF_SCREEN); input_backward(cursor - j); /* back to old pos cursor */ } @@ -487,7 +497,7 @@ static void put(void) (command_len - cursor + 1) * sizeof(command_ps[0])); memcpy(command_ps + cursor, delbuf, j * sizeof(command_ps[0])); command_len += j; - input_end(); /* rewrite new line */ + put_till_end_and_adv_cursor(); input_backward(cursor - ocursor - j + 1); /* at end of new text */ } #endif @@ -505,7 +515,7 @@ static void input_backspace(void) static void input_forward(void) { if (cursor < command_len) - cmdedit_set_out_char(command_ps[cursor + 1]); + put_cur_glyph_and_inc_cursor(); } #if ENABLE_FEATURE_TAB_COMPLETION @@ -1955,7 +1965,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li case CTRL('E'): vi_case('$'|VI_CMDMODE_BIT:) /* Control-e -- End of line */ - input_end(); + put_till_end_and_adv_cursor(); break; case CTRL('F'): vi_case('l'|VI_CMDMODE_BIT:) @@ -1984,12 +1994,12 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li /* Control-k -- clear to end of line */ command_ps[cursor] = BB_NUL; command_len = cursor; - printf("\033[J"); + printf(SEQ_CLEAR_TILL_END_OF_SCREEN); break; case CTRL('L'): vi_case(CTRL('L')|VI_CMDMODE_BIT:) /* Control-l -- clear screen */ - printf("\033[H"); + printf("\033[H"); /* cursor to top,left */ redraw(0, command_len - cursor); break; #if MAX_HISTORY > 0 @@ -2040,7 +2050,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li vi_cmdmode = 0; break; case 'A'|VI_CMDMODE_BIT: - input_end(); + put_till_end_and_adv_cursor(); vi_cmdmode = 0; break; case 'x'|VI_CMDMODE_BIT: @@ -2200,7 +2210,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li input_backward(cursor); break; case KEYCODE_END: - input_end(); + put_till_end_and_adv_cursor(); break; default: @@ -2260,7 +2270,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li /* We are at the end, append */ command_ps[cursor] = ic; command_ps[cursor + 1] = BB_NUL; - cmdedit_set_out_char(' '); + put_cur_glyph_and_inc_cursor(); if (unicode_bidi_isrtl(ic)) input_backward(1); } else { @@ -2273,8 +2283,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li /* is right-to-left char, or neutral one (e.g. comma) was just added to rtl text? */ if (!isrtl_str()) sc++; /* no */ - /* rewrite from cursor */ - input_end(); + put_till_end_and_adv_cursor(); /* to prev x pos + 1 */ input_backward(cursor - sc); } -- cgit v1.2.3-55-g6feb From a2215b98f7d65bc613b9c8f008d79672402c6a07 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 May 2010 01:49:04 +0200 Subject: sed: fix a command with multible trailing backslashes Signed-off-by: Denys Vlasenko --- editors/sed.c | 14 ++++++++------ testsuite/sed.tests | 14 ++++++++++++++ testsuite/testing.sh | 2 +- 3 files changed, 23 insertions(+), 7 deletions(-) mode change 100755 => 100644 testsuite/testing.sh diff --git a/editors/sed.c b/editors/sed.c index 30ab8c9fb..4bd6e0168 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -487,7 +487,7 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) static void add_cmd(const char *cmdstr) { sed_cmd_t *sed_cmd; - int temp; + unsigned len, n; /* Append this line to any unfinished line from last time. */ if (G.add_cmd_line) { @@ -496,12 +496,14 @@ static void add_cmd(const char *cmdstr) cmdstr = G.add_cmd_line = tp; } - /* If this line ends with backslash, request next line. */ - temp = strlen(cmdstr); - if (temp && cmdstr[--temp] == '\\') { + /* If this line ends with unescaped backslash, request next line. */ + n = len = strlen(cmdstr); + while (n && cmdstr[n-1] == '\\') + n--; + if ((len - n) & 1) { /* if odd number of trailing backslashes */ if (!G.add_cmd_line) G.add_cmd_line = xstrdup(cmdstr); - G.add_cmd_line[temp] = '\0'; + G.add_cmd_line[len-1] = '\0'; return; } @@ -560,7 +562,7 @@ static void add_cmd(const char *cmdstr) /* last part (mandatory) will be a command */ if (!*cmdstr) bb_error_msg_and_die("missing command"); - sed_cmd->cmd = *(cmdstr++); + sed_cmd->cmd = *cmdstr++; cmdstr = parse_cmd_args(sed_cmd, cmdstr); /* Add the command to the command array */ diff --git a/testsuite/sed.tests b/testsuite/sed.tests index b0de9657c..5b0750cac 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests @@ -258,4 +258,18 @@ testing "sed nested {}s" \ "qwe\nasd\nacd\nacd\n" "" \ "qwe\nasd\nzxc\n" +testing "sed a cmd ended by double backslash" \ + "sed -e '/| one /a \\ + | three \\\\' -e '/| one-/a \\ + | three-* \\\\'" \ +' | one \\ + | three \\ + | two \\ +' '' \ +' | one \\ + | two \\ +' + +# testing "description" "arguments" "result" "infile" "stdin" + exit $FAILCOUNT diff --git a/testsuite/testing.sh b/testsuite/testing.sh old mode 100755 new mode 100644 index 65a0f6529..913d7f8ef --- a/testsuite/testing.sh +++ b/testsuite/testing.sh @@ -73,7 +73,7 @@ testing() if [ $# -ne 5 ] then - echo "Test $NAME has wrong number of arguments (must be 5) ($# $*)" >&2 + echo "Test $NAME has wrong number of arguments: $# (must be 5)" >&2 exit 1 fi -- cgit v1.2.3-55-g6feb From e82cf339e476126e4016e417aee3c6eb52c702c9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 May 2010 15:59:32 +0200 Subject: randomtest fixes Signed-off-by: Denys Vlasenko --- testsuite/ash.tests | 2 +- testsuite/cut/cut-cuts-a-field | 2 +- testsuite/date/date-R-works | 9 ++++++++- testsuite/du/du-h-works | 6 ++---- testsuite/du/du-k-works | 8 ++++---- testsuite/du/du-l-works | 10 ++++++---- testsuite/du/du-m-works | 6 ++---- testsuite/du/du-s-works | 4 +++- testsuite/du/du-works | 4 +++- testsuite/expand/expand-works-like-GNU | 8 ++++---- testsuite/hostid/hostid-works | 10 ++++++++-- testsuite/hostname/hostname-d-works | 5 +++-- testsuite/rx.tests | 4 ++-- testsuite/sed.tests | 4 ++-- testsuite/tar.tests | 2 +- testsuite/tr/tr-works | 2 +- 16 files changed, 51 insertions(+), 35 deletions(-) diff --git a/testsuite/ash.tests b/testsuite/ash.tests index 183394a20..dd626e6d1 100755 --- a/testsuite/ash.tests +++ b/testsuite/ash.tests @@ -71,7 +71,7 @@ testing "2 bytes which are not valid unicode chars followed by left arrow key" \ # not checked by the test), then read and execute the rest: "echo A | ..." # The bug was that ash was eating the beginning of "echo A" despite the pause. testing "Invalid unicode chars followed by a pause do not eat next chars" \ - "{ echo -ne 'echo \xff\n'; sleep 1; echo -ne 'echo A | hexdump -C >ash.output; exit; exit; exit; exit\n'; } \ + "{ $ECHO -ne 'echo \xff\n'; sleep 1; $ECHO -ne 'echo A | hexdump -C >ash.output; exit; exit; exit; exit\n'; } \ | script -q -c 'ash' /dev/null >/dev/null; cat ash.output" \ "\ 00000000 41 0a |A.| diff --git a/testsuite/cut/cut-cuts-a-field b/testsuite/cut/cut-cuts-a-field index 4c7f44007..e200b6b78 100644 --- a/testsuite/cut/cut-cuts-a-field +++ b/testsuite/cut/cut-cuts-a-field @@ -1 +1 @@ -test $(echo -e "f1\tf2\tf3" | busybox cut -f 2) = f2 +test $($ECHO -e "f1\tf2\tf3" | busybox cut -f 2) = f2 diff --git a/testsuite/date/date-R-works b/testsuite/date/date-R-works index 34cd735e5..d05634456 100644 --- a/testsuite/date/date-R-works +++ b/testsuite/date/date-R-works @@ -1 +1,8 @@ -test x"`date -R`" = x"`busybox date -R`" +dt1="`date -R`" +# Wait for the start of next second +dt="$dt1" +while test x"$dt" = x"$dt1"; do + dt="`date -R`" +done + +test x"$dt" = x"`busybox date -R`" diff --git a/testsuite/du/du-h-works b/testsuite/du/du-h-works index a1b4b4905..c18433c29 100644 --- a/testsuite/du/du-h-works +++ b/testsuite/du/du-h-works @@ -1,6 +1,4 @@ # FEATURE: CONFIG_FEATURE_HUMAN_READABLE -d=/bin -du -h "$d" > logfile.gnu -busybox du -h "$d" > logfile.bb -cmp logfile.gnu logfile.bb +dd if=/dev/zero of=file bs=1M count=1 2>/dev/null +test x"`busybox du -h .`" = x"1.0M ." diff --git a/testsuite/du/du-k-works b/testsuite/du/du-k-works index 6c2c5d073..a52264945 100644 --- a/testsuite/du/du-k-works +++ b/testsuite/du/du-k-works @@ -1,4 +1,4 @@ -d=/bin -du -k "$d" > logfile.gnu -busybox du -k "$d" > logfile.bb -cmp logfile.gnu logfile.bb +dd if=/dev/zero of=file1 bs=1k count=64 2>/dev/null +dd if=/dev/zero of=file2 bs=1k count=16 2>/dev/null +test x"`busybox du -k .`" = x"80 ." \ + -o x"`busybox du -k .`" = x"88 ." \ diff --git a/testsuite/du/du-l-works b/testsuite/du/du-l-works index 64dcf8726..6b150e0dd 100644 --- a/testsuite/du/du-l-works +++ b/testsuite/du/du-l-works @@ -1,6 +1,8 @@ # FEATURE: CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K -d=/bin -du -l "$d" > logfile.gnu -busybox du -l "$d" > logfile.bb -cmp logfile.gnu logfile.bb +dd if=/dev/zero of=file1 bs=1k count=64 2>/dev/null +ln file1 file1.1 +dd if=/dev/zero of=file2 bs=1k count=16 2>/dev/null +test x"`busybox du -l .`" = x"144 ." \ + -o x"`busybox du -l .`" = x"148 ." \ + -o x"`busybox du -l .`" = x"152 ." \ diff --git a/testsuite/du/du-m-works b/testsuite/du/du-m-works index 6e733c016..9fa7437ac 100644 --- a/testsuite/du/du-m-works +++ b/testsuite/du/du-m-works @@ -1,6 +1,4 @@ # FEATURE: CONFIG_FEATURE_HUMAN_READABLE -d=/bin -du -m "$d" > logfile.gnu -busybox du -m "$d" > logfile.bb -cmp logfile.gnu logfile.bb +dd if=/dev/zero of=file bs=1M count=1 2>/dev/null +test x"`busybox du -m .`" = x"1 ." diff --git a/testsuite/du/du-s-works b/testsuite/du/du-s-works index 0c870ceb5..534432cb0 100644 --- a/testsuite/du/du-s-works +++ b/testsuite/du/du-s-works @@ -3,4 +3,6 @@ d=/bin du -s "$d" > logfile.gnu busybox du -s "$d" > logfile.bb -cmp logfile.gnu logfile.bb +cmp logfile.gnu logfile.bb && exit 0 +diff -u logfile.gnu logfile.bb +exit 1 diff --git a/testsuite/du/du-works b/testsuite/du/du-works index 4db684a9b..e320f1dd0 100644 --- a/testsuite/du/du-works +++ b/testsuite/du/du-works @@ -3,4 +3,6 @@ d=/bin du "$d" > logfile.gnu busybox du "$d" > logfile.bb -cmp logfile.gnu logfile.bb +cmp logfile.gnu logfile.bb && exit 0 +diff -u logfile.gnu logfile.bb +exit 1 diff --git a/testsuite/expand/expand-works-like-GNU b/testsuite/expand/expand-works-like-GNU index 843111275..b0278d88d 100644 --- a/testsuite/expand/expand-works-like-GNU +++ b/testsuite/expand/expand-works-like-GNU @@ -1,8 +1,8 @@ # FEATURE: CONFIG_UNEXPAND rm -f foo bar -echo -e "\ty" | expand -t 3 ../../busybox > foo -echo -e "\ty" | busybox unexpand -t 3 ../../busybox > bar +$ECHO -e "\ty" | expand -t 3 ../../busybox > foo +$ECHO -e "\ty" | busybox unexpand -t 3 ../../busybox > bar set +e test ! -f foo -a -f bar if [ $? = 0 ] ; then @@ -10,8 +10,8 @@ if [ $? = 0 ] ; then diff -q foo bar fi rm -f foo bar -echo -e "\ty\tx" | expand -it 3 ../../busybox > foo -echo -e "\ty\tx" | busybox unexpand -it 3 ../../busybox > bar +$ECHO -e "\ty\tx" | expand -it 3 ../../busybox > foo +$ECHO -e "\ty\tx" | busybox unexpand -it 3 ../../busybox > bar set +e test ! -f foo -a -f bar if [ $? = 0 ] ; then diff --git a/testsuite/hostid/hostid-works b/testsuite/hostid/hostid-works index e85698e66..bcfd717af 100644 --- a/testsuite/hostid/hostid-works +++ b/testsuite/hostid/hostid-works @@ -1,2 +1,8 @@ -test x$(hostid) = x$(busybox hostid) - +h=x$(busybox hostid) +# Is $h a sequence of hex numbers? +x="${h//[0123456789abcdef]/x}" +x="${x//xxx/x}" +x="${x//xxx/x}" +x="${x//xxx/x}" +x="${x//xx/x}" +test x"$x" = x"x" diff --git a/testsuite/hostname/hostname-d-works b/testsuite/hostname/hostname-d-works index a9aeb92cb..e062242bb 100644 --- a/testsuite/hostname/hostname-d-works +++ b/testsuite/hostname/hostname-d-works @@ -1,2 +1,3 @@ -test x$(hostname -d) = x$(busybox hostname -d) - +f=$(busybox hostname -f) +d=$(busybox hostname -d) +test x"${f#*.}" = x"$d" diff --git a/testsuite/rx.tests b/testsuite/rx.tests index c2b8814a2..985fcdc01 100755 --- a/testsuite/rx.tests +++ b/testsuite/rx.tests @@ -18,9 +18,9 @@ testing "rx" \ 00000000 43 06 06 |C..|\n\ 00000003\n\ ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????" \ - "" "\1\1\376\ + "" "\01\01\0376\ ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????\ -\x1A\x1A\x1A\x1A\x1A\x4B\xB0\4" +\x1A\x1A\x1A\x1A\x1A\x4B\xB0\04" rm -f rx.OUTFILE 2>/dev/null diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 5b0750cac..88b9c4e4b 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests @@ -110,7 +110,7 @@ testing "sed embedded NUL" "sed -e 's/woo/bang/'" "\0bang\0woo\0" "" \ testing "sed embedded NUL g" "sed -e 's/woo/bang/g'" "bang\0bang\0" "" \ "woo\0woo\0" test x"$SKIP_KNOWN_BUGS" = x"" && { -echo -e "/woo/a he\0llo" > sed.commands +$ECHO -e "/woo/a he\0llo" > sed.commands testing "sed NUL in command" "sed -f sed.commands" "woo\nhe\0llo\n" "" "woo" rm sed.commands } @@ -153,7 +153,7 @@ testing "sed clusternewline" \ "one\none\n111\n222\ntwo\ntwo" "one" "two" } testing "sed subst+write" \ - "sed -e 's/i/z/' -e 'woutputw' input -; echo -n X; cat outputw" \ + "sed -e 's/i/z/' -e 'woutputw' input -; $ECHO -n X; cat outputw" \ "thzngy\nagaznXthzngy\nagazn" "thingy" "again" rm outputw testing "sed trailing NUL" \ diff --git a/testsuite/tar.tests b/testsuite/tar.tests index d1d4165ca..f40079037 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -84,7 +84,7 @@ chmod 550 input_dir ln input_file input_dir ln input_soft input_dir tar cf test.tar input_* -tar tvf test.tar | sed "s/.*[0-9] input/input/" +tar tvf test.tar | sed "s/.*[0-9] input/input/" | sort tar xf test.tar 2>&1 echo Ok: $? ls -l . input_dir/* | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/" diff --git a/testsuite/tr/tr-works b/testsuite/tr/tr-works index 3783971ce..5e4a30ee4 100644 --- a/testsuite/tr/tr-works +++ b/testsuite/tr/tr-works @@ -2,7 +2,7 @@ run_tr () { - echo -n "echo '$1' | tr '$2' '$3': " + $ECHO -n "echo '$1' | tr '$2' '$3': " echo "$1" | $bb tr "$2" "$3" echo } -- cgit v1.2.3-55-g6feb From 5055a9f98999d3a6c2f4d043a85f6c2d6fb7eaf2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 May 2010 04:08:20 +0200 Subject: cttyhack: don't do anything if ctty is already available function old new delta cttyhack_main 244 269 +25 Signed-off-by: Denys Vlasenko --- shell/cttyhack.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/shell/cttyhack.c b/shell/cttyhack.c index 572a3af03..bde2acdc9 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c @@ -53,23 +53,32 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv) } strcpy(console, "/dev/tty"); - if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { - /* this is a serial console */ - sprintf(console + 8, "S%d", u.sr.line); - } else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { - /* this is linux virtual tty */ - sprintf(console + 8, "S%d" + 1, u.vt.v_active); - } - - if (console[8]) { - fd = xopen(console, O_RDWR); - //bb_error_msg("switching to '%s'", console); - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - while (fd > 2) close(fd--); - /* Some other session may have it as ctty. Steal it from them */ - ioctl(0, TIOCSCTTY, 1); + fd = open(console, O_RDWR); + if (fd >= 0) { + /* We already have ctty, nothing to do */ + close(fd); + } else { + /* We don't have ctty (or don't have "/dev/tty" node...) */ + if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { + /* this is a serial console */ + sprintf(console + 8, "S%d", u.sr.line); + } else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { + /* this is linux virtual tty */ + sprintf(console + 8, "S%d" + 1, u.vt.v_active); + } + if (console[8]) { + fd = xopen(console, O_RDWR); + //bb_error_msg("switching to '%s'", console); + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + while (fd > 2) + close(fd--); + /* Some other session may have it as ctty, + * steal it from them: + */ + ioctl(0, TIOCSCTTY, 1); + } } BB_EXECVP(argv[0], argv); -- cgit v1.2.3-55-g6feb From c84c85ae345f6b3a4ba74ae1ab22acddd41fa456 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 May 2010 20:30:44 +0200 Subject: gen_build_files: use raw reads (ones which don't eat backslashes) Signed-off-by: Denys Vlasenko --- scripts/gen_build_files.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index 2baefa2ee..73c9916c7 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -7,7 +7,7 @@ cd -- "$2" || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } srctree="$1" -find -type d | while read; do +find -type d | while read -r; do d="$REPLY" src="$srctree/$d/Kbuild.src" @@ -17,7 +17,7 @@ find -type d | while read; do s=`sed -n 's@^//kbuild:@@p' -- "$srctree/$d"/*.c` echo "# DO NOT EDIT. This file is generated from Kbuild.src" >"$dst.$$.tmp" - while read; do + while read -r; do test x"$REPLY" = x"INSERT" && REPLY="$s" printf "%s\n" "$REPLY" done <"$src" >>"$dst.$$.tmp" @@ -37,7 +37,7 @@ find -type d | while read; do s=`sed -n 's@^//config:@@p' -- "$srctree/$d"/*.c` echo "# DO NOT EDIT. This file is generated from Config.src" >"$dst.$$.tmp" - while read; do + while read -r; do test x"$REPLY" = x"INSERT" && REPLY="$s" printf "%s\n" "$REPLY" done <"$src" >>"$dst.$$.tmp" -- cgit v1.2.3-55-g6feb From b367bb2a620d3c349b0a61b949a6ebca32bf5395 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 15 May 2010 20:43:07 +0200 Subject: cttyhack: document the need to setsid function old new delta packed_usage 26988 27057 +69 Signed-off-by: Denys Vlasenko --- include/usage.h | 12 ++++++++++-- shell/Config.in | 15 +++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/usage.h b/include/usage.h index 9d9ad008b..be52f187f 100644 --- a/include/usage.h +++ b/include/usage.h @@ -649,8 +649,16 @@ "\n -S SALT" \ ) \ -#define cttyhack_trivial_usage NOUSAGE_STR -#define cttyhack_full_usage "" +#define cttyhack_trivial_usage \ + "PROG ARGS" +#define cttyhack_full_usage "\n\n" \ + "Give PROG a controlling tty if possible." \ + "\nExample for /etc/inittab (for busybox init):" \ + "\n ::respawn:/bin/cttyhack /bin/sh" \ + "\nGiving controlling tty to shell running with PID 1:" \ + "\n $ exec cttyhack sh" \ + "\nStarting an interative shell from boot shell script:" \ + "\n setsid cttyhack sh" \ #define cut_trivial_usage \ "[OPTIONS] [FILE]..." diff --git a/shell/Config.in b/shell/Config.in index 3b1650615..36a931715 100644 --- a/shell/Config.in +++ b/shell/Config.in @@ -354,9 +354,20 @@ config CTTYHACK It analyzes stdin with various ioctls, trying to determine whether it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line). If it detects one, it closes stdin/out/err and reopens that device. - Then it executes given program. Usage example for /etc/inittab - (for busybox init): + Then it executes given program. Opening the device will make + that device a controlling tty. This may require cttyhack + to be a session leader. + + Example for /etc/inittab (for busybox init): ::respawn:/bin/cttyhack /bin/sh + Giving controlling tty to shell running with PID 1: + + $ exec cttyhack sh + + Starting an interative shell from boot shell script: + + setsid cttyhack sh + endmenu -- cgit v1.2.3-55-g6feb From 084e2284c700561732cc708ee557169be9d18308 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 15 May 2010 21:08:51 +0200 Subject: gen_build_files.sh uses bashism, document it Signed-off-by: Denys Vlasenko --- scripts/gen_build_files.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index 73c9916c7..ea14de5e2 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -1,4 +1,7 @@ -#!/bin/sh +#!/bin/bash +# bashism: +# "read -r" without variable name reads line into $REPLY +# without stripping whitespace. test $# -ge 2 || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } @@ -7,9 +10,7 @@ cd -- "$2" || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } srctree="$1" -find -type d | while read -r; do - d="$REPLY" - +find -type d | while read -r d; do src="$srctree/$d/Kbuild.src" dst="$d/Kbuild" if test -f "$src"; then @@ -49,7 +50,6 @@ find -type d | while read -r; do mv -- "$dst.$$.tmp" "$dst" fi fi - done # Last read failed. This is normal. Don't exit with its error code: -- cgit v1.2.3-55-g6feb From a29b055bf1c21fb65bfeb5fdd982dfcd15f2b360 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 May 2010 02:12:56 +0200 Subject: setsid: check for setsid error directly function old new delta setsid_main 74 66 -8 Signed-off-by: Denys Vlasenko --- miscutils/setsid.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/miscutils/setsid.c b/miscutils/setsid.c index d7de1f149..fd3283e30 100644 --- a/miscutils/setsid.c +++ b/miscutils/setsid.c @@ -25,11 +25,24 @@ int setsid_main(int argc UNUSED_PARAM, char **argv) /* setsid() is allowed only when we are not a process group leader. * Otherwise our PID serves as PGID of some existing process group * and cannot be used as PGID of a new process group. */ - if (getpgrp() == getpid()) - if (fork_or_rexec(argv)) - exit(EXIT_SUCCESS); /* parent */ + if (setsid() < 0) { + pid_t pid = fork_or_rexec(argv); + if (pid != 0) { + /* parent */ + /* TODO: + * we can waitpid(pid, &status, 0) and then even + * emulate exitcode, making the behavior consistent + * in both forked and non forked cases. + * However, the code is larger and upstream + * does not do such trick. + */ + exit(EXIT_SUCCESS); + } - setsid(); /* no error possible */ + /* child */ + /* now there should be no error: */ + setsid(); + } BB_EXECVP(argv[1], argv + 1); bb_simple_perror_msg_and_die(argv[1]); -- cgit v1.2.3-55-g6feb From 8806d64acd621cb5fd65b6a512cb6dc99079ca4d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 May 2010 02:36:18 +0200 Subject: hush: mention PPID, RANDOM support Signed-off-by: Denys Vlasenko --- shell/hush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/hush.c b/shell/hush.c index 9b15efb30..07cacbfc9 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -57,7 +57,7 @@ * * TODOs: * grep for "TODO" and fix (some of them are easy) - * special variables (done: PWD) + * special variables (done: PWD, PPID, RANDOM) * follow IFS rules more precisely, including update semantics * export builtin should be special, its arguments are assignments * and therefore expansion of them should be "one-word" expansion: -- cgit v1.2.3-55-g6feb From 0bb2980605f88b1c78757db0c7a149d15a167288 Mon Sep 17 00:00:00 2001 From: Peter Tyser Date: Sun, 16 May 2010 02:48:21 +0200 Subject: Makefile: Clean up auto-generated Kbuild and Config.in files Previously these auto-generated files were left behind after a 'make mrproper' was ran. Signed-off-by: Peter Tyser Signed-off-by: Denys Vlasenko --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index da8f7d7b6..14f5cd149 100644 --- a/Makefile +++ b/Makefile @@ -1001,6 +1001,8 @@ $(mrproper-dirs): mrproper: clean archmrproper $(mrproper-dirs) $(call cmd,rmdirs) $(call cmd,rmfiles) + @find -name Config.src | sed 's/.src$/.in/' | xargs -r rm -f + @find -name Kbuild.src | sed 's/.src$//' | xargs -r rm -f # distclean # -- cgit v1.2.3-55-g6feb From 748139332ad632001935b0535764cdbd1c71ce26 Mon Sep 17 00:00:00 2001 From: Peter Tyser Date: Thu, 13 May 2010 18:46:00 -0500 Subject: scripts/Makefile.clean: Make Kbuild and Makefile optional During cleaning, some directories might not have a Makefile or Kbuild file. Previously scripts/Makefile.clean would spit out the following error when neither file could be found: ptyser@petert busybox $ make mrproper scripts/Makefile.clean:17: /home/user/busybox/findutils/Makefile: No such file or directory make[1]: *** No rule to make target `/home/user/busybox/findutils/Makefile'. Stop. make: *** [_clean_findutils] Error 2 This issue can be triggered by running 'make mrproper' in a freshly cloned busybox repository. Signed-off-by: Peter Tyser Signed-off-by: Denys Vlasenko --- scripts/Makefile.clean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index cff33498f..03e397f42 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean @@ -14,7 +14,7 @@ clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj # The filename Kbuild has precedence over Makefile kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) -include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) +-include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) # Figure out what we need to build from the various variables # ========================================================================== -- cgit v1.2.3-55-g6feb From 0b7412e66b3d702557a2bf214752ff68d80fcda3 Mon Sep 17 00:00:00 2001 From: Peter Tyser Date: Thu, 13 May 2010 18:56:22 -0500 Subject: findutils: Add Config.in and Kbuild to .gitignore These are auto-generated files and should be ignored by git. Signed-off-by: Peter Tyser Signed-off-by: Denys Vlasenko --- findutils/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 findutils/.gitignore diff --git a/findutils/.gitignore b/findutils/.gitignore new file mode 100644 index 000000000..7a30caf5c --- /dev/null +++ b/findutils/.gitignore @@ -0,0 +1,3 @@ +# Config.in and Kbuild are auto-generated +Config.in +Kbuild -- cgit v1.2.3-55-g6feb From b8909c52fe850d2731326534822164c2f5258bf5 Mon Sep 17 00:00:00 2001 From: Tomas Heinrich Date: Sun, 16 May 2010 20:46:53 +0200 Subject: lineedit: partially fix wide and combining chars editing Signed-off-by: Tomas Heinrich Signed-off-by: Denys Vlasenko --- include/unicode.h | 11 +++++ libbb/lineedit.c | 124 +++++++++++++++++++++++++++++++++++------------------- libbb/unicode.c | 2 +- 3 files changed, 92 insertions(+), 45 deletions(-) diff --git a/include/unicode.h b/include/unicode.h index 4e2927297..747026abe 100644 --- a/include/unicode.h +++ b/include/unicode.h @@ -35,6 +35,16 @@ enum { # define LAST_SUPPORTED_WCHAR CONFIG_LAST_SUPPORTED_WCHAR # endif +# if LAST_SUPPORTED_WCHAR < 0x300 +# undef ENABLE_UNICODE_COMBINING_WCHARS +# define ENABLE_UNICODE_COMBINING_WCHARS 0 +# endif + +# if LAST_SUPPORTED_WCHAR < 0x1100 +# undef ENABLE_UNICODE_WIDE_WCHARS +# define ENABLE_UNICODE_WIDE_WCHARS 0 +# endif + # if LAST_SUPPORTED_WCHAR < 0x590 # undef ENABLE_UNICODE_BIDI_SUPPORT # define ENABLE_UNICODE_BIDI_SUPPORT 0 @@ -92,6 +102,7 @@ size_t wcrtomb(char *s, wchar_t wc, mbstate_t *ps) FAST_FUNC; int iswspace(wint_t wc) FAST_FUNC; int iswalnum(wint_t wc) FAST_FUNC; int iswpunct(wint_t wc) FAST_FUNC; +int wcwidth(unsigned ucs) FAST_FUNC; # if ENABLE_UNICODE_BIDI_SUPPORT # undef unicode_bidi_isrtl int unicode_bidi_isrtl(wint_t wc) FAST_FUNC; diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 7fffe7ba2..9f2d65717 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -42,14 +42,10 @@ #include "libbb.h" #include "unicode.h" -/* FIXME: obsolete CONFIG item? */ -#define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0 - #ifdef TEST # define ENABLE_FEATURE_EDITING 0 # define ENABLE_FEATURE_TAB_COMPLETION 0 # define ENABLE_FEATURE_USERNAME_COMPLETION 0 -# define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0 #endif @@ -97,10 +93,10 @@ static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } # if ENABLE_UNICODE_PRESERVE_BROKEN -# define unicode_mark_inv_wchar(wc) ((wc) | 0x20000000) -# define unicode_is_inv_wchar(wc) ((wc) & 0x20000000) +# define unicode_mark_raw_byte(wc) ((wc) | 0x20000000) +# define unicode_is_raw_byte(wc) ((wc) & 0x20000000) # else -# define unicode_is_inv_wchar(wc) 0 +# define unicode_is_raw_byte(wc) 0 # endif @@ -240,7 +236,7 @@ static unsigned save_string(char *dst, unsigned maxsize) wchar_t wc; int n = srcpos; while ((wc = command_ps[srcpos]) != 0 - && !unicode_is_inv_wchar(wc) + && !unicode_is_raw_byte(wc) ) { srcpos++; } @@ -269,15 +265,45 @@ static void BB_PUTCHAR(wchar_t c) mbstate_t mbst = { 0 }; ssize_t len; - if (unicode_is_inv_wchar(c)) - c = CONFIG_SUBST_WCHAR; len = wcrtomb(buf, c, &mbst); if (len > 0) { buf[len] = '\0'; fputs(buf, stdout); } } -#else +# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS +static wchar_t adjust_width_and_validate_wc(unsigned *width_adj, wchar_t wc) +# else +static wchar_t adjust_width_and_validate_wc(wchar_t wc) +# define adjust_width_and_validate_wc(width_adj, wc) \ + ((*(width_adj))++, adjust_width_and_validate_wc(wc)) +# endif +{ + int w = 1; + + if (unicode_status == UNICODE_ON) { + if (unicode_is_raw_byte(wc) + || (CONFIG_LAST_SUPPORTED_WCHAR && wc > CONFIG_LAST_SUPPORTED_WCHAR) + ) { + goto subst; + } + w = wcwidth(wc); + if ((ENABLE_UNICODE_COMBINING_WCHARS && w < 0) + || (!ENABLE_UNICODE_COMBINING_WCHARS && w <= 0) + || (!ENABLE_UNICODE_WIDE_WCHARS && w > 1) + ) { + subst: + w = 1; + wc = CONFIG_SUBST_WCHAR; + } + } + +# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS + *width_adj += w; +#endif + return wc; +} +#else /* !UNICODE */ static size_t load_string(const char *src, int maxsize) { safe_strncpy(command_ps, src, maxsize); @@ -290,6 +316,8 @@ static void save_string(char *dst, unsigned maxsize) } # endif # define BB_PUTCHAR(c) bb_putchar(c) +/* Should never be called: */ +int adjust_width_and_validate_wc(unsigned *width_adj, int wc); #endif @@ -300,6 +328,8 @@ static void save_string(char *dst, unsigned maxsize) static void put_cur_glyph_and_inc_cursor(void) { CHAR_T c = command_ps[cursor]; + unsigned width = 0; + int ofs_to_right; if (c == BB_NUL) { /* erase character after end of input string */ @@ -307,28 +337,23 @@ static void put_cur_glyph_and_inc_cursor(void) } else { /* advance cursor only if we aren't at the end yet */ cursor++; - cmdedit_x++; + if (unicode_status == UNICODE_ON) { + IF_UNICODE_WIDE_WCHARS(width = cmdedit_x;) + c = adjust_width_and_validate_wc(&cmdedit_x, c); + IF_UNICODE_WIDE_WCHARS(width = cmdedit_x - width;) + } else { + cmdedit_x++; + } } -#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT - /* Display non-printable characters in reverse */ - if (!BB_isprint(c)) { - if (c >= 128) - c -= 128; - if (c < ' ') - c += '@'; - if (c == 127) - c = '?'; - printf("\033[7m%c\033[0m", c); - } else -#endif - { + ofs_to_right = cmdedit_x - cmdedit_termw; + if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right <= 0) { + /* c fits on this line */ BB_PUTCHAR(c); } - if (cmdedit_x >= cmdedit_termw) { - /* terminal is scrolled down */ - cmdedit_y++; - cmdedit_x = 0; + + if (ofs_to_right >= 0) { + /* we go to the next line */ #if HACK_FOR_WRONG_WIDTH /* This works better if our idea of term width is wrong * and it is actually wider (often happens on serial lines). @@ -351,6 +376,14 @@ static void put_cur_glyph_and_inc_cursor(void) BB_PUTCHAR(c); bb_putchar('\b'); #endif + cmdedit_y++; + if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) { + width = 0; + } else { /* ofs_to_right > 0 */ + /* wide char c didn't fit on prev line */ + BB_PUTCHAR(c); + } + cmdedit_x = width; } } @@ -389,10 +422,22 @@ static void input_backward(unsigned num) if (num > cursor) num = cursor; - if (!num) + if (num == 0) return; cursor -= num; + if ((ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS) + && unicode_status == UNICODE_ON + ) { + /* correct NUM to be equal to _screen_ width */ + int n = num; + num = 0; + while (--n >= 0) + adjust_width_and_validate_wc(&num, command_ps[cursor + n]); + if (num == 0) + return; + } + if (cmdedit_x >= num) { cmdedit_x -= num; if (num <= 4) { @@ -412,6 +457,8 @@ static void input_backward(unsigned num) } /* Need to go one or more lines up */ +//FIXME: this does not work correctly if prev line has one "unfilled" screen position +//caused by wide unicode char not fitting in that one screen position. num -= cmdedit_x; { unsigned w = cmdedit_termw; /* volatile var */ @@ -765,21 +812,13 @@ static NOINLINE int find_match(char *matchBuf, int *len_with_quotes) } /* mask \+symbol and convert '\t' to ' ' */ - for (i = j = 0; matchBuf[i]; i++, j++) + for (i = j = 0; matchBuf[i]; i++, j++) { if (matchBuf[i] == '\\') { collapse_pos(j, j + 1); int_buf[j] |= QUOT; i++; -#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT - if (matchBuf[i] == '\t') /* algorithm equivalent */ - int_buf[j] = ' ' | QUOT; -#endif } -#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT - else if (matchBuf[i] == '\t') - int_buf[j] = ' '; -#endif - + } /* mask "symbols" or 'symbols' */ c2 = 0; for (i = 0; int_buf[i]; i++) { @@ -1774,7 +1813,7 @@ static int lineedit_read_key(char *read_key_buffer) # if !ENABLE_UNICODE_PRESERVE_BROKEN ic = CONFIG_SUBST_WCHAR; # else - ic = unicode_mark_inv_wchar(unicode_buf[0]); + ic = unicode_mark_raw_byte(unicode_buf[0]); # endif } else { /* Valid unicode char, return its code */ @@ -2384,9 +2423,6 @@ int main(int argc, char **argv) "% "; #endif -#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT - setlocale(LC_ALL, ""); -#endif while (1) { int l; l = read_line_input(prompt, buff); diff --git a/libbb/unicode.c b/libbb/unicode.c index d1c6167c7..eb0ea6129 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c @@ -418,7 +418,7 @@ static int in_uint16_table(unsigned ucs, const uint16_t *table, unsigned max) * This implementation assumes that wchar_t characters are encoded * in ISO 10646. */ -static int wcwidth(unsigned ucs) +int FAST_FUNC wcwidth(unsigned ucs) { # if LAST_SUPPORTED_WCHAR >= 0x300 /* sorted list of non-overlapping intervals of non-spacing characters */ -- cgit v1.2.3-55-g6feb From 26e2c1db0df35df1affa558efc12d2bcfd7718e2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 May 2010 21:15:03 +0200 Subject: stop using LAST_SUPPORTED_WCHAR and CONFIG_LAST_SUPPORTED_WCHAR, it's confusing Signed-off-by: Denys Vlasenko --- include/unicode.h | 11 +++++------ libbb/lineedit.c | 5 ++--- libbb/unicode.c | 26 +++++++++++++------------- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/include/unicode.h b/include/unicode.h index 747026abe..eaf67c833 100644 --- a/include/unicode.h +++ b/include/unicode.h @@ -30,22 +30,21 @@ enum { #else # if CONFIG_LAST_SUPPORTED_WCHAR < 126 || CONFIG_LAST_SUPPORTED_WCHAR >= 0x30000 -# define LAST_SUPPORTED_WCHAR 0x2ffff -# else -# define LAST_SUPPORTED_WCHAR CONFIG_LAST_SUPPORTED_WCHAR +# undef CONFIG_LAST_SUPPORTED_WCHAR +# define CONFIG_LAST_SUPPORTED_WCHAR 0x2ffff # endif -# if LAST_SUPPORTED_WCHAR < 0x300 +# if CONFIG_LAST_SUPPORTED_WCHAR < 0x300 # undef ENABLE_UNICODE_COMBINING_WCHARS # define ENABLE_UNICODE_COMBINING_WCHARS 0 # endif -# if LAST_SUPPORTED_WCHAR < 0x1100 +# if CONFIG_LAST_SUPPORTED_WCHAR < 0x1100 # undef ENABLE_UNICODE_WIDE_WCHARS # define ENABLE_UNICODE_WIDE_WCHARS 0 # endif -# if LAST_SUPPORTED_WCHAR < 0x590 +# if CONFIG_LAST_SUPPORTED_WCHAR < 0x590 # undef ENABLE_UNICODE_BIDI_SUPPORT # define ENABLE_UNICODE_BIDI_SUPPORT 0 # endif diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 9f2d65717..72a1786ff 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -282,9 +282,8 @@ static wchar_t adjust_width_and_validate_wc(wchar_t wc) int w = 1; if (unicode_status == UNICODE_ON) { - if (unicode_is_raw_byte(wc) - || (CONFIG_LAST_SUPPORTED_WCHAR && wc > CONFIG_LAST_SUPPORTED_WCHAR) - ) { + if (wc > CONFIG_LAST_SUPPORTED_WCHAR) { + /* note: also true for unicode_is_raw_byte(wc) */ goto subst; } w = wcwidth(wc); diff --git a/libbb/unicode.c b/libbb/unicode.c index eb0ea6129..b2c28239b 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c @@ -240,7 +240,7 @@ int FAST_FUNC iswpunct(wint_t wc) } -# if LAST_SUPPORTED_WCHAR >= 0x300 +# if CONFIG_LAST_SUPPORTED_WCHAR >= 0x300 struct interval { uint16_t first; uint16_t last; @@ -420,7 +420,7 @@ static int in_uint16_table(unsigned ucs, const uint16_t *table, unsigned max) */ int FAST_FUNC wcwidth(unsigned ucs) { -# if LAST_SUPPORTED_WCHAR >= 0x300 +# if CONFIG_LAST_SUPPORTED_WCHAR >= 0x300 /* sorted list of non-overlapping intervals of non-spacing characters */ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ # define BIG_(a,b) { a, b }, @@ -579,14 +579,14 @@ int FAST_FUNC wcwidth(unsigned ucs) if ((ucs & ~0x80) < 0x20 || ucs == 0x7f) return -1; /* Quick abort if it is an obviously invalid char */ - if (ucs > LAST_SUPPORTED_WCHAR) + if (ucs > CONFIG_LAST_SUPPORTED_WCHAR) return -1; /* Optimization: no combining chars below 0x300 */ - if (LAST_SUPPORTED_WCHAR < 0x300 || ucs < 0x300) + if (CONFIG_LAST_SUPPORTED_WCHAR < 0x300 || ucs < 0x300) return 1; -# if LAST_SUPPORTED_WCHAR >= 0x300 +# if CONFIG_LAST_SUPPORTED_WCHAR >= 0x300 /* Binary search in table of non-spacing characters */ if (in_interval_table(ucs, combining, ARRAY_SIZE(combining) - 1)) return 0; @@ -594,25 +594,25 @@ int FAST_FUNC wcwidth(unsigned ucs) return 0; /* Optimization: all chars below 0x1100 are not double-width */ - if (LAST_SUPPORTED_WCHAR < 0x1100 || ucs < 0x1100) + if (CONFIG_LAST_SUPPORTED_WCHAR < 0x1100 || ucs < 0x1100) return 1; -# if LAST_SUPPORTED_WCHAR >= 0x1100 +# if CONFIG_LAST_SUPPORTED_WCHAR >= 0x1100 /* Invalid code points: */ /* High (d800..dbff) and low (dc00..dfff) surrogates (valid only in UTF16) */ /* Private Use Area (e000..f8ff) */ /* Noncharacters fdd0..fdef */ - if ((LAST_SUPPORTED_WCHAR >= 0xd800 && ucs >= 0xd800 && ucs <= 0xf8ff) - || (LAST_SUPPORTED_WCHAR >= 0xfdd0 && ucs >= 0xfdd0 && ucs <= 0xfdef) + if ((CONFIG_LAST_SUPPORTED_WCHAR >= 0xd800 && ucs >= 0xd800 && ucs <= 0xf8ff) + || (CONFIG_LAST_SUPPORTED_WCHAR >= 0xfdd0 && ucs >= 0xfdd0 && ucs <= 0xfdef) ) { return -1; } /* 0xfffe and 0xffff in every plane are invalid */ - if (LAST_SUPPORTED_WCHAR >= 0xfffe && ((ucs & 0xfffe) == 0xfffe)) { + if (CONFIG_LAST_SUPPORTED_WCHAR >= 0xfffe && ((ucs & 0xfffe) == 0xfffe)) { return -1; } -# if LAST_SUPPORTED_WCHAR >= 0x10000 +# if CONFIG_LAST_SUPPORTED_WCHAR >= 0x10000 if (ucs >= 0x10000) { /* Combining chars in Supplementary Multilingual Plane 0x1xxxx */ static const struct interval combining0x10000[] = { @@ -625,7 +625,7 @@ int FAST_FUNC wcwidth(unsigned ucs) if (in_interval_table(ucs ^ 0x10000, combining0x10000, ARRAY_SIZE(combining0x10000) - 1)) return 0; /* Check a few non-spacing chars in Supplementary Special-purpose Plane 0xExxxx */ - if (LAST_SUPPORTED_WCHAR >= 0xE0001 + if (CONFIG_LAST_SUPPORTED_WCHAR >= 0xE0001 && ( ucs == 0xE0001 || (ucs >= 0xE0020 && ucs <= 0xE007F) || (ucs >= 0xE0100 && ucs <= 0xE01EF) @@ -644,7 +644,7 @@ int FAST_FUNC wcwidth(unsigned ucs) || ucs == 0x2329 /* left-pointing angle bracket; also CJK punct. char */ || ucs == 0x232a /* right-pointing angle bracket; also CJK punct. char */ || (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) /* CJK ... Yi */ -# if LAST_SUPPORTED_WCHAR >= 0xac00 +# if CONFIG_LAST_SUPPORTED_WCHAR >= 0xac00 || (ucs >= 0xac00 && ucs <= 0xd7a3) /* Hangul Syllables */ || (ucs >= 0xf900 && ucs <= 0xfaff) /* CJK Compatibility Ideographs */ || (ucs >= 0xfe10 && ucs <= 0xfe19) /* Vertical forms */ -- cgit v1.2.3-55-g6feb From d9a3e89f501800c3e7c779b7e9545a5c80134593 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 May 2010 23:42:13 +0200 Subject: consolidate ESC sequences function old new delta bell 2 - -2 CMdown 2 - -2 Ceos 4 - -4 Ceol 4 - -4 CMup 4 - -4 SOs 5 - -5 SOn 5 - -5 CMrc 9 - -9 Signed-off-by: Denys Vlasenko --- console-tools/clear.c | 3 ++- console-tools/reset.c | 10 +++++----- editors/vi.c | 16 ++++++++-------- libbb/lineedit.c | 2 +- miscutils/fbsplash.c | 4 ++-- miscutils/less.c | 10 +++++----- procps/top.c | 8 ++++---- procps/watch.c | 3 ++- 8 files changed, 29 insertions(+), 27 deletions(-) diff --git a/console-tools/clear.c b/console-tools/clear.c index 8b727b39b..b0c6d65d2 100644 --- a/console-tools/clear.c +++ b/console-tools/clear.c @@ -15,5 +15,6 @@ int clear_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int clear_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { - return printf("\033[H\033[J") != 6; + /* home; clear to the end of screen */ + return printf("\033[H""\033[J") != 6; } diff --git a/console-tools/reset.c b/console-tools/reset.c index 6917eda42..f0ea5cb20 100644 --- a/console-tools/reset.c +++ b/console-tools/reset.c @@ -28,11 +28,11 @@ int reset_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { /* See 'man 4 console_codes' for details: - * "ESC c" -- Reset - * "ESC ( K" -- Select user mapping - * "ESC [ J" -- Erase display - * "ESC [ 0 m" -- Reset all display attributes - * "ESC [ ? 25 h" -- Make cursor visible. + * "ESC c" -- Reset + * "ESC ( K" -- Select user mapping + * "ESC [ J" -- Erase to the end of screen + * "ESC [ 0 m" -- Reset all display attributes + * "ESC [ ? 25 h" -- Make cursor visible */ printf("\033c\033(K\033[J\033[0m\033[?25h"); /* http://bugs.busybox.net/view.php?id=1414: diff --git a/editors/vi.c b/editors/vi.c index b8cacb43f..d9124fd76 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -60,18 +60,18 @@ enum { /* vt102 typical ESC sequence */ /* terminal standout start/normal ESC sequence */ -static const char SOs[] ALIGN1 = "\033[7m"; -static const char SOn[] ALIGN1 = "\033[0m"; +#define SOs "\033[7m" +#define SOn "\033[0m" /* terminal bell sequence */ -static const char bell[] ALIGN1 = "\007"; +#define bell "\007" /* Clear-end-of-line and Clear-end-of-screen ESC sequence */ -static const char Ceol[] ALIGN1 = "\033[K"; -static const char Ceos[] ALIGN1 = "\033[J"; +#define Ceol "\033[K" +#define Ceos "\033[J" /* Cursor motion arbitrary destination ESC sequence */ -static const char CMrc[] ALIGN1 = "\033[%d;%dH"; +#define CMrc "\033[%u;%uH" /* Cursor motion up and down ESC sequence */ -static const char CMup[] ALIGN1 = "\033[A"; -static const char CMdown[] ALIGN1 = "\n"; +#define CMup "\033[A" +#define CMdown "\n" #if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK // cmds modifying text[] diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 72a1786ff..bc089ab1c 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -466,7 +466,7 @@ static void input_backward(unsigned num) cmdedit_x = w * count_y - num; } /* go to 1st column; go up; go to correct column */ - printf("\r" "\033[%dA" "\033[%dC", count_y, cmdedit_x); + printf("\r" "\033[%uA" "\033[%uC", count_y, cmdedit_x); } static void put_prompt(void) diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c index 5974006bb..e370d207b 100644 --- a/miscutils/fbsplash.c +++ b/miscutils/fbsplash.c @@ -359,7 +359,7 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) if (fifo_filename && bCursorOff) { // hide cursor (BEFORE any fb ops) - full_write(STDOUT_FILENO, "\x1b" "[?25l", 6); + full_write(STDOUT_FILENO, "\033[?25l", 6); } fb_drawimage(); @@ -404,7 +404,7 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) } if (bCursorOff) // restore cursor - full_write(STDOUT_FILENO, "\x1b" "[?25h", 6); + full_write(STDOUT_FILENO, "\033[?25h", 6); return EXIT_SUCCESS; } diff --git a/miscutils/less.c b/miscutils/less.c index e4f8ab979..848266212 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -29,11 +29,11 @@ #endif /* The escape codes for highlighted and normal text */ -#define HIGHLIGHT "\033[7m" -#define NORMAL "\033[0m" -/* The escape code to clear the screen */ -#define CLEAR "\033[H\033[J" -/* The escape code to clear to end of line */ +#define HIGHLIGHT "\033[7m" +#define NORMAL "\033[0m" +/* The escape code to home and clear to the end of screen */ +#define CLEAR "\033[H\033[J" +/* The escape code to clear to the end of line */ #define CLEAR_2_EOL "\033[K" enum { diff --git a/procps/top.c b/procps/top.c index f5c0a123f..e4afafc4c 100644 --- a/procps/top.c +++ b/procps/top.c @@ -478,8 +478,8 @@ static unsigned long display_header(int scr_width, int *lines_rem_p) snprintf(scrbuf, scr_width, "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", used, mfree, shared, buffers, cached); - /* clear screen & go to top */ - printf(OPT_BATCH_MODE ? "%s\n" : "\e[H\e[J%s\n", scrbuf); + /* go to top & clear to the end of screen */ + printf(OPT_BATCH_MODE ? "%s\n" : "\033[H\033[J%s\n", scrbuf); (*lines_rem_p)--; /* Display CPU time split as percentage of total time @@ -518,7 +518,7 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) #endif /* what info of the processes is shown */ - printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, + printf(OPT_BATCH_MODE ? "%.*s" : "\033[7m%.*s\033[0m", scr_width, " PID PPID USER STAT VSZ %MEM" IF_FEATURE_TOP_SMP_PROCESS(" CPU") IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(" %CPU") @@ -772,7 +772,7 @@ static void display_topmem_header(int scr_width, int *lines_rem_p) snprintf(linebuf, sizeof(linebuf), "Mem total:%s anon:%s map:%s free:%s", S(total), S(anon), S(map), S(mfree)); - printf(OPT_BATCH_MODE ? "%.*s\n" : "\e[H\e[J%.*s\n", scr_width, linebuf); + printf(OPT_BATCH_MODE ? "%.*s\n" : "\033[H\033[J%.*s\n", scr_width, linebuf); snprintf(linebuf, sizeof(linebuf), " slab:%s buf:%s cache:%s dirty:%s write:%s", diff --git a/procps/watch.c b/procps/watch.c index 126945c40..a1cde9ea0 100644 --- a/procps/watch.c +++ b/procps/watch.c @@ -52,7 +52,8 @@ int watch_main(int argc UNUSED_PARAM, char **argv) width = (unsigned)-1; // make sure first time new_width != width header = NULL; while (1) { - printf("\033[H\033[J"); + /* home; clear to the end of screen */ + printf("\033[H""\033[J"); if (!(opt & 0x2)) { // no -t const unsigned time_len = sizeof("1234-67-90 23:56:89"); time_t t; -- cgit v1.2.3-55-g6feb From 248c324f7c6d407467ab3ad9057dfe33fb2723d8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 00:45:44 +0200 Subject: lineedit: fix moving backwards across lines with wide chars function old new delta input_backward 212 208 -4 Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 67 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index bc089ab1c..836fc0089 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -413,12 +413,22 @@ static void beep(void) bb_putchar('\007'); } +static void put_prompt(void) +{ + unsigned w; + + out1str(cmdedit_prompt); + fflush_all(); + cursor = 0; + w = cmdedit_termw; /* read volatile var once */ + cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */ + cmdedit_x = cmdedit_prmt_len % w; +} + /* Move back one character */ /* (optimized for slow terminals) */ static void input_backward(unsigned num) { - int count_y; - if (num > cursor) num = cursor; if (num == 0) @@ -456,29 +466,44 @@ static void input_backward(unsigned num) } /* Need to go one or more lines up */ -//FIXME: this does not work correctly if prev line has one "unfilled" screen position -//caused by wide unicode char not fitting in that one screen position. - num -= cmdedit_x; - { - unsigned w = cmdedit_termw; /* volatile var */ + if (ENABLE_UNICODE_WIDE_WCHARS) { + /* With wide chars, it is hard to "backtrack" + * and reliably figure out where to put cursor. + * Example (<> is a wide char; # is an ordinary char, _ cursor): + * |prompt: <><> | + * |<><><><><><> | + * |_ | + * and user presses left arrow. num = 1, cmdedit_x = 0, + * We need to go up one line, and then - how do we know that + * we need to go *10* positions to the right? Because + * |prompt: <>#<>| + * |<><><>#<><><>| + * |_ | + * in this situation we need to go *11* positions to the right. + * + * A simpler thing to do is to redraw everything from the start + * up to new cursor position (which is already known): + */ + unsigned sv_cursor; + if (cmdedit_y > 0) /* up to start y */ + printf("\033[%uA", cmdedit_y); + bb_putchar('\r'); + cmdedit_y = 0; + sv_cursor = cursor; + put_prompt(); /* sets cursor to 0 */ + while (cursor < sv_cursor) + put_cur_glyph_and_inc_cursor(); + } else { + int count_y; + unsigned w; + num -= cmdedit_x; + w = cmdedit_termw; /* read volatile var once */ count_y = 1 + (num / w); cmdedit_y -= count_y; cmdedit_x = w * count_y - num; + /* go to 1st column; go up; go to correct column */ + printf("\r" "\033[%uA" "\033[%uC", count_y, cmdedit_x); } - /* go to 1st column; go up; go to correct column */ - printf("\r" "\033[%uA" "\033[%uC", count_y, cmdedit_x); -} - -static void put_prompt(void) -{ - unsigned w; - - out1str(cmdedit_prompt); - fflush_all(); - cursor = 0; - w = cmdedit_termw; /* read volatile var once */ - cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */ - cmdedit_x = cmdedit_prmt_len % w; } /* draw prompt, editor line, and clear tail */ -- cgit v1.2.3-55-g6feb From 3015a1351a355434cf5b307114c0506e15f4214a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 01:59:16 +0200 Subject: scripts/gen_build_files.sh: revert to using /bin/sh People want busybox to build w/o bash, with /bin/sh = ash Signed-off-by: Denys Vlasenko --- scripts/gen_build_files.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index ea14de5e2..6982877d8 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # bashism: # "read -r" without variable name reads line into $REPLY # without stripping whitespace. -- cgit v1.2.3-55-g6feb From 27ff681cfa573ce2a63b35c48047f1d7adcb1f02 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 02:56:18 +0200 Subject: ash: add two testcases for (not yet fixed) ash bugs Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/source2.right | 1 + shell/ash_test/ash-misc/source2.tests | 4 ++++ shell/ash_test/ash-signals/signal5.right | 12 ++++++++++++ shell/ash_test/ash-signals/signal5.tests | 14 ++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 shell/ash_test/ash-misc/source2.right create mode 100755 shell/ash_test/ash-misc/source2.tests create mode 100644 shell/ash_test/ash-signals/signal5.right create mode 100755 shell/ash_test/ash-signals/signal5.tests diff --git a/shell/ash_test/ash-misc/source2.right b/shell/ash_test/ash-misc/source2.right new file mode 100644 index 000000000..ce7171c87 --- /dev/null +++ b/shell/ash_test/ash-misc/source2.right @@ -0,0 +1 @@ +Done: 0 diff --git a/shell/ash_test/ash-misc/source2.tests b/shell/ash_test/ash-misc/source2.tests new file mode 100755 index 000000000..ab63247ef --- /dev/null +++ b/shell/ash_test/ash-misc/source2.tests @@ -0,0 +1,4 @@ +# Not fixed yet +false +. /dev/null +echo Done: $? diff --git a/shell/ash_test/ash-signals/signal5.right b/shell/ash_test/ash-signals/signal5.right new file mode 100644 index 000000000..35fcbd63d --- /dev/null +++ b/shell/ash_test/ash-signals/signal5.right @@ -0,0 +1,12 @@ +Waiting +sleeping for 1 sec +sleeping for 2 sec +1 sec passed, sending USR1 to parent +USR1 received +Wait exit code: 138 +Waiting +2 sec passed, sending USR1 to parent +USR1 received +Wait exit code: 138 +Waiting +Wait returned 0 diff --git a/shell/ash_test/ash-signals/signal5.tests b/shell/ash_test/ash-signals/signal5.tests new file mode 100755 index 000000000..b75b14917 --- /dev/null +++ b/shell/ash_test/ash-signals/signal5.tests @@ -0,0 +1,14 @@ +# Not fixed yet +trap "echo USR1 received" USR1 +stub() { + echo "sleeping for $1 sec" + sleep $1 + echo "$1 sec passed, sending USR1 to parent" + kill -USR1 $$ +} +stub 2 & +stub 1 & +until { echo "Waiting"; wait; } do + echo "Wait exit code: $?" +done +echo "Wait returned 0" -- cgit v1.2.3-55-g6feb From 9963fe36c2af2bf99fcbd2eae6e9e050c8cf779b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 04:05:53 +0200 Subject: lineedit: trivial simplifications. -7 bytes Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 836fc0089..36d057bbb 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -397,17 +397,10 @@ static void put_till_end_and_adv_cursor(void) static void goto_new_line(void) { put_till_end_and_adv_cursor(); - if (cmdedit_x) + if (cmdedit_x != 0) bb_putchar('\n'); } - -static void out1str(const char *s) -{ - if (s) - fputs(s, stdout); -} - static void beep(void) { bb_putchar('\007'); @@ -417,7 +410,7 @@ static void put_prompt(void) { unsigned w; - out1str(cmdedit_prompt); + fputs(cmdedit_prompt, stdout); fflush_all(); cursor = 0; w = cmdedit_termw; /* read volatile var once */ @@ -485,9 +478,8 @@ static void input_backward(unsigned num) * up to new cursor position (which is already known): */ unsigned sv_cursor; - if (cmdedit_y > 0) /* up to start y */ - printf("\033[%uA", cmdedit_y); - bb_putchar('\r'); + /* go to 1st column; go up to first line */ + printf("\r" "\033[%uA", cmdedit_y); cmdedit_y = 0; sv_cursor = cursor; put_prompt(); /* sets cursor to 0 */ @@ -509,7 +501,7 @@ static void input_backward(unsigned num) /* draw prompt, editor line, and clear tail */ static void redraw(int y, int back_cursor) { - if (y > 0) /* up to start y */ + if (y > 0) /* up y lines */ printf("\033[%uA", y); bb_putchar('\r'); put_prompt(); @@ -1616,7 +1608,7 @@ static void ask_terminal(void) pfd.events = POLLIN; if (safe_poll(&pfd, 1, 0) == 0) { S.sent_ESC_br6n = 1; - out1str("\033" "[6n"); + fputs("\033" "[6n", stdout); fflush_all(); /* make terminal see it ASAP! */ } } -- cgit v1.2.3-55-g6feb From 7c1ed9fbdedb6cd038df11322a82ac7aea412524 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 04:42:40 +0200 Subject: ash: fix signal5.tests Signed-off-by: Denys Vlasenko --- shell/ash.c | 17 ++++++++++++----- shell/ash_test/ash-signals/signal5.tests | 1 - 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index ec5e0b8c7..ef22da1b6 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3874,9 +3874,9 @@ dowait(int wait_flags, struct job *job) } static int -blocking_wait_with_raise_on_sig(struct job *job) +blocking_wait_with_raise_on_sig(void) { - pid_t pid = dowait(DOWAIT_BLOCK, job); + pid_t pid = dowait(DOWAIT_BLOCK, NULL); if (pid <= 0 && pending_sig) raise_exception(EXSIG); return pid; @@ -4069,14 +4069,21 @@ waitcmd(int argc UNUSED_PARAM, char **argv) jp->waited = 1; jp = jp->prev_job; } + blocking_wait_with_raise_on_sig(); /* man bash: * "When bash is waiting for an asynchronous command via * the wait builtin, the reception of a signal for which a trap * has been set will cause the wait builtin to return immediately * with an exit status greater than 128, immediately after which * the trap is executed." - * Do we do it that way? */ - blocking_wait_with_raise_on_sig(NULL); + * + * blocking_wait_with_raise_on_sig raises signal handlers + * if it gets no pid (pid < 0). However, + * if child sends us a signal *and immediately exits*, + * blocking_wait_with_raise_on_sig gets pid > 0 + * and does not handle pending_sig. Check this case: */ + if (pending_sig) + raise_exception(EXSIG); } } @@ -4096,7 +4103,7 @@ waitcmd(int argc UNUSED_PARAM, char **argv) job = getjob(*argv, 0); /* loop until process terminated or stopped */ while (job->state == JOBRUNNING) - blocking_wait_with_raise_on_sig(NULL); + blocking_wait_with_raise_on_sig(); job->waited = 1; retval = getstatus(job); repeat: ; diff --git a/shell/ash_test/ash-signals/signal5.tests b/shell/ash_test/ash-signals/signal5.tests index b75b14917..5003180f7 100755 --- a/shell/ash_test/ash-signals/signal5.tests +++ b/shell/ash_test/ash-signals/signal5.tests @@ -1,4 +1,3 @@ -# Not fixed yet trap "echo USR1 received" USR1 stub() { echo "sleeping for $1 sec" -- cgit v1.2.3-55-g6feb From 0f01b00d742f92061cbbd9e95d1cd0368c4d2a4c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 04:57:55 +0200 Subject: add two more tests which currently fail Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-signals/signal6.right | 2 ++ shell/ash_test/ash-signals/signal6.tests | 3 +++ shell/hush_test/hush-bugs/parse_err.right | 2 ++ shell/hush_test/hush-bugs/parse_err.tests | 3 +++ 4 files changed, 10 insertions(+) create mode 100644 shell/ash_test/ash-signals/signal6.right create mode 100755 shell/ash_test/ash-signals/signal6.tests create mode 100644 shell/hush_test/hush-bugs/parse_err.right create mode 100755 shell/hush_test/hush-bugs/parse_err.tests diff --git a/shell/ash_test/ash-signals/signal6.right b/shell/ash_test/ash-signals/signal6.right new file mode 100644 index 000000000..df4d9306a --- /dev/null +++ b/shell/ash_test/ash-signals/signal6.right @@ -0,0 +1,2 @@ +got TERM +Done: 0 diff --git a/shell/ash_test/ash-signals/signal6.tests b/shell/ash_test/ash-signals/signal6.tests new file mode 100755 index 000000000..ffeded2a5 --- /dev/null +++ b/shell/ash_test/ash-signals/signal6.tests @@ -0,0 +1,3 @@ +# Bug: TERM does not trigger in the child +{ trap "echo got TERM" TERM; sleep 3; }& sleep 1; kill $!; wait +echo Done: $? diff --git a/shell/hush_test/hush-bugs/parse_err.right b/shell/hush_test/hush-bugs/parse_err.right new file mode 100644 index 000000000..df4d9306a --- /dev/null +++ b/shell/hush_test/hush-bugs/parse_err.right @@ -0,0 +1,2 @@ +got TERM +Done: 0 diff --git a/shell/hush_test/hush-bugs/parse_err.tests b/shell/hush_test/hush-bugs/parse_err.tests new file mode 100755 index 000000000..dd7d9ad64 --- /dev/null +++ b/shell/hush_test/hush-bugs/parse_err.tests @@ -0,0 +1,3 @@ +# Bug happens only if there is no space in "}&" +{ trap "echo got TERM" TERM; sleep 3; }& sleep 1; kill $!; wait +echo Done: $? -- cgit v1.2.3-55-g6feb From 3227d3f982e809fd02b37d6274f1c7da0a307cea Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 09:49:47 +0200 Subject: hush: fix hush-bugs/parse_err.tests function old new delta parse_stream 2325 2339 +14 builtin_umask 121 123 +2 builtin_type 116 114 -2 Signed-off-by: Denys Vlasenko --- shell/hush.c | 13 +++++++++---- shell/hush_test/hush-bugs/parse_err.right | 2 -- shell/hush_test/hush-bugs/parse_err.tests | 3 --- shell/hush_test/hush-parsing/group2.right | 2 ++ shell/hush_test/hush-parsing/group2.tests | 3 +++ 5 files changed, 14 insertions(+), 9 deletions(-) delete mode 100644 shell/hush_test/hush-bugs/parse_err.right delete mode 100755 shell/hush_test/hush-bugs/parse_err.tests create mode 100644 shell/hush_test/hush-parsing/group2.right create mode 100755 shell/hush_test/hush-parsing/group2.tests diff --git a/shell/hush.c b/shell/hush.c index 07cacbfc9..1bc0c611d 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6232,10 +6232,15 @@ static struct pipe *parse_stream(char **pstring, is_special = "{}<>;&|()#'" /* special outside of "str" */ "\\$\"" IF_HUSH_TICK("`"); /* always special */ /* Are { and } special here? */ - if (ctx.command->argv /* word [word]{... */ - || dest.length /* word{... */ - || dest.o_quoted /* ""{... */ - || (next != ';' && next != ')' && !strchr(G.ifs, next)) /* {word */ + if (ctx.command->argv /* word [word]{... - non-special */ + || dest.length /* word{... - non-special */ + || dest.o_quoted /* ""{... - non-special */ + || (next != ';' /* }; - special */ + && next != ')' /* }) - special */ + && next != '&' /* }& and }&& ... - special */ + && next != '|' /* }|| ... - special */ + && !strchr(G.ifs, next) /* {word - non-special */ + ) ) { /* They are not special, skip "{}" */ is_special += 2; diff --git a/shell/hush_test/hush-bugs/parse_err.right b/shell/hush_test/hush-bugs/parse_err.right deleted file mode 100644 index df4d9306a..000000000 --- a/shell/hush_test/hush-bugs/parse_err.right +++ /dev/null @@ -1,2 +0,0 @@ -got TERM -Done: 0 diff --git a/shell/hush_test/hush-bugs/parse_err.tests b/shell/hush_test/hush-bugs/parse_err.tests deleted file mode 100755 index dd7d9ad64..000000000 --- a/shell/hush_test/hush-bugs/parse_err.tests +++ /dev/null @@ -1,3 +0,0 @@ -# Bug happens only if there is no space in "}&" -{ trap "echo got TERM" TERM; sleep 3; }& sleep 1; kill $!; wait -echo Done: $? diff --git a/shell/hush_test/hush-parsing/group2.right b/shell/hush_test/hush-parsing/group2.right new file mode 100644 index 000000000..df4d9306a --- /dev/null +++ b/shell/hush_test/hush-parsing/group2.right @@ -0,0 +1,2 @@ +got TERM +Done: 0 diff --git a/shell/hush_test/hush-parsing/group2.tests b/shell/hush_test/hush-parsing/group2.tests new file mode 100755 index 000000000..d99178585 --- /dev/null +++ b/shell/hush_test/hush-parsing/group2.tests @@ -0,0 +1,3 @@ +# Bug was in handling of "}&" without space +{ trap "echo got TERM" TERM; sleep 2; }& sleep 1; kill $!; wait +echo Done: $? -- cgit v1.2.3-55-g6feb From ef215558fa261d0aeb653ea49efebcf2811d59a3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 09:55:13 +0200 Subject: typo fix Signed-off-by: Denys Vlasenko --- include/usage.h | 2 +- shell/Config.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/usage.h b/include/usage.h index be52f187f..3fce939bb 100644 --- a/include/usage.h +++ b/include/usage.h @@ -657,7 +657,7 @@ "\n ::respawn:/bin/cttyhack /bin/sh" \ "\nGiving controlling tty to shell running with PID 1:" \ "\n $ exec cttyhack sh" \ - "\nStarting an interative shell from boot shell script:" \ + "\nStarting interactive shell from boot shell script:" \ "\n setsid cttyhack sh" \ #define cut_trivial_usage \ diff --git a/shell/Config.in b/shell/Config.in index 36a931715..cf599dff4 100644 --- a/shell/Config.in +++ b/shell/Config.in @@ -366,7 +366,7 @@ config CTTYHACK $ exec cttyhack sh - Starting an interative shell from boot shell script: + Starting an interactive shell from boot shell script: setsid cttyhack sh -- cgit v1.2.3-55-g6feb From 82dd14a510caf192c90e764f36bf424d647b5376 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 10:10:01 +0200 Subject: ash: use CONFIG_FEATURE_EDITING_MAX_LEN Signed-off-by: Denys Vlasenko --- init/bootchartd.c | 2 +- shell/ash.c | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/init/bootchartd.c b/init/bootchartd.c index 9faf14d36..d1f9ed30e 100644 --- a/init/bootchartd.c +++ b/init/bootchartd.c @@ -57,7 +57,7 @@ /* Globals */ struct globals { - char jiffy_line[sizeof(bb_common_bufsiz1)]; + char jiffy_line[COMMON_BUFSIZE]; } FIX_ALIASING; #define G (*(struct globals*)&bb_common_bufsiz1) #define INIT_G() do { } while (0) diff --git a/shell/ash.c b/shell/ash.c index ef22da1b6..75bfbf115 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2589,9 +2589,7 @@ pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) /* ============ ... */ -#define IBUFSIZ COMMON_BUFSIZE -/* buffer for top level input file */ -#define basebuf bb_common_bufsiz1 +#define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024) /* Syntax classes */ #define CWORD 0 /* character is nothing special */ @@ -9447,12 +9445,12 @@ preadfd(void) #if ENABLE_FEATURE_EDITING retry: if (!iflag || g_parsefile->fd != STDIN_FILENO) - nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1); + nr = nonblock_safe_read(g_parsefile->fd, buf, IBUFSIZ - 1); else { #if ENABLE_FEATURE_TAB_COMPLETION line_input_state->path_lookup = pathval(); #endif - nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state); + nr = read_line_input(cmdedit_prompt, buf, IBUFSIZ, line_input_state); if (nr == 0) { /* Ctrl+C pressed */ if (trap[SIGINT]) { @@ -9469,7 +9467,7 @@ preadfd(void) } } #else - nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1); + nr = nonblock_safe_read(g_parsefile->fd, buf, IBUFSIZ - 1); #endif #if 0 @@ -12728,7 +12726,8 @@ static void init(void) { /* from input.c: */ - basepf.next_to_pgetc = basepf.buf = basebuf; + /* we will never free this */ + basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ); /* from trap.c: */ signal(SIGCHLD, SIG_DFL); -- cgit v1.2.3-55-g6feb From 786cce1871ade4240c629187d6609de155fe3536 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 10:14:20 +0200 Subject: fix false positive in signal5.tests Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-signals/signal5.right | 8 ++++---- shell/ash_test/ash-signals/signal5.tests | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/shell/ash_test/ash-signals/signal5.right b/shell/ash_test/ash-signals/signal5.right index 35fcbd63d..162f56bbc 100644 --- a/shell/ash_test/ash-signals/signal5.right +++ b/shell/ash_test/ash-signals/signal5.right @@ -1,11 +1,11 @@ -Waiting -sleeping for 1 sec +sleeping for 3 sec sleeping for 2 sec -1 sec passed, sending USR1 to parent +Waiting +2 sec passed, sending USR1 to parent USR1 received Wait exit code: 138 Waiting -2 sec passed, sending USR1 to parent +3 sec passed, sending USR1 to parent USR1 received Wait exit code: 138 Waiting diff --git a/shell/ash_test/ash-signals/signal5.tests b/shell/ash_test/ash-signals/signal5.tests index 5003180f7..371120e95 100755 --- a/shell/ash_test/ash-signals/signal5.tests +++ b/shell/ash_test/ash-signals/signal5.tests @@ -5,8 +5,9 @@ stub() { echo "$1 sec passed, sending USR1 to parent" kill -USR1 $$ } +stub 3 & stub 2 & -stub 1 & +sleep 1 until { echo "Waiting"; wait; } do echo "Wait exit code: $?" done -- cgit v1.2.3-55-g6feb From 1118d9b213e4cad56e6f79c1753e0a52defadaa5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 12:30:44 +0200 Subject: lineedit: fix insertion deep inside line (*several lines* before end) function old new delta input_backward 212 229 +17 Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 36d057bbb..f7d3ffed8 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -486,15 +486,22 @@ static void input_backward(unsigned num) while (cursor < sv_cursor) put_cur_glyph_and_inc_cursor(); } else { - int count_y; - unsigned w; + int lines_up; + unsigned width; + /* num = chars to go back from the beginning of current line: */ num -= cmdedit_x; - w = cmdedit_termw; /* read volatile var once */ - count_y = 1 + (num / w); - cmdedit_y -= count_y; - cmdedit_x = w * count_y - num; - /* go to 1st column; go up; go to correct column */ - printf("\r" "\033[%uA" "\033[%uC", count_y, cmdedit_x); + width = cmdedit_termw; /* read volatile var once */ + /* num=1...w: one line up, w+1...2w: two, etc: */ + lines_up = 1 + (num - 1) / width; + cmdedit_x = (width * cmdedit_y - num) % width; + cmdedit_y -= lines_up; + /* go to 1st column; go up */ + printf("\r" "\033[%uA", lines_up); + /* go to correct column. + * xtarm, konsole, Linux VT interpret 0 as 1 below! wow. + * Need to *make sure* we skip it if cmdedit_x == 0 */ + if (cmdedit_x) + printf("\033[%uC", cmdedit_x); } } -- cgit v1.2.3-55-g6feb From bbf1aa1eaf6278e23ae75914c8d9b9be4d0e28f5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 12:33:13 +0200 Subject: typo fix Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index f7d3ffed8..18664b8c1 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -498,8 +498,8 @@ static void input_backward(unsigned num) /* go to 1st column; go up */ printf("\r" "\033[%uA", lines_up); /* go to correct column. - * xtarm, konsole, Linux VT interpret 0 as 1 below! wow. - * Need to *make sure* we skip it if cmdedit_x == 0 */ + * xterm, konsole, Linux VT interpret 0 as 1 below! wow. + * need to *make sure* we skip it if cmdedit_x == 0 */ if (cmdedit_x) printf("\033[%uC", cmdedit_x); } -- cgit v1.2.3-55-g6feb From cd10dc40e4057d081caf7676a4fed31977f2d94d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 17:10:46 +0200 Subject: ash: fix ". empty_file" exitcode. +5 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 8 +++++--- shell/ash_test/ash-misc/source2.tests | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 75bfbf115..ef5b2d4c1 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12031,13 +12031,16 @@ dotcmd(int argc, char **argv) { struct strlist *sp; volatile struct shparam saveparam; - int status = 0; for (sp = cmdenviron; sp; sp = sp->next) setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED); + /* "false; . empty_file; echo $?" should print 0, not 1: */ + exitstatus = 0; + if (argv[1]) { /* That's what SVR2 does */ char *fullname = find_dot_file(argv[1]); + argv += 2; argc -= 2; if (argc) { /* argc > 0, argv[0] != NULL */ @@ -12056,9 +12059,8 @@ dotcmd(int argc, char **argv) freeparam(&shellparam); shellparam = saveparam; }; - status = exitstatus; } - return status; + return exitstatus; } static int FAST_FUNC diff --git a/shell/ash_test/ash-misc/source2.tests b/shell/ash_test/ash-misc/source2.tests index ab63247ef..1870cdf7e 100755 --- a/shell/ash_test/ash-misc/source2.tests +++ b/shell/ash_test/ash-misc/source2.tests @@ -1,4 +1,3 @@ -# Not fixed yet false . /dev/null echo Done: $? -- cgit v1.2.3-55-g6feb From 82731b4b7a5634bdee52d98b1a7686e18a861ebc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 17:49:52 +0200 Subject: ash,hush: make "source" a synonym for . if bash compat is on Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 ++ shell/hush.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/shell/ash.c b/shell/ash.c index ef5b2d4c1..ea813e02f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8944,7 +8944,9 @@ static const struct builtincmd builtintab[] = { { BUILTIN_SPEC_REG "return" , returncmd }, { BUILTIN_SPEC_REG "set" , setcmd }, { BUILTIN_SPEC_REG "shift" , shiftcmd }, +#if ENABLE_ASH_BASH_COMPAT { BUILTIN_SPEC_REG "source" , dotcmd }, +#endif #if ENABLE_ASH_BUILTIN_TEST { BUILTIN_REGULAR "test" , testcmd }, #endif diff --git a/shell/hush.c b/shell/hush.c index 1bc0c611d..a88fa055b 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -673,6 +673,9 @@ static const struct built_in_command bltins1[] = { #endif BLTIN("set" , builtin_set , "Set/unset positional parameters"), BLTIN("shift" , builtin_shift , "Shift positional parameters"), +#if ENABLE_HUSH_BASH_COMPAT + BLTIN("source" , builtin_source , "Run commands in a file"), +#endif BLTIN("trap" , builtin_trap , "Trap signals"), BLTIN("type" , builtin_type , "Show command type"), BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"), -- cgit v1.2.3-55-g6feb From adc0e20892d55b8c762c6d259d3c87a100aec14d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 18:56:58 +0200 Subject: hush: update bash compat todo comment Signed-off-by: Denys Vlasenko --- shell/hush.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index a88fa055b..e6c083f55 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -39,21 +39,24 @@ * * POSIX syntax not implemented: * aliases - * <(list) and >(list) Process Substitution * Tilde Expansion * - * Bash stuff (optionally enabled): - * &> and >& redirection of stdout+stderr - * Brace Expansion - * reserved words: [[ ]] function select - * substrings ${var:1:5} + * Bash compat TODO: + * redirection of stdout+stderr: &> and >& + * brace expansion: one/{two,three,four} + * reserved words: function select + * advanced test: [[ ]] + * substrings: ${var:1:5} + * process substitution: <(list) and >(list) + * =~: regex operator * let EXPR [EXPR...] * Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION) * If the last arg evaluates to 0, let returns 1; 0 otherwise. * NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used) * ((EXPR)) * The EXPR is evaluated according to ARITHMETIC EVALUATION. - * This is exactly equivalent to let "expression". + * This is exactly equivalent to let "EXPR". + * $[EXPR]: synonym for $((EXPR)) * * TODOs: * grep for "TODO" and fix (some of them are easy) -- cgit v1.2.3-55-g6feb From 0e81e488fdec7d6b1d96439407b8a50737d35929 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 May 2010 23:51:00 +0200 Subject: shell/README: describe special builtins Signed-off-by: Denys Vlasenko --- shell/README | 190 ++++++++++++++++++++++++++--------------------------------- 1 file changed, 82 insertions(+), 108 deletions(-) diff --git a/shell/README b/shell/README index 59efe499f..550c712d3 100644 --- a/shell/README +++ b/shell/README @@ -1,108 +1,82 @@ -Various bits of what is known about busybox shells, in no particular order. - -2008-02-14 -ash: does not restore tty pgrp if killed by HUP. Symptom: Midnight Commander -is backgrounded if you started ash under it, and then killed it with HUP. - -2007-11-23 -hush: fixed bogus glob handling; fixed exec <"$1"; added test and echo builtins - -2007-06-13 -hush: exec <"$1" doesn't do parameter subst - -2007-05-24 -hush: environment-related memory leak plugged, with net code size -decrease. - -2007-05-24 -hush: '( echo ${name )' will show syntax error message, but prompt -doesn't return (need to press ). Pressing Ctrl-C, , -'( echo ${name )' again, Ctrl-C segfaults. - -2007-05-21 -hush: environment cannot be handled by libc routines as they are leaky -(by API design and thus unfixable): hush will leak memory in this script, -bash does not: -pid=$$ -while true; do - unset t; - t=111111111111111111111111111111111111111111111111111111111111111111111111 - export t - ps -o vsz,pid,comm | grep " $pid " -done -The fix is to not use setenv/putenv/unsetenv but manipulate env ourself. TODO. -hush: meanwhile, first three command subst bugs mentioned below are fixed. :) - -2007-05-06 -hush: more bugs spotted. Comparison with bash: -bash-3.2# echo "TEST`date;echo;echo`BEST" -TESTSun May 6 09:21:05 CEST 2007BEST [we dont strip eols] -bash-3.2# echo "TEST`echo '$(echo ZZ)'`BEST" -TEST$(echo ZZ)BEST [we execute inner echo] -bash-3.2# echo "TEST`echo "'"`BEST" -TEST'BEST [we totally mess up this one] -bash-3.2# echo `sleep 5` -[Ctrl-C should work, Ctrl-Z should do nothing][we totally mess up this one] -bash-3.2# if true; then -> [Ctrl-C] -bash-3.2# [we re-issue "> "] -bash-3.2# if echo `sleep 5`; then -> true; fi [we execute sleep before "> "] - -2007-05-04 -hush: made ctrl-Z/C work correctly for "while true; do true; done" -(namely, it backgrounds/interrupts entire "while") - -2007-05-03 -hush: new bug spotted: Ctrl-C on "while true; do true; done" doesn't -work right: -# while true; do true; done -[1] 0 true <-- pressing Ctrl-C several times... -[2] 0 true -[3] 0 true -Segmentation fault - -2007-05-03 -hush: update on "sleep 1 | exit 3; echo $?" bug. -parse_stream_outer() repeatedly calls parse_stream(). -parse_stream() is now fixed to stop on ';' in this example, -fixing it (parse_stream_outer() will call parse_stream() 1st time, -execute the parse tree, call parse_stream() 2nd time and execute the tree). -But it's not the end of story. -In more complex situations we _must_ parse way farther before executing. -Example #2: "{ sleep 1 | exit 3; echo $?; ...few_lines... } >file". -Because of redirection, we cannot execute 1st pipe before we parse it all. -We probably need to learn to store $var expressions in parse tree. -Debug printing of parse tree would be nice too. - -2007-04-28 -hush: Ctrl-C and Ctrl-Z for single NOFORK commands are working. -Memory and other resource leaks (opendir) are not addressed -(testcase is "rm -i" interrupted by ctrl-c). - -2007-04-21 -hush: "sleep 5 | sleep 6" + Ctrl-Z + fg seems to work. -"rm -i" + Ctrl-C, "sleep 5" + Ctrl-Z still doesn't work -for SH_STANDALONE case :( - -2007-04-21 -hush: fixed non-backgrounding of "sleep 1 &" and totally broken -"sleep 1 | sleep 2 &". Noticed a bug where successive jobs -get numbers 1,2,3 even when job #1 has exited before job# 2 is started. -(bash reuses #1 in this case) - -2007-04-21 -hush: "sleep 1 | exit 3; echo $?" prints 0 because $? is substituted -_before_ pipe gets executed!! run_list_real() already has "pipe;echo" -parsed and handed to it for execution, so it sees "pipe"; "echo 0". - -2007-04-21 -hush: removed setsid() and made job control sort-of-sometimes-work. -Ctrl-C in "rm -i" works now except for SH_STANDALONE case. -"sleep 1 | exit 3" + "echo $?" works, "sleep 1 | exit 3; echo $?" -shows exitcode 0 (should be 3). "sleep 1 | sleep 2 &" fails horribly. - -2007-04-14 -lash, hush: both do setsid() and as a result don't have ctty! -Ctrl-C doesn't work for any child (try rm -i), etc... -lash: bare ">file" doesn't create a file (hush works) +http://www.opengroup.org/onlinepubs/9699919799/ +Open Group Base Specifications Issue 7 + + +http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html +Shell & Utilities + +It says that any of the standard utilities may be implemented +as a regular shell built-in. It gives a list of utilities which +are usually implemented that way (and some of them can only +be implemented as built-ins, like "alias"): + +alias +bg +cd +command +false +fc +fg +getopts +jobs +kill +newgrp +pwd +read +true +umask +unalias +wait + + +http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html +Shell Command Language + +It says that shell must implement special built-ins. Special built-ins +differ from regular ones by the fact that variable assignments +done on special builtin is *PRESERVED*. That is, + +VAR=VAL special_builtin; echo $VAR + +should print VAL. + +(Another distinction is that an error in special built-in should +abort the shell, but this is not such a critical difference, +and moreover, at least bash's "set" does not follow this rule, +which is even codified in autoconf now...). + +List of special builtins: + +. file +: [argument...] +break [n] +continue [n] +eval [argument...] +exec [command [argument...]] +exit [n] +export name[=word]... +export -p +readonly name[=word]... +readonly -p +return [n] +set [-abCefhmnuvx] [-o option] [argument...] +set [+abCefhmnuvx] [+o option] [argument...] +set -- [argument...] +set -o +set +o +shift [n] +times +trap n [condition...] +trap [action condition...] +unset [-fv] name... + +In practice, no one uses this obscure feature - none of these builtins +gives any special reasons to play such dirty tricks. + +However. This section says that *function invocation* should act +similar to special built-in. That is, variable assignments +done on function invocation should be preserved after function invocation. + +This is significant: it is not unthinkable to want to run a function +with some variables set to special values. But because of the above, +it does not work: variable will "leak" out of the function. -- cgit v1.2.3-55-g6feb From a1db8b8415cbac40c679a1ac11f90e97bf5a95f9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 May 2010 00:24:17 +0200 Subject: make scripts/gen_build_files.sh standard-clean Signed-off-by: Denys Vlasenko --- scripts/gen_build_files.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index 6982877d8..d2db907f3 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -1,7 +1,4 @@ #!/bin/sh -# bashism: -# "read -r" without variable name reads line into $REPLY -# without stripping whitespace. test $# -ge 2 || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } @@ -18,7 +15,12 @@ find -type d | while read -r d; do s=`sed -n 's@^//kbuild:@@p' -- "$srctree/$d"/*.c` echo "# DO NOT EDIT. This file is generated from Kbuild.src" >"$dst.$$.tmp" - while read -r; do + + # Why "IFS='' read -r REPLY"?? + # This atrocity is needed to read lines without mangling. + # IFS='' prevents whitespace trimming, + # -r suppresses backslash handling. + while IFS='' read -r REPLY; do test x"$REPLY" = x"INSERT" && REPLY="$s" printf "%s\n" "$REPLY" done <"$src" >>"$dst.$$.tmp" @@ -38,7 +40,8 @@ find -type d | while read -r d; do s=`sed -n 's@^//config:@@p' -- "$srctree/$d"/*.c` echo "# DO NOT EDIT. This file is generated from Config.src" >"$dst.$$.tmp" - while read -r; do + + while IFS='' read -r REPLY; do test x"$REPLY" = x"INSERT" && REPLY="$s" printf "%s\n" "$REPLY" done <"$src" >>"$dst.$$.tmp" -- cgit v1.2.3-55-g6feb From e66cf821cf1e4bd8c1ef28445c0559269f69bab9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 May 2010 09:12:53 +0200 Subject: ash,hush: make bare "." set exitcode to 2 function old new delta dotcmd 300 305 +5 builtin_source 176 171 -5 Signed-off-by: Denys Vlasenko --- shell/ash.c | 45 +++++++++++++++++++++++++-------------------- shell/hush.c | 23 ++++++++++++++--------- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index ea813e02f..641a14035 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12031,37 +12031,42 @@ find_dot_file(char *name) static int FAST_FUNC dotcmd(int argc, char **argv) { + char *fullname; struct strlist *sp; volatile struct shparam saveparam; for (sp = cmdenviron; sp; sp = sp->next) setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED); + if (!argv[1]) { + /* bash says: "bash: .: filename argument required" */ + return 2; /* bash compat */ + } + /* "false; . empty_file; echo $?" should print 0, not 1: */ exitstatus = 0; - if (argv[1]) { /* That's what SVR2 does */ - char *fullname = find_dot_file(argv[1]); + fullname = find_dot_file(argv[1]); - argv += 2; - argc -= 2; - if (argc) { /* argc > 0, argv[0] != NULL */ - saveparam = shellparam; - shellparam.malloced = 0; - shellparam.nparam = argc; - shellparam.p = argv; - }; - - setinputfile(fullname, INPUT_PUSH_FILE); - commandname = fullname; - cmdloop(0); - popfile(); + argv += 2; + argc -= 2; + if (argc) { /* argc > 0, argv[0] != NULL */ + saveparam = shellparam; + shellparam.malloced = 0; + shellparam.nparam = argc; + shellparam.p = argv; + }; + + setinputfile(fullname, INPUT_PUSH_FILE); + commandname = fullname; + cmdloop(0); + popfile(); + + if (argc) { + freeparam(&shellparam); + shellparam = saveparam; + }; - if (argc) { - freeparam(&shellparam); - shellparam = saveparam; - }; - } return exitstatus; } diff --git a/shell/hush.c b/shell/hush.c index e6c083f55..8baccf246 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7870,21 +7870,26 @@ static int FAST_FUNC builtin_shift(char **argv) static int FAST_FUNC builtin_source(char **argv) { - char *arg_path; + char *arg_path, *filename; FILE *input; save_arg_t sv; #if ENABLE_HUSH_FUNCTIONS smallint sv_flg; #endif - if (*++argv == NULL) - return EXIT_FAILURE; - - if (strchr(*argv, '/') == NULL && (arg_path = find_in_path(*argv)) != NULL) { - input = fopen_for_read(arg_path); - free(arg_path); - } else - input = fopen_or_warn(*argv, "r"); + arg_path = NULL; + filename = *++argv; + if (!filename) { + /* bash says: "bash: .: filename argument required" */ + return 2; /* bash compat */ + } + if (!strchr(filename, '/')) { + arg_path = find_in_path(filename); + if (arg_path) + filename = arg_path; + } + input = fopen_or_warn(filename, "r"); + free(arg_path); if (!input) { /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ return EXIT_FAILURE; -- cgit v1.2.3-55-g6feb From 5e2d572381dd0c354a4463382fe1297c709a8464 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 May 2010 14:11:21 +0200 Subject: ash: fix testsuite false positives Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-redir/redir3.tests | 2 +- shell/ash_test/ash-redir/redir7.tests | 2 +- shell/ash_test/ash-redir/redir8.tests | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/ash_test/ash-redir/redir3.tests b/shell/ash_test/ash-redir/redir3.tests index f50a7674c..e37d5e45a 100755 --- a/shell/ash_test/ash-redir/redir3.tests +++ b/shell/ash_test/ash-redir/redir3.tests @@ -1,4 +1,4 @@ -# redirects to closed descriptors should not leave these descriptors" +# redirects to closed descriptors should not leave these descriptors # open afterwards echo TEST 9>/dev/null echo MUST ERROR OUT >&9 diff --git a/shell/ash_test/ash-redir/redir7.tests b/shell/ash_test/ash-redir/redir7.tests index 17d1040e0..ca3979a81 100755 --- a/shell/ash_test/ash-redir/redir7.tests +++ b/shell/ash_test/ash-redir/redir7.tests @@ -7,6 +7,6 @@ echo -e 'echo Ok >uni\x81code' >>unicode.sh echo -e 'cat uni\x81code' >>unicode.sh echo -e 'cat uni?code' >>unicode.sh -. unicode.sh +. ./unicode.sh rm uni*code* echo Done diff --git a/shell/ash_test/ash-redir/redir8.tests b/shell/ash_test/ash-redir/redir8.tests index 32ab607b8..8cb42c0d3 100755 --- a/shell/ash_test/ash-redir/redir8.tests +++ b/shell/ash_test/ash-redir/redir8.tests @@ -10,6 +10,6 @@ echo -e 'v=uni\x81code' >>unicode.sh echo -e 'echo Ok >"$v"' >>unicode.sh echo -e 'cat uni\x81code' >>unicode.sh echo -e 'cat uni?code' >>unicode.sh -. unicode.sh +. ./unicode.sh rm uni*code* echo Done -- cgit v1.2.3-55-g6feb From 51b4a9e2f192c03039f339401026752f6340df25 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 May 2010 14:35:20 +0200 Subject: ash: fix var_leak testcase Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-vars/var_leak.right | 3 ++- shell/ash_test/ash-vars/var_leak.tests | 19 ++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/shell/ash_test/ash-vars/var_leak.right b/shell/ash_test/ash-vars/var_leak.right index 45c5458dd..be78112c8 100644 --- a/shell/ash_test/ash-vars/var_leak.right +++ b/shell/ash_test/ash-vars/var_leak.right @@ -1,2 +1,3 @@ should be empty: '' -should be empty: '' +should be not empty: 'val2' +should be not empty: 'val3' diff --git a/shell/ash_test/ash-vars/var_leak.tests b/shell/ash_test/ash-vars/var_leak.tests index 1b1123fb7..032059295 100755 --- a/shell/ash_test/ash-vars/var_leak.tests +++ b/shell/ash_test/ash-vars/var_leak.tests @@ -1,9 +1,18 @@ -# This currently fails with CONFIG_FEATURE_SH_NOFORK=y +# true is a regular builtin, varibale should not leak out of it +# this currently fails with CONFIG_FEATURE_SH_NOFORK=y VAR='' -VAR=qwe true +VAR=val1 true echo "should be empty: '$VAR'" -# This fails (always) +# ash follows the "special builtin leaks variables" rule here: +# exec is a special builtin. (bash does not do it) VAR='' -VAR=qwe exec 2>&1 -echo "should be empty: '$VAR'" +VAR=val2 exec 2>&1 +echo "should be not empty: '$VAR'" + +# ash follows the "function call is a special builtin" rule here +# (bash does not do it) +f() { true; } +VAR='' +VAR=val3 f +echo "should be not empty: '$VAR'" -- cgit v1.2.3-55-g6feb From 238bf187ba5708bc04065b761ffc98c877043fe4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 May 2010 15:49:07 +0200 Subject: ash: fix bug which causes signal6.tests to fail function old new delta trapcmd 271 277 +6 localcmd 277 275 -2 Signed-off-by: Denys Vlasenko --- networking/route.c | 2 +- shell/ash.c | 22 +++++++++++++++------- shell/ash_test/ash-signals/signal6.tests | 1 - 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/networking/route.c b/networking/route.c index 241be8e09..a3199621a 100644 --- a/networking/route.c +++ b/networking/route.c @@ -178,7 +178,7 @@ static NOINLINE void INET_setroute(int action, char **args) int prefix_len; prefix_len = xatoul_range(prefix+1, 0, 32); - mask_in_addr(rt) = htonl( ~ (0xffffffffUL >> prefix_len)); + mask_in_addr(rt) = htonl( ~(0xffffffffUL >> prefix_len)); *prefix = '\0'; #if HAVE_NEW_ADDRT rt.rt_genmask.sa_family = AF_INET; diff --git a/shell/ash.c b/shell/ash.c index 641a14035..4f2fa756b 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -208,6 +208,7 @@ struct globals_misc { /* indicates specified signal received */ uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */ + uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */ char *trap[NSIG]; char **trap_ptr; /* used only by "trap hack" */ @@ -236,6 +237,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc; #define optlist (G_misc.optlist ) #define sigmode (G_misc.sigmode ) #define gotsig (G_misc.gotsig ) +#define may_have_traps (G_misc.may_have_traps ) #define trap (G_misc.trap ) #define trap_ptr (G_misc.trap_ptr ) #define random_gen (G_misc.random_gen ) @@ -333,7 +335,7 @@ raise_interrupt(void) /* Signal is not automatically unmasked after it is raised, * do it ourself - unmask all signals */ sigprocmask_allsigs(SIG_UNBLOCK); - /* pending_sig = 0; - now done in onsig() */ + /* pending_sig = 0; - now done in signal_handler() */ ex_type = EXSIG; if (gotsig[SIGINT - 1] && !trap[SIGINT]) { @@ -3268,10 +3270,10 @@ ignoresig(int signo) } /* - * Signal handler. Only one usage site - in setsignal() + * Only one usage site - in setsignal() */ static void -onsig(int signo) +signal_handler(int signo) { gotsig[signo - 1] = 1; @@ -3366,7 +3368,7 @@ setsignal(int signo) act.sa_handler = SIG_DFL; switch (new_act) { case S_CATCH: - act.sa_handler = onsig; + act.sa_handler = signal_handler; act.sa_flags = 0; /* matters only if !DFL and !IGN */ sigfillset(&act.sa_mask); /* ditto */ break; @@ -8443,15 +8445,16 @@ evalsubshell(union node *n, int flags) int status; expredir(n->nredir.redirect); - if (!backgnd && flags & EV_EXIT && !trap[0]) + if (!backgnd && (flags & EV_EXIT) && !may_have_traps) goto nofork; INT_OFF; jp = makejob(/*n,*/ 1); if (forkshell(jp, n, backgnd) == 0) { + /* child */ INT_ON; flags |= EV_EXIT; if (backgnd) - flags &=~ EV_TESTED; + flags &= ~EV_TESTED; nofork: redirect(n->nredir.redirect, 0); evaltreenr(n->nredir.n, flags); @@ -9193,16 +9196,19 @@ evalcommand(union node *cmd, int flags) } #endif /* Fork off a child process if necessary. */ - if (!(flags & EV_EXIT) || trap[0]) { + if (!(flags & EV_EXIT) || may_have_traps) { INT_OFF; jp = makejob(/*cmd,*/ 1); if (forkshell(jp, cmd, FORK_FG) != 0) { + /* parent */ exitstatus = waitforjob(jp); INT_ON; TRACE(("forked child exited with %d\n", exitstatus)); break; } + /* child */ FORCE_INT_ON; + /* fall through to exec'ing exeternal program */ } listsetvar(varlist.list, VEXPORT|VSTACK); shellexec(argv, path, cmdentry.u.index); @@ -12349,6 +12355,8 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) action = ckstrdup(action); } free(trap[signo]); + if (action) + may_have_traps = 1; trap[signo] = action; if (signo != 0) setsignal(signo); diff --git a/shell/ash_test/ash-signals/signal6.tests b/shell/ash_test/ash-signals/signal6.tests index ffeded2a5..3ce151060 100755 --- a/shell/ash_test/ash-signals/signal6.tests +++ b/shell/ash_test/ash-signals/signal6.tests @@ -1,3 +1,2 @@ -# Bug: TERM does not trigger in the child { trap "echo got TERM" TERM; sleep 3; }& sleep 1; kill $!; wait echo Done: $? -- cgit v1.2.3-55-g6feb From c7f95d23f6bc7e17a3b79decf83eb362b389e53a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 May 2010 15:52:23 +0200 Subject: typo fix Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 4f2fa756b..d082333ba 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9208,7 +9208,7 @@ evalcommand(union node *cmd, int flags) } /* child */ FORCE_INT_ON; - /* fall through to exec'ing exeternal program */ + /* fall through to exec'ing external program */ } listsetvar(varlist.list, VEXPORT|VSTACK); shellexec(argv, path, cmdentry.u.index); -- cgit v1.2.3-55-g6feb