aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archival/dpkg.c2
-rw-r--r--archival/libarchive/lzo1x_9x.c2
-rw-r--r--archival/lzop.c1
-rw-r--r--coreutils/factor.c2
-rw-r--r--editors/sed.c5
-rw-r--r--editors/vi.c252
-rw-r--r--include/libbb.h11
-rw-r--r--klibc-utils/resume.c4
-rw-r--r--libbb/appletlib.c5
-rw-r--r--libbb/isqrt.c58
-rw-r--r--libbb/xfuncs_printf.c16
-rw-r--r--loginutils/add-remove-shell.c1
-rw-r--r--loginutils/adduser.c2
-rw-r--r--loginutils/getty.c2
-rw-r--r--miscutils/devfsd.c1
-rw-r--r--miscutils/less.c14
-rw-r--r--miscutils/man.c44
-rw-r--r--modutils/modprobe-small.c10
-rw-r--r--networking/ftpd.c13
-rw-r--r--networking/ifupdown.c5
-rw-r--r--networking/netstat.c7
-rw-r--r--networking/ntpd.c2
-rw-r--r--networking/tls.h18
-rw-r--r--networking/tls_pstm_montgomery_reduce.c4
-rw-r--r--procps/watch.c26
-rw-r--r--shell/ash.c2
-rw-r--r--shell/hush.c5
-rw-r--r--util-linux/acpid.c2
-rw-r--r--util-linux/dmesg.c1
-rw-r--r--util-linux/lsblk.c11
-rw-r--r--util-linux/lspci.c1
-rw-r--r--util-linux/mount.c25
-rw-r--r--util-linux/volume_id/get_devname.c2
-rw-r--r--util-linux/volume_id/unused_lvm.c1
34 files changed, 319 insertions, 238 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c
index a6a8333a8..a53da8df1 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -1694,7 +1694,7 @@ static void unpack_package(deb_file_t *deb_file)
1694 accept_list = NULL; 1694 accept_list = NULL;
1695 i = 0; 1695 i = 0;
1696 while (i < ARRAY_SIZE(all_control_files)) { 1696 while (i < ARRAY_SIZE(all_control_files)) {
1697 char *c = xasprintf("./%s", all_control_files[i]); 1697 char *c = concat_path_file(".", all_control_files[i]);
1698 llist_add_to(&accept_list, c); 1698 llist_add_to(&accept_list, c);
1699 i++; 1699 i++;
1700 } 1700 }
diff --git a/archival/libarchive/lzo1x_9x.c b/archival/libarchive/lzo1x_9x.c
index df26b375f..2c405b636 100644
--- a/archival/libarchive/lzo1x_9x.c
+++ b/archival/libarchive/lzo1x_9x.c
@@ -797,7 +797,6 @@ static int lzo1x_999_compress_internal(const uint8_t *in, unsigned in_len,
797 if (swd->use_best_off) 797 if (swd->use_best_off)
798 better_match(swd, &m_len, &m_off); 798 better_match(swd, &m_len, &m_off);
799#endif 799#endif
800
801 /* shall we try a lazy match ? */ 800 /* shall we try a lazy match ? */
802 ahead = 0; 801 ahead = 0;
803 if (m_len >= max_lazy) { 802 if (m_len >= max_lazy) {
@@ -811,7 +810,6 @@ static int lzo1x_999_compress_internal(const uint8_t *in, unsigned in_len,
811 max_ahead = LZO_MIN(2, (unsigned)l1 - 1); 810 max_ahead = LZO_MIN(2, (unsigned)l1 - 1);
812 } 811 }
813 812
814
815 while (ahead < max_ahead && c->look > m_len) { 813 while (ahead < max_ahead && c->look > m_len) {
816 int lazy_match_min_gain; 814 int lazy_match_min_gain;
817 815
diff --git a/archival/lzop.c b/archival/lzop.c
index bdcc6d548..98587e8dd 100644
--- a/archival/lzop.c
+++ b/archival/lzop.c
@@ -208,7 +208,6 @@ static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
208 lit = 0; 208 lit = 0;
209 goto match_done; 209 goto match_done;
210 210
211
212 /* handle matches */ 211 /* handle matches */
213 do { 212 do {
214 if (t < 16) { /* a M1 match */ 213 if (t < 16) { /* a M1 match */
diff --git a/coreutils/factor.c b/coreutils/factor.c
index 9de5ea8eb..1889836b0 100644
--- a/coreutils/factor.c
+++ b/coreutils/factor.c
@@ -136,7 +136,7 @@ static void factorize(wide_t N);
136 136
137static half_t isqrt_odd(wide_t N) 137static half_t isqrt_odd(wide_t N)
138{ 138{
139 half_t s = isqrt(N); 139 half_t s = isqrt_ull(N);
140 /* s^2 is <= N, (s+1)^2 > N */ 140 /* s^2 is <= N, (s+1)^2 > N */
141 141
142 /* If s^2 in fact is EQUAL to N, it's very lucky. 142 /* If s^2 in fact is EQUAL to N, it's very lucky.
diff --git a/editors/sed.c b/editors/sed.c
index 204417108..b9e2c40ad 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -668,9 +668,8 @@ static void add_cmd(const char *cmdstr)
668 668
669 /* Append this line to any unfinished line from last time. */ 669 /* Append this line to any unfinished line from last time. */
670 if (G.add_cmd_line) { 670 if (G.add_cmd_line) {
671 char *tp = xasprintf("%s\n%s", G.add_cmd_line, cmdstr); 671 cmdstr = xasprintf_inplace(G.add_cmd_line,
672 free(G.add_cmd_line); 672 "%s\n%s", G.add_cmd_line, cmdstr);
673 cmdstr = G.add_cmd_line = tp;
674 } 673 }
675 674
676 /* If this line ends with unescaped backslash, request next line. */ 675 /* If this line ends with unescaped backslash, request next line. */
diff --git a/editors/vi.c b/editors/vi.c
index 7ec3427f9..e3ad120f6 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -612,7 +612,6 @@ static int crashme = 0;
612#endif 612#endif
613 613
614static void show_status_line(void); // put a message on the bottom line 614static void show_status_line(void); // put a message on the bottom line
615static void status_line_bold(const char *, ...);
616 615
617static void show_help(void) 616static void show_help(void)
618{ 617{
@@ -1172,11 +1171,15 @@ static void redraw(int full_screen)
1172//----- Flash the screen -------------------------------------- 1171//----- Flash the screen --------------------------------------
1173static void flash(int h) 1172static void flash(int h)
1174{ 1173{
1175 standout_start(); 1174 //standout_start();
1176 redraw(TRUE); 1175 //redraw(TRUE);
1176 write1(ESC"[?5h"); // "reverse screen on"
1177
1177 mysleep(h); 1178 mysleep(h);
1178 standout_end(); 1179
1179 redraw(TRUE); 1180 //standout_end();
1181 //redraw(TRUE);
1182 write1(ESC"[?5l"); // "reverse screen off"
1180} 1183}
1181 1184
1182static void indicate_error(void) 1185static void indicate_error(void)
@@ -1411,11 +1414,10 @@ static void show_status_line(void)
1411 go_bottom_and_clear_to_eol(); 1414 go_bottom_and_clear_to_eol();
1412 write1(status_buffer); 1415 write1(status_buffer);
1413 if (have_status_msg) { 1416 if (have_status_msg) {
1414 if (((int)strlen(status_buffer) - (have_status_msg - 1)) > 1417 int n = (int)strlen(status_buffer) - (have_status_msg - 1);
1415 (columns - 1) ) { 1418 // careful with int->unsigned promotion in comparison!
1416 have_status_msg = 0; 1419 if (n >= 0 && n >= columns)
1417 Hit_Return(); 1420 Hit_Return();
1418 }
1419 have_status_msg = 0; 1421 have_status_msg = 0;
1420 } 1422 }
1421 place_cursor(crow, ccol); // put cursor back in correct place 1423 place_cursor(crow, ccol); // put cursor back in correct place
@@ -2725,7 +2727,7 @@ static char *get_one_address(char *p, int *result, int *valid)
2725 2727
2726// Read line addresses for a colon command. The user can enter as 2728// Read line addresses for a colon command. The user can enter as
2727// many as they like but only the last two will be used. 2729// many as they like but only the last two will be used.
2728static char *get_address(char *p, int *b, int *e, unsigned int *got) 2730static char *get_address(char *p, int *b, int *e, unsigned *got)
2729{ 2731{
2730 int state = GET_ADDRESS; 2732 int state = GET_ADDRESS;
2731 int valid; 2733 int valid;
@@ -2839,19 +2841,23 @@ static void setops(char *args, int flg_no)
2839# if ENABLE_FEATURE_VI_COLON_EXPAND 2841# if ENABLE_FEATURE_VI_COLON_EXPAND
2840static char *expand_args(char *args) 2842static char *expand_args(char *args)
2841{ 2843{
2842 char *s, *t; 2844 char *s;
2843 const char *replace; 2845 const char *replace;
2844 2846
2845 args = xstrdup(args); 2847 args = xstrdup(args);
2846 for (s = args; *s; s++) { 2848 for (s = args; *s; s++) {
2849 unsigned n;
2850
2847 if (*s == '%') { 2851 if (*s == '%') {
2848 replace = current_filename; 2852 replace = current_filename;
2849 } else if (*s == '#') { 2853 } else if (*s == '#') {
2850 replace = alt_filename; 2854 replace = alt_filename;
2851 } else { 2855 } else {
2852 if (*s == '\\' && s[1] != '\0') { 2856 if (*s == '\\' && s[1] != '\0') {
2853 for (t = s++; *t; t++) 2857 char *t;
2858 for (t = s; *t; t++)
2854 *t = t[1]; 2859 *t = t[1];
2860 s++;
2855 } 2861 }
2856 continue; 2862 continue;
2857 } 2863 }
@@ -2862,11 +2868,9 @@ static char *expand_args(char *args)
2862 return NULL; 2868 return NULL;
2863 } 2869 }
2864 2870
2865 *s = '\0'; 2871 n = (s - args);
2866 t = xasprintf("%s%s%s", args, replace, s+1); 2872 xasprintf_inplace(args, "%.*s%s%s", n, args, replace, s+1);
2867 s = t + (s - args) + strlen(replace); 2873 s = args + n + strlen(replace);
2868 free(args);
2869 args = t;
2870 } 2874 }
2871 return args; 2875 return args;
2872} 2876}
@@ -2944,7 +2948,6 @@ static char *regex_search(char *q, regex_t *preg, const char *Rorig,
2944# define strchr_backslash(s, c) strchr(s, c) 2948# define strchr_backslash(s, c) strchr(s, c)
2945#endif /* ENABLE_FEATURE_VI_REGEX_SEARCH */ 2949#endif /* ENABLE_FEATURE_VI_REGEX_SEARCH */
2946 2950
2947// buf must be no longer than MAX_INPUT_LEN!
2948static void colon(char *buf) 2951static void colon(char *buf)
2949{ 2952{
2950#if !ENABLE_FEATURE_VI_COLON 2953#if !ENABLE_FEATURE_VI_COLON
@@ -3004,16 +3007,17 @@ static void colon(char *buf)
3004 } 3007 }
3005 not_implemented(p); 3008 not_implemented(p);
3006#else 3009#else
3007 3010 char cmd[sizeof("features!")]; // longest known command + NUL
3011 char *args;
3012 int cmdlen;
3013 char *useforce;
3014 char *q, *r;
3015 int b, e;
3008// check how many addresses we got 3016// check how many addresses we got
3009# define GOT_ADDRESS (got & 1) 3017# define GOT_ADDRESS (got & 1)
3010# define GOT_RANGE ((got & 3) == 3) 3018# define GOT_RANGE ((got & 3) == 3)
3011 3019 unsigned got;
3012 char c, *buf1, *q, *r; 3020 char *exp = NULL; // may hold expand_args() result: if VI_COLON_EXPAND, needs freeing!
3013 char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args, *exp = NULL;
3014 int i, l, li, b, e;
3015 unsigned int got;
3016 int useforce;
3017 3021
3018 // :3154 // if (-e line 3154) goto it else stay put 3022 // :3154 // if (-e line 3154) goto it else stay put
3019 // :4,33w! foo // write a portion of buffer to file "foo" 3023 // :4,33w! foo // write a portion of buffer to file "foo"
@@ -3028,52 +3032,38 @@ static void colon(char *buf)
3028 // :/xyz/ // goto the "xyz" line 3032 // :/xyz/ // goto the "xyz" line
3029 // :s/find/replace/ // substitute pattern "find" with "replace" 3033 // :s/find/replace/ // substitute pattern "find" with "replace"
3030 // :!<cmd> // run <cmd> then return 3034 // :!<cmd> // run <cmd> then return
3031 //
3032 3035
3033 while (*buf == ':') 3036 while (*buf == ':')
3034 buf++; // move past leading colons 3037 buf++; // move past leading colons
3035 while (isblank(*buf)) 3038 buf = skip_whitespace(buf); // move past leading blanks
3036 buf++; // move past leading blanks 3039 if (!*buf || *buf == '"')
3037 if (!buf[0] || buf[0] == '"')
3038 goto ret; // ignore empty lines or those starting with '"' 3040 goto ret; // ignore empty lines or those starting with '"'
3039 3041
3040 li = i = 0; 3042 // look for optional address(es) ":." ":1" ":1,9" ":'q,'a" ":%"
3041 b = e = -1; 3043 b = e = -1;
3042 got = 0; 3044 got = 0;
3043 li = count_lines(text, end - 1);
3044 fn = current_filename;
3045
3046 // look for optional address(es) :. :1 :1,9 :'q,'a :%
3047 buf = get_address(buf, &b, &e, &got); 3045 buf = get_address(buf, &b, &e, &got);
3048 if (buf == NULL) { 3046 if (buf == NULL)
3049 goto ret; 3047 goto ret;
3050 }
3051 3048
3052 // get the COMMAND into cmd[] 3049 // get the COMMAND into cmd[]
3053 strcpy(cmd, buf); 3050 safe_strncpy(cmd, buf, sizeof(cmd));
3054 buf1 = cmd; 3051 skip_non_whitespace(cmd)[0] = '\0';
3055 while (!isspace(*buf1) && *buf1 != '\0') { 3052 useforce = last_char_is(cmd, '!');
3056 buf1++; 3053 if (useforce && useforce > cmd)
3057 } 3054 *useforce = '\0'; // "CMD!" -> "CMD" (unless single "!")
3058 cmdend = buf1; 3055 // find ARGuments
3059 // get any ARGuments 3056 args = skip_whitespace(skip_non_whitespace(buf));
3060 while (isblank(*buf1)) 3057
3061 buf1++;
3062 args = buf1;
3063 *cmdend = '\0';
3064 useforce = FALSE;
3065 if (cmdend > cmd && cmdend[-1] == '!') {
3066 useforce = TRUE;
3067 cmdend[-1] = '\0'; // get rid of !
3068 }
3069 // assume the command will want a range, certain commands 3058 // assume the command will want a range, certain commands
3070 // (read, substitute) need to adjust these assumptions 3059 // (read, substitute) need to adjust these assumptions
3071 if (!GOT_ADDRESS) { 3060 q = text; // if no addr, use 1,$ for the range
3072 q = text; // no addr, use 1,$ for the range 3061 r = end - 1;
3073 r = end - 1; 3062 if (GOT_ADDRESS) { // at least one addr was given, get its details
3074 } else { 3063 int lines;
3075 // at least one addr was given, get its details 3064 if (e < 0
3076 if (e < 0 || e > li) { 3065 || e > (lines = count_lines(text, end - 1))
3066 ) {
3077 status_line_bold("Invalid range"); 3067 status_line_bold("Invalid range");
3078 goto ret; 3068 goto ret;
3079 } 3069 }
@@ -3083,31 +3073,28 @@ static void colon(char *buf)
3083 // number of the single line the user wants. 3073 // number of the single line the user wants.
3084 // Reset the end pointer to the end of that line. 3074 // Reset the end pointer to the end of that line.
3085 r = end_line(q); 3075 r = end_line(q);
3086 li = 1;
3087 } else { 3076 } else {
3088 // we were given two addrs. change the 3077 // we were given two addrs. change the
3089 // start pointer to the addr given by user. 3078 // start pointer to the addr given by user.
3090 if (b < 0 || b > li || b > e) { 3079 if (b < 0 || b > lines || b > e) {
3091 status_line_bold("Invalid range"); 3080 status_line_bold("Invalid range");
3092 goto ret; 3081 goto ret;
3093 } 3082 }
3094 q = find_line(b); // what line is #b 3083 q = find_line(b); // what line is #b
3095 r = end_line(r); 3084 r = end_line(r);
3096 li = e - b + 1;
3097 } 3085 }
3098 } 3086 }
3099 // ------------ now look for the command ------------ 3087 // ------------ now look for the command ------------
3100 i = strlen(cmd); 3088 cmdlen = strlen(cmd);
3101 if (i == 0) { // :123CR goto line #123 3089 if (cmdlen == 0) { // ":123<enter>" - goto line #123
3102 if (e >= 0) { 3090 if (e >= 0) {
3103 dot = find_line(e); // what line is #e 3091 dot = find_line(e); // what line is #e
3104 dot_skip_over_ws(); 3092 dot_skip_over_ws();
3105 } 3093 }
3106 } 3094 }
3107# if ENABLE_FEATURE_ALLOW_EXEC 3095# if ENABLE_FEATURE_ALLOW_EXEC
3108 else if (cmd[0] == '!') { // run a cmd 3096 else if (cmd[0] == '!') { // ":!CMD" - run shell CMD
3109 int retcode; 3097 int retcode;
3110 // :!ls run the <cmd>
3111 if (GOT_ADDRESS) { 3098 if (GOT_ADDRESS) {
3112 status_line_bold("Range not allowed"); 3099 status_line_bold("Range not allowed");
3113 goto ret; 3100 goto ret;
@@ -3129,25 +3116,27 @@ static void colon(char *buf)
3129 e = count_lines(text, dot); 3116 e = count_lines(text, dot);
3130 } 3117 }
3131 status_line("%d", e); 3118 status_line("%d", e);
3132 } else if (strncmp(cmd, "delete", i) == 0) { // delete lines 3119 } else if (strncmp(cmd, "delete", cmdlen) == 0) { // delete lines
3133 if (!GOT_ADDRESS) { // no addr given- use defaults 3120 if (!GOT_ADDRESS) { // no addr given- use defaults
3134 q = begin_line(dot); // assume .,. for the range 3121 q = begin_line(dot); // assume .,. for the range
3135 r = end_line(dot); 3122 r = end_line(dot);
3136 } 3123 }
3137 dot = yank_delete(q, r, WHOLE, YANKDEL, ALLOW_UNDO); // save, then delete lines 3124 dot = yank_delete(q, r, WHOLE, YANKDEL, ALLOW_UNDO); // save, then delete lines
3138 dot_skip_over_ws(); 3125 dot_skip_over_ws();
3139 } else if (strncmp(cmd, "edit", i) == 0) { // Edit a file 3126 } else if (strncmp(cmd, "edit", cmdlen) == 0) { // Edit a file
3140 int size; 3127 int size;
3128 char *fn;
3141 3129
3142 // don't edit, if the current file has been modified 3130 // don't edit, if the current file has been modified
3143 if (modified_count && !useforce) { 3131 if (modified_count && !useforce) {
3144 status_line_bold("No write since last change (:%s! overrides)", cmd); 3132 status_line_bold("No write since last change (:%s! overrides)", cmd);
3145 goto ret; 3133 goto ret;
3146 } 3134 }
3135 fn = current_filename;
3147 if (args[0]) { 3136 if (args[0]) {
3148 // the user supplied a file name 3137 // the user supplied a file name
3149 fn = exp = expand_args(args); 3138 fn = expand_args(args);
3150 if (exp == NULL) 3139 if (fn == NULL)
3151 goto ret; 3140 goto ret;
3152 } else if (current_filename == NULL) { 3141 } else if (current_filename == NULL) {
3153 // no user file name, no current name- punt 3142 // no user file name, no current name- punt
@@ -3167,8 +3156,6 @@ static void colon(char *buf)
3167 reg[YDreg] = NULL; 3156 reg[YDreg] = NULL;
3168 } 3157 }
3169# endif 3158# endif
3170 // how many lines in text[]?
3171 li = count_lines(text, end - 1);
3172 status_line("'%s'%s" 3159 status_line("'%s'%s"
3173 IF_FEATURE_VI_READONLY("%s") 3160 IF_FEATURE_VI_READONLY("%s")
3174 " %uL, %uC", 3161 " %uL, %uC",
@@ -3177,9 +3164,10 @@ static void colon(char *buf)
3177 IF_FEATURE_VI_READONLY( 3164 IF_FEATURE_VI_READONLY(
3178 ((readonly_mode) ? " [Readonly]" : ""), 3165 ((readonly_mode) ? " [Readonly]" : ""),
3179 ) 3166 )
3180 li, (int)(end - text) 3167 count_lines(text, end - 1),
3168 (int)(end - text)
3181 ); 3169 );
3182 } else if (strncmp(cmd, "file", i) == 0) { // what File is this 3170 } else if (strncmp(cmd, "file", cmdlen) == 0) { // what File is this
3183 if (e >= 0) { 3171 if (e >= 0) {
3184 status_line_bold("No address allowed on this command"); 3172 status_line_bold("No address allowed on this command");
3185 goto ret; 3173 goto ret;
@@ -3194,46 +3182,52 @@ static void colon(char *buf)
3194 // user wants file status info 3182 // user wants file status info
3195 last_status_cksum = 0; // force status update 3183 last_status_cksum = 0; // force status update
3196 } 3184 }
3197 } else if (strncmp(cmd, "features", i) == 0) { // what features are available 3185 } else if (strncmp(cmd, "features", cmdlen) == 0) { // what features are available
3198 // print out values of all features 3186 // print out values of all features
3199 go_bottom_and_clear_to_eol(); 3187 go_bottom_and_clear_to_eol();
3200 cookmode(); 3188 cookmode();
3201 show_help(); 3189 show_help();
3202 rawmode(); 3190 rawmode();
3203 Hit_Return(); 3191 Hit_Return();
3204 } else if (strncmp(cmd, "list", i) == 0) { // literal print line 3192 } else if (strncmp(cmd, "list", cmdlen) == 0) { // literal print line
3193 char *dst;
3205 if (!GOT_ADDRESS) { // no addr given- use defaults 3194 if (!GOT_ADDRESS) { // no addr given- use defaults
3206 q = begin_line(dot); // assume .,. for the range 3195 q = begin_line(dot); // assume .,. for the range
3207 r = end_line(dot); 3196 r = end_line(dot);
3208 } 3197 }
3209 go_bottom_and_clear_to_eol(); 3198 have_status_msg = 1;
3210 puts("\r"); 3199 dst = status_buffer;
3211 for (; q <= r; q++) { 3200#define MAXPRINT (sizeof(ESC_BOLD_TEXT "^?" ESC_NORM_TEXT) + 1)
3201 while (q <= r && dst < status_buffer + STATUS_BUFFER_LEN - MAXPRINT) {
3202 char c;
3212 int c_is_no_print; 3203 int c_is_no_print;
3213 3204
3214 c = *q; 3205 c = *q++;
3206 if (c == '\n') {
3207 *dst++ = '$';
3208 break;
3209 }
3215 c_is_no_print = (c & 0x80) && !Isprint(c); 3210 c_is_no_print = (c & 0x80) && !Isprint(c);
3216 if (c_is_no_print) { 3211 if (c_is_no_print) {
3217 c = '.'; 3212//TODO: print fewer ESC if more than one ctrl char
3218 standout_start(); 3213 dst = stpcpy(dst, ESC_BOLD_TEXT);
3214 *dst++ = '.';
3215 dst = stpcpy(dst, ESC_NORM_TEXT);
3216 continue;
3219 } 3217 }
3220 if (c == '\n') { 3218 if (c < ' ' || c == 127) {
3221 write1("$\r"); 3219 *dst++ = '^';
3222 } else if (c < ' ' || c == 127) {
3223 bb_putchar('^');
3224 if (c == 127) 3220 if (c == 127)
3225 c = '?'; 3221 c = '?';
3226 else 3222 else
3227 c += '@'; 3223 c += '@';
3228 } 3224 }
3229 bb_putchar(c); 3225 *dst++ = c;
3230 if (c_is_no_print)
3231 standout_end();
3232 } 3226 }
3233 Hit_Return(); 3227 *dst = '\0';
3234 } else if (strncmp(cmd, "quit", i) == 0 // quit 3228 } else if (strncmp(cmd, "quit", cmdlen) == 0 // quit
3235 || strncmp(cmd, "next", i) == 0 // edit next file 3229 || strncmp(cmd, "next", cmdlen) == 0 // edit next file
3236 || strncmp(cmd, "prev", i) == 0 // edit previous file 3230 || strncmp(cmd, "prev", cmdlen) == 0 // edit previous file
3237 ) { 3231 ) {
3238 int n; 3232 int n;
3239 if (useforce) { 3233 if (useforce) {
@@ -3268,13 +3262,14 @@ static void colon(char *buf)
3268 optind -= 2; 3262 optind -= 2;
3269 } 3263 }
3270 editing = 0; 3264 editing = 0;
3271 } else if (strncmp(cmd, "read", i) == 0) { // read file into text[] 3265 } else if (strncmp(cmd, "read", cmdlen) == 0) { // read file into text[]
3272 int size, num; 3266 int size, num;
3267 char *fn = current_filename;
3273 3268
3274 if (args[0]) { 3269 if (args[0]) {
3275 // the user supplied a file name 3270 // the user supplied a file name
3276 fn = exp = expand_args(args); 3271 fn = expand_args(args);
3277 if (exp == NULL) 3272 if (fn == NULL)
3278 goto ret; 3273 goto ret;
3279 init_filename(fn); 3274 init_filename(fn);
3280 } else if (current_filename == NULL) { 3275 } else if (current_filename == NULL) {
@@ -3300,17 +3295,16 @@ static void colon(char *buf)
3300 } 3295 }
3301 if (size < 0) 3296 if (size < 0)
3302 goto ret; // nothing was inserted 3297 goto ret; // nothing was inserted
3303 // how many lines in text[]?
3304 li = count_lines(q, q + size - 1);
3305 status_line("'%s'" 3298 status_line("'%s'"
3306 IF_FEATURE_VI_READONLY("%s") 3299 IF_FEATURE_VI_READONLY("%s")
3307 " %uL, %uC", 3300 " %uL, %uC",
3308 fn, 3301 fn,
3309 IF_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),) 3302 IF_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),)
3310 li, size 3303 count_lines(q, q + size - 1),
3304 size
3311 ); 3305 );
3312 dot = find_line(num); 3306 dot = find_line(num);
3313 } else if (strncmp(cmd, "rewind", i) == 0) { // rewind cmd line args 3307 } else if (strncmp(cmd, "rewind", cmdlen) == 0) { // rewind cmd line args
3314 if (modified_count && !useforce) { 3308 if (modified_count && !useforce) {
3315 status_line_bold("No write since last change (:%s! overrides)", cmd); 3309 status_line_bold("No write since last change (:%s! overrides)", cmd);
3316 } else { 3310 } else {
@@ -3319,11 +3313,12 @@ static void colon(char *buf)
3319 editing = 0; 3313 editing = 0;
3320 } 3314 }
3321# if ENABLE_FEATURE_VI_SET 3315# if ENABLE_FEATURE_VI_SET
3322 } else if (strncmp(cmd, "set", i) == 0) { // set or clear features 3316 } else if (strncmp(cmd, "set", cmdlen) == 0 // set or clear features
3317 IF_FEATURE_VI_SEARCH(&& cmdlen > 1) // (do not confuse with "s /find/repl/")
3318 ) {
3323# if ENABLE_FEATURE_VI_SETOPTS 3319# if ENABLE_FEATURE_VI_SETOPTS
3324 char *argp, *argn, oldch; 3320 char *argp, *argn, oldch;
3325# endif 3321# endif
3326 // only blank is regarded as args delimiter. What about tab '\t'?
3327 if (!args[0] || strcmp(args, "all") == 0) { 3322 if (!args[0] || strcmp(args, "all") == 0) {
3328 // print out values of all options 3323 // print out values of all options
3329# if ENABLE_FEATURE_VI_SETOPTS 3324# if ENABLE_FEATURE_VI_SETOPTS
@@ -3370,7 +3365,7 @@ static void colon(char *buf)
3370# if ENABLE_FEATURE_VI_SETOPTS 3365# if ENABLE_FEATURE_VI_SETOPTS
3371 argp = args; 3366 argp = args;
3372 while (*argp) { 3367 while (*argp) {
3373 i = 0; 3368 int i = 0;
3374 if (argp[0] == 'n' && argp[1] == 'o') // "noXXX" 3369 if (argp[0] == 'n' && argp[1] == 'o') // "noXXX"
3375 i = 2; 3370 i = 2;
3376 argn = skip_non_whitespace(argp); 3371 argn = skip_non_whitespace(argp);
@@ -3385,8 +3380,10 @@ static void colon(char *buf)
3385 3380
3386# if ENABLE_FEATURE_VI_SEARCH 3381# if ENABLE_FEATURE_VI_SEARCH
3387 } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern 3382 } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern
3383 char c;
3388 char *F, *R, *flags; 3384 char *F, *R, *flags;
3389 size_t len_F, len_R; 3385 size_t len_F, len_R;
3386 int i;
3390 int gflag = 0; // global replace flag 3387 int gflag = 0; // global replace flag
3391 int subs = 0; // number of substitutions 3388 int subs = 0; // number of substitutions
3392# if ENABLE_FEATURE_VI_VERBOSE_STATUS 3389# if ENABLE_FEATURE_VI_VERBOSE_STATUS
@@ -3400,12 +3397,12 @@ static void colon(char *buf)
3400 int undo = 0; 3397 int undo = 0;
3401# endif 3398# endif
3402# endif 3399# endif
3403 3400 buf = skip_whitespace(buf + 1); // spaces allowed: "s /find/repl/"
3404 // F points to the "find" pattern 3401 // F points to the "find" pattern
3405 // R points to the "replace" pattern 3402 // R points to the "replace" pattern
3406 // replace the cmd line delimiters "/" with NULs 3403 // replace the cmd line delimiters "/" with NULs
3407 c = buf[1]; // what is the delimiter 3404 c = buf[0]; // what is the delimiter
3408 F = buf + 2; // start of "find" 3405 F = buf + 1; // start of "find"
3409 R = strchr_backslash(F, c); // middle delimiter 3406 R = strchr_backslash(F, c); // middle delimiter
3410 if (!R) 3407 if (!R)
3411 goto colon_s_fail; 3408 goto colon_s_fail;
@@ -3450,7 +3447,6 @@ static void colon(char *buf)
3450# else 3447# else
3451 len_R = strlen(R); 3448 len_R = strlen(R);
3452# endif 3449# endif
3453
3454 for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0 3450 for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0
3455 char *ls = q; // orig line start 3451 char *ls = q; // orig line start
3456 char *found; 3452 char *found;
@@ -3522,15 +3518,16 @@ static void colon(char *buf)
3522 regfree(&preg); 3518 regfree(&preg);
3523# endif 3519# endif
3524# endif /* FEATURE_VI_SEARCH */ 3520# endif /* FEATURE_VI_SEARCH */
3525 } else if (strncmp(cmd, "version", i) == 0) { // show software version 3521 } else if (strncmp(cmd, "version", cmdlen) == 0) { // show software version
3526 status_line(BB_VER); 3522 status_line(BB_VER);
3527 } else if (strncmp(cmd, "write", i) == 0 // write text to file 3523 } else if (strncmp(cmd, "write", cmdlen) == 0 // write text to file
3528 || strcmp(cmd, "wq") == 0 3524 || strcmp(cmd, "wq") == 0
3529 || strcmp(cmd, "wn") == 0 3525 || strcmp(cmd, "wn") == 0
3530 || (cmd[0] == 'x' && !cmd[1]) 3526 || (cmd[0] == 'x' && !cmd[1])
3531 ) { 3527 ) {
3532 int size; 3528 int size, l;
3533 //int forced = FALSE; 3529 //int forced = FALSE;
3530 char *fn = current_filename;
3534 3531
3535 // is there a file name to write to? 3532 // is there a file name to write to?
3536 if (args[0]) { 3533 if (args[0]) {
@@ -3539,8 +3536,10 @@ static void colon(char *buf)
3539 exp = expand_args(args); 3536 exp = expand_args(args);
3540 if (exp == NULL) 3537 if (exp == NULL)
3541 goto ret; 3538 goto ret;
3542 if (!useforce && (fn == NULL || strcmp(fn, exp) != 0) && 3539 if (!useforce
3543 stat(exp, &statbuf) == 0) { 3540 && (fn == NULL || strcmp(fn, exp) != 0)
3541 && stat(exp, &statbuf) == 0
3542 ) {
3544 status_line_bold("File exists (:w! overrides)"); 3543 status_line_bold("File exists (:w! overrides)");
3545 goto ret; 3544 goto ret;
3546 } 3545 }
@@ -3559,12 +3558,10 @@ static void colon(char *buf)
3559 // system(syscmd); 3558 // system(syscmd);
3560 // forced = TRUE; 3559 // forced = TRUE;
3561 //} 3560 //}
3561 size = l = 0;
3562 if (modified_count != 0 || cmd[0] != 'x') { 3562 if (modified_count != 0 || cmd[0] != 'x') {
3563 size = r - q + 1; 3563 size = r - q + 1;
3564 l = file_write(fn, q, r); 3564 l = file_write(fn, q, r);
3565 } else {
3566 size = 0;
3567 l = 0;
3568 } 3565 }
3569 //if (useforce && forced) { 3566 //if (useforce && forced) {
3570 // chmod u-w 3567 // chmod u-w
@@ -3577,8 +3574,8 @@ static void colon(char *buf)
3577 status_line_bold_errno(fn); 3574 status_line_bold_errno(fn);
3578 } else { 3575 } else {
3579 // how many lines written 3576 // how many lines written
3580 li = count_lines(q, q + l - 1); 3577 int lines = count_lines(q, q + l - 1);
3581 status_line("'%s' %uL, %uC", fn, li, l); 3578 status_line("'%s' %uL, %uC", fn, lines, l);
3582 if (l == size) { 3579 if (l == size) {
3583 if (q == text && q + l == end) { 3580 if (q == text && q + l == end) {
3584 modified_count = 0; 3581 modified_count = 0;
@@ -3590,37 +3587,35 @@ static void colon(char *buf)
3590 // are there other files to edit? 3587 // are there other files to edit?
3591 int n = cmdline_filecnt - optind - 1; 3588 int n = cmdline_filecnt - optind - 1;
3592 if (n > 0) { 3589 if (n > 0) {
3593 if (useforce) { 3590 if (!useforce) {
3594 // force end of argv list
3595 optind = cmdline_filecnt;
3596 } else {
3597 status_line_bold("%u more file(s) to edit", n); 3591 status_line_bold("%u more file(s) to edit", n);
3598 goto ret; 3592 goto ret;
3599 } 3593 }
3594 // force end of argv list
3595 optind = cmdline_filecnt;
3600 } 3596 }
3601 editing = 0; 3597 editing = 0;
3602 } 3598 }
3603 } 3599 }
3604 } 3600 }
3605# if ENABLE_FEATURE_VI_YANKMARK 3601# if ENABLE_FEATURE_VI_YANKMARK
3606 } else if (strncmp(cmd, "yank", i) == 0) { // yank lines 3602 } else if (strncmp(cmd, "yank", cmdlen) == 0) { // yank lines
3603 int lines;
3607 if (!GOT_ADDRESS) { // no addr given- use defaults 3604 if (!GOT_ADDRESS) { // no addr given- use defaults
3608 q = begin_line(dot); // assume .,. for the range 3605 q = begin_line(dot); // assume .,. for the range
3609 r = end_line(dot); 3606 r = end_line(dot);
3610 } 3607 }
3611 text_yank(q, r, YDreg, WHOLE); 3608 text_yank(q, r, YDreg, WHOLE);
3612 li = count_lines(q, r); 3609 lines = count_lines(q, r);
3613 status_line("Yank %d lines (%d chars) into [%c]", 3610 status_line("Yank %d lines (%d chars) into [%c]",
3614 li, strlen(reg[YDreg]), what_reg()); 3611 lines, strlen(reg[YDreg]), what_reg());
3615# endif 3612# endif
3616 } else { 3613 } else {
3617 // cmd unknown 3614 // cmd unknown
3618 not_implemented(cmd); 3615 not_implemented(cmd);
3619 } 3616 }
3620 ret: 3617 ret:
3621# if ENABLE_FEATURE_VI_COLON_EXPAND 3618 IF_FEATURE_VI_COLON_EXPAND(free(exp);)
3622 free(exp);
3623# endif
3624 dot = bound_dot(dot); // make sure "dot" is valid 3619 dot = bound_dot(dot); // make sure "dot" is valid
3625 return; 3620 return;
3626# if ENABLE_FEATURE_VI_SEARCH 3621# if ENABLE_FEATURE_VI_SEARCH
@@ -4977,8 +4972,7 @@ static void run_cmds(char *p)
4977 if (p) 4972 if (p)
4978 while (*p == '\n') 4973 while (*p == '\n')
4979 *p++ = '\0'; 4974 *p++ = '\0';
4980 if (strlen(q) < MAX_INPUT_LEN) 4975 colon(q);
4981 colon(q);
4982 } 4976 }
4983} 4977}
4984#endif 4978#endif
diff --git a/include/libbb.h b/include/libbb.h
index 6c4fe17c9..6ce99abda 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -457,7 +457,12 @@ unsigned FAST_FUNC bb_popcnt_long(unsigned long m);
457#define bb_popcnt_long(m) bb_popcnt_32(m) 457#define bb_popcnt_long(m) bb_popcnt_32(m)
458#endif 458#endif
459 459
460unsigned long FAST_FUNC isqrt(unsigned long long N); 460unsigned FAST_FUNC isqrt(unsigned long N);
461#if LLONG_MAX > LONG_MAX
462unsigned long FAST_FUNC isqrt_ull(unsigned long long N);
463#else
464# define isqrt_ull(N) isqrt(N)
465#endif
461 466
462unsigned long long monotonic_ns(void) FAST_FUNC; 467unsigned long long monotonic_ns(void) FAST_FUNC;
463unsigned long long monotonic_us(void) FAST_FUNC; 468unsigned long long monotonic_us(void) FAST_FUNC;
@@ -1042,6 +1047,8 @@ int parse_pasv_epsv(char *buf) FAST_FUNC;
1042/* 0 if argv[0] is NULL: */ 1047/* 0 if argv[0] is NULL: */
1043unsigned string_array_len(char **argv) FAST_FUNC; 1048unsigned string_array_len(char **argv) FAST_FUNC;
1044void overlapping_strcpy(char *dst, const char *src) FAST_FUNC; 1049void overlapping_strcpy(char *dst, const char *src) FAST_FUNC;
1050/* Like strncpy but make sure the resulting string is always 0 terminated: */
1051/* writes SIZE chars, the [SIZE-1] char is always NUL (unless SIZE==0). */
1045char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC; 1052char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC;
1046char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC; 1053char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC;
1047unsigned count_strstr(const char *str, const char *sub) FAST_FUNC; 1054unsigned count_strstr(const char *str, const char *sub) FAST_FUNC;
@@ -1053,6 +1060,8 @@ int bb_putchar(int ch) FAST_FUNC;
1053int bb_putchar_stderr(char ch) FAST_FUNC; 1060int bb_putchar_stderr(char ch) FAST_FUNC;
1054int fputs_stdout(const char *s) FAST_FUNC; 1061int fputs_stdout(const char *s) FAST_FUNC;
1055char *xasprintf(const char *format, ...) __attribute__ ((format(printf, 1, 2))) RETURNS_MALLOC; 1062char *xasprintf(const char *format, ...) __attribute__ ((format(printf, 1, 2))) RETURNS_MALLOC;
1063char *xasprintf_and_free(char *allocated, const char *format, ...) __attribute__ ((format(printf, 2, 3))) RETURNS_MALLOC;
1064#define xasprintf_inplace(allocated, ...) ((allocated) = xasprintf_and_free((allocated), __VA_ARGS__))
1056char *auto_string(char *str) FAST_FUNC; 1065char *auto_string(char *str) FAST_FUNC;
1057// gcc-4.1.1 still isn't good enough at optimizing it 1066// gcc-4.1.1 still isn't good enough at optimizing it
1058// (+200 bytes compared to macro) 1067// (+200 bytes compared to macro)
diff --git a/klibc-utils/resume.c b/klibc-utils/resume.c
index 7b9d18b5d..179413627 100644
--- a/klibc-utils/resume.c
+++ b/klibc-utils/resume.c
@@ -39,7 +39,7 @@ static dev_t name_to_dev_t(const char *devname)
39 struct stat st; 39 struct stat st;
40 int r; 40 int r;
41 41
42 if (strncmp(devname, "/dev/", 5) != 0) { 42 if (!is_prefixed_with(devname, "/dev/")) {
43 char *cptr; 43 char *cptr;
44 44
45 cptr = strchr(devname, ':'); 45 cptr = strchr(devname, ':');
@@ -59,7 +59,7 @@ static dev_t name_to_dev_t(const char *devname)
59 return res; 59 return res;
60 } 60 }
61 61
62 devname = xasprintf("/dev/%s", devname); 62 devname = concat_path_file("/dev", devname);
63 } 63 }
64 /* Now devname is always "/dev/FOO" */ 64 /* Now devname is always "/dev/FOO" */
65 65
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index b2dcf93e0..481cc278e 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -1413,8 +1413,11 @@ int main(int argc UNUSED_PARAM, char **argv)
1413# endif 1413# endif
1414 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); 1414 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
1415# if !ENABLE_BUSYBOX 1415# if !ENABLE_BUSYBOX
1416 if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox")) 1416 if (argv[1] && argv[1][0] != '-' /* do not match "busybox --OPT" */
1417 && is_prefixed_with(bb_basename(argv[0]), "busybox")
1418 ) {
1417 argv++; 1419 argv++;
1420 }
1418# endif 1421# endif
1419 applet_name = argv[0]; 1422 applet_name = argv[0];
1420 if (applet_name[0] == '-') 1423 if (applet_name[0] == '-')
diff --git a/libbb/isqrt.c b/libbb/isqrt.c
index 817b7d036..507c7d637 100644
--- a/libbb/isqrt.c
+++ b/libbb/isqrt.c
@@ -9,15 +9,42 @@
9#ifndef ISQRT_TEST 9#ifndef ISQRT_TEST
10# include "libbb.h" 10# include "libbb.h"
11#else 11#else
12/* gcc -DISQRT_TEST -Wall -O2 isqrt.c -oisqrt && ./isqrt $((RANDOM*RANDOM)) */ 12// gcc -DISQRT_TEST -Wall -Os -ffunction-sections isqrt.c -S -fverbose-asm
13// gcc -DISQRT_TEST -Wall -Os -ffunction-sections isqrt.c -c
14// gcc -DISQRT_TEST -Wall -Os -ffunction-sections isqrt.c -oisqrt && ./isqrt $((RANDOM*RANDOM))
13# include <stdlib.h> 15# include <stdlib.h>
14# include <stdio.h> 16# include <stdio.h>
15# include <time.h> 17# include <time.h>
18# include <limits.h>
16# define FAST_FUNC /* nothing */ 19# define FAST_FUNC /* nothing */
17#endif 20#endif
18 21
19/* Returns such x that x+1 > sqrt(N) */ 22/* Returns such x that x+1 > sqrt(N) */
20unsigned long FAST_FUNC isqrt(unsigned long long N) 23
24/* Stolen from kernel code */
25unsigned FAST_FUNC isqrt(unsigned long x)
26{
27 unsigned long y = 0;
28 unsigned long m = 1UL << (8*sizeof(x) - 2);
29 // ^^^^^ should be m = 1UL << ((fls(x) - 1) & ~1UL);
30 // but calculating fls() would take time and code
31
32 do {
33 unsigned long b = y + m;
34 y >>= 1;
35 if (x >= b) {
36 x -= b;
37 y += m;
38 }
39 m >>= 2;
40 } while (m);
41 return y;
42}
43
44#if LLONG_MAX > LONG_MAX
45# if defined(i386)
46/* Smaller code on this register-starved arch */
47unsigned long FAST_FUNC isqrt_ull(unsigned long long N)
21{ 48{
22 unsigned long x; 49 unsigned long x;
23 unsigned shift; 50 unsigned shift;
@@ -33,15 +60,40 @@ unsigned long FAST_FUNC isqrt(unsigned long long N)
33 } while ((int)shift >= 0); 60 } while ((int)shift >= 0);
34 return x; 61 return x;
35} 62}
63# else
64/* Stolen from kernel code */
65unsigned long FAST_FUNC isqrt_ull(unsigned long long x)
66{
67 unsigned long long y = 0;
68 unsigned long long m = 1ULL << (8*sizeof(x) - 2);
69 // ^^^^^ should be m = 1ULL << ((fls(x) - 1) & ~1ULL);
70 // but calculating fls() would take time and code
71
72 do {
73 unsigned long long b = y + m;
74 y >>= 1;
75 if (x >= b) {
76 x -= b;
77 y += m;
78 }
79 m >>= 2;
80 } while (m);
81 return y;
82}
83# endif
84#endif /* wide version needed */
36 85
37#ifdef ISQRT_TEST 86#ifdef ISQRT_TEST
87# if LLONG_MAX == LONG_MAX
88# define isqrt_ull(N) isqrt(N)
89# endif
38int main(int argc, char **argv) 90int main(int argc, char **argv)
39{ 91{
40 unsigned long long n = argv[1] ? strtoull(argv[1], NULL, 0) : time(NULL); 92 unsigned long long n = argv[1] ? strtoull(argv[1], NULL, 0) : time(NULL);
41 for (;;) { 93 for (;;) {
42 unsigned long h; 94 unsigned long h;
43 n--; 95 n--;
44 h = isqrt(n); 96 h = isqrt_ull(n);
45 if (!(n & 0xffff)) 97 if (!(n & 0xffff))
46 printf("isqrt(%llx)=%lx\n", n, h); 98 printf("isqrt(%llx)=%lx\n", n, h);
47 if ((unsigned long long)h * h > n) { 99 if ((unsigned long long)h * h > n) {
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index 675c91d68..f4d1b913a 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -351,6 +351,22 @@ char* xasprintf(const char *format, ...)
351 return string_ptr; 351 return string_ptr;
352} 352}
353 353
354char* xasprintf_and_free(char *allocated, const char *format, ...)
355{
356 va_list p;
357 int r;
358 char *string_ptr;
359
360 va_start(p, format);
361 r = vasprintf(&string_ptr, format, p);
362 va_end(p);
363
364 if (r < 0)
365 bb_die_memory_exhausted();
366 free(allocated);
367 return string_ptr;
368}
369
354void FAST_FUNC xsetenv(const char *key, const char *value) 370void FAST_FUNC xsetenv(const char *key, const char *value)
355{ 371{
356 if (setenv(key, value, 1)) 372 if (setenv(key, value, 1))
diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c
index 2470050e7..ff54ab5db 100644
--- a/loginutils/add-remove-shell.c
+++ b/loginutils/add-remove-shell.c
@@ -64,7 +64,6 @@ int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
64 if (orig_fp) 64 if (orig_fp)
65 xfstat(fileno(orig_fp), &sb, orig_fn); 65 xfstat(fileno(orig_fp), &sb, orig_fn);
66 66
67
68 new_fn = xasprintf("%s.tmp", orig_fn); 67 new_fn = xasprintf("%s.tmp", orig_fn);
69 /* 68 /*
70 * O_TRUNC or O_EXCL? At the first glance, O_EXCL looks better, 69 * O_TRUNC or O_EXCL? At the first glance, O_EXCL looks better,
diff --git a/loginutils/adduser.c b/loginutils/adduser.c
index bfab05203..ac43feb48 100644
--- a/loginutils/adduser.c
+++ b/loginutils/adduser.c
@@ -227,7 +227,7 @@ int adduser_main(int argc UNUSED_PARAM, char **argv)
227 die_if_bad_username(pw.pw_name); 227 die_if_bad_username(pw.pw_name);
228 if (!pw.pw_dir) { 228 if (!pw.pw_dir) {
229 /* create string for $HOME if not specified already */ 229 /* create string for $HOME if not specified already */
230 pw.pw_dir = xasprintf("/home/%s", argv[0]); 230 pw.pw_dir = concat_path_file("/home", argv[0]);
231 } 231 }
232 pw.pw_passwd = (char *)"x"; 232 pw.pw_passwd = (char *)"x";
233 if (opts & OPT_SYSTEM_ACCOUNT) { 233 if (opts & OPT_SYSTEM_ACCOUNT) {
diff --git a/loginutils/getty.c b/loginutils/getty.c
index 4581cc9f7..67a08f487 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -213,7 +213,7 @@ static void open_tty(void)
213 /* Set up new standard input, unless we are given an already opened port */ 213 /* Set up new standard input, unless we are given an already opened port */
214 if (NOT_LONE_DASH(G.tty_name)) { 214 if (NOT_LONE_DASH(G.tty_name)) {
215 if (G.tty_name[0] != '/') 215 if (G.tty_name[0] != '/')
216 G.tty_name = xasprintf("/dev/%s", G.tty_name); /* will leak it */ 216 G.tty_name = concat_path_file("/dev", G.tty_name); /* will leak it */
217 217
218 /* Open the tty as standard input */ 218 /* Open the tty as standard input */
219 debug("open(2)\n"); 219 debug("open(2)\n");
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c
index 642cd3637..d57691414 100644
--- a/miscutils/devfsd.c
+++ b/miscutils/devfsd.c
@@ -962,7 +962,6 @@ static void action_compat(const struct devfsd_notify_struct *info, unsigned int
962 dest_name = dest_buf; 962 dest_name = dest_buf;
963 compat_name = compat_buf; 963 compat_name = compat_buf;
964 964
965
966 /* 1 == scsi/generic 2 == scsi/disc 3 == scsi/cd 6 == ide/host/disc 7 == ide/host/cd */ 965 /* 1 == scsi/generic 2 == scsi/disc 3 == scsi/cd 6 == ide/host/disc 7 == ide/host/cd */
967 if (i == 1 || i == 2 || i == 3 || i == 6 || i ==7) 966 if (i == 1 || i == 2 || i == 3 || i == 6 || i ==7)
968 sprintf(compat_buf, fmt[i], host, bus, target, lun); 967 sprintf(compat_buf, fmt[i], host, bus, target, lun);
diff --git a/miscutils/less.c b/miscutils/less.c
index 5a8fc5a74..91403a252 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -857,13 +857,13 @@ static void print_found(const char *line)
857 goto start; 857 goto start;
858 858
859 while (match_status == 0) { 859 while (match_status == 0) {
860 char *new = xasprintf("%s%.*s"HIGHLIGHT"%.*s"NORMAL, 860 xasprintf_inplace(growline,
861 growline ? growline : "", 861 "%s%.*s"HIGHLIGHT"%.*s"NORMAL,
862 (int)match_structs.rm_so, str, 862 growline ? growline : "",
863 (int)(match_structs.rm_eo - match_structs.rm_so), 863 (int)match_structs.rm_so,
864 str + match_structs.rm_so); 864 str,
865 free(growline); 865 (int)(match_structs.rm_eo - match_structs.rm_so),
866 growline = new; 866 str + match_structs.rm_so);
867 str += match_structs.rm_eo; 867 str += match_structs.rm_eo;
868 line += match_structs.rm_eo; 868 line += match_structs.rm_eo;
869 eflags = REG_NOTBOL; 869 eflags = REG_NOTBOL;
diff --git a/miscutils/man.c b/miscutils/man.c
index 38c1b9aa3..cf67f1538 100644
--- a/miscutils/man.c
+++ b/miscutils/man.c
@@ -73,7 +73,7 @@ struct globals {
73 73
74static int show_manpage(char *man_filename, int man, int level); 74static int show_manpage(char *man_filename, int man, int level);
75 75
76static int run_pipe(char *man_filename, int man, int level) 76static int run_man_pipe(char *man_filename, int man, int level)
77{ 77{
78 char *cmd; 78 char *cmd;
79 79
@@ -115,24 +115,36 @@ static int run_pipe(char *man_filename, int man, int level)
115 * ".so man7/path_resolution.7\n<junk>" 115 * ".so man7/path_resolution.7\n<junk>"
116 */ 116 */
117 *strchrnul(line, '\n') = '\0'; 117 *strchrnul(line, '\n') = '\0';
118 linkname = skip_whitespace(&line[4]); 118 linkname = skip_whitespace(line + 4);
119 119//testcase:
120 /* If link has no slashes, we just replace man page name. 120// cd /usr/share/man/man2
121 * If link has slashes (however many), we go back *once*. 121// man ./path_resolution.2.gz
122 * ".so zzz/ggg/page.3" does NOT go back two levels. */ 122 while (man_filename[0] == '.' && man_filename[1] == '/')
123 man_filename += 2;
123 p = strrchr(man_filename, '/'); 124 p = strrchr(man_filename, '/');
124 if (!p) 125 if (!p)
125 goto ordinary_manpage; 126 man_filename = (char*)".." + 1; /* "NAME.N" -> "." */
126 *p = '\0'; 127 else
128 *p = '\0'; /* "PFX/manN/NAME.N" -> "PFX/manN" */
129
130 /* If link has slashes (however many), we go back *once*.
131 * ".so zzz/ggg/page.3" does NOT go back two levels.
132 */
127 if (strchr(linkname, '/')) { 133 if (strchr(linkname, '/')) {
134 if (!p) { /* man_filename had no path */
135 man_filename--; /* ".." */
136 goto append_link;
137 }
128 p = strrchr(man_filename, '/'); 138 p = strrchr(man_filename, '/');
129 if (!p) 139 if (!p)
130 goto ordinary_manpage; 140 man_filename = (char*)".." + 1; /* "manN" -> "." */
131 *p = '\0'; 141 else
132 } 142 *p = '\0'; /* "PFX/manN" -> "PFX" */
143 } /* else (link has no slashes): will do "PFX/manN" -> "PFX/manN/link" */
133 144
134 /* Links do not have .gz extensions, even if manpage 145 /* Links do not have .gz extensions, even if manpage
135 * is compressed */ 146 * is compressed */
147 append_link:
136 man_filename = xasprintf("%s/%s", man_filename, linkname); 148 man_filename = xasprintf("%s/%s", man_filename, linkname);
137 free(line); 149 free(line);
138 /* Note: we leak "new" man_filename string as well... */ 150 /* Note: we leak "new" man_filename string as well... */
@@ -172,26 +184,26 @@ static int show_manpage(char *man_filename, int man, int level)
172#endif 184#endif
173 185
174#if ENABLE_FEATURE_SEAMLESS_LZMA 186#if ENABLE_FEATURE_SEAMLESS_LZMA
175 if (run_pipe(filename_with_zext, man, level)) 187 if (run_man_pipe(filename_with_zext, man, level))
176 return 1; 188 return 1;
177#endif 189#endif
178#if ENABLE_FEATURE_SEAMLESS_XZ 190#if ENABLE_FEATURE_SEAMLESS_XZ
179 strcpy(ext, "xz"); 191 strcpy(ext, "xz");
180 if (run_pipe(filename_with_zext, man, level)) 192 if (run_man_pipe(filename_with_zext, man, level))
181 return 1; 193 return 1;
182#endif 194#endif
183#if ENABLE_FEATURE_SEAMLESS_BZ2 195#if ENABLE_FEATURE_SEAMLESS_BZ2
184 strcpy(ext, "bz2"); 196 strcpy(ext, "bz2");
185 if (run_pipe(filename_with_zext, man, level)) 197 if (run_man_pipe(filename_with_zext, man, level))
186 return 1; 198 return 1;
187#endif 199#endif
188#if ENABLE_FEATURE_SEAMLESS_GZ 200#if ENABLE_FEATURE_SEAMLESS_GZ
189 strcpy(ext, "gz"); 201 strcpy(ext, "gz");
190 if (run_pipe(filename_with_zext, man, level)) 202 if (run_man_pipe(filename_with_zext, man, level))
191 return 1; 203 return 1;
192#endif 204#endif
193 205
194 return run_pipe(man_filename, man, level); 206 return run_man_pipe(man_filename, man, level);
195} 207}
196 208
197static char **add_MANPATH(char **man_path_list, int *count_mp, char *path) 209static char **add_MANPATH(char **man_path_list, int *count_mp, char *path)
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index 31a215a29..7f584102d 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -723,7 +723,7 @@ static int process_module(char *name, const char *cmdline_options)
723 723
724 options = NULL; 724 options = NULL;
725 if (!is_remove) { 725 if (!is_remove) {
726 char *opt_filename = xasprintf("/etc/modules/%s", name); 726 char *opt_filename = concat_path_file("/etc/modules", name);
727 options = xmalloc_open_read_close(opt_filename, NULL); 727 options = xmalloc_open_read_close(opt_filename, NULL);
728 if (options) 728 if (options)
729 replace_char(options, '\n', ' '); 729 replace_char(options, '\n', ' ');
@@ -731,10 +731,8 @@ static int process_module(char *name, const char *cmdline_options)
731 if (cmdline_options) { 731 if (cmdline_options) {
732 /* NB: cmdline_options always have one leading ' ' 732 /* NB: cmdline_options always have one leading ' '
733 * (see main()), we remove it here */ 733 * (see main()), we remove it here */
734 char *op = xasprintf(options ? "%s %s" : "%s %s" + 3, 734 xasprintf_inplace(options, options ? "%s %s" : "%s %s" + 3,
735 cmdline_options + 1, options); 735 cmdline_options + 1, options);
736 free(options);
737 options = op;
738 } 736 }
739#endif 737#endif
740 free(opt_filename); 738 free(opt_filename);
@@ -1010,9 +1008,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
1010 char **arg = argv; 1008 char **arg = argv;
1011 while (*++arg) { 1009 while (*++arg) {
1012 /* Enclose options in quotes */ 1010 /* Enclose options in quotes */
1013 char *s = options; 1011 xasprintf_inplace(options, "%s \"%s\"", options ? options : "", *arg);
1014 options = xasprintf("%s \"%s\"", s ? s : "", *arg);
1015 free(s);
1016 *arg = NULL; 1012 *arg = NULL;
1017 } 1013 }
1018# else 1014# else
diff --git a/networking/ftpd.c b/networking/ftpd.c
index c3125410e..96db5d9fd 100644
--- a/networking/ftpd.c
+++ b/networking/ftpd.c
@@ -491,19 +491,18 @@ static void
491handle_pasv(void) 491handle_pasv(void)
492{ 492{
493 unsigned port; 493 unsigned port;
494 char *addr, *response; 494 char *response;
495 495
496 port = bind_for_passive_mode(); 496 port = bind_for_passive_mode();
497 497
498 if (G.local_addr->u.sa.sa_family == AF_INET) 498 if (G.local_addr->u.sa.sa_family == AF_INET)
499 addr = xmalloc_sockaddr2dotted_noport(&G.local_addr->u.sa); 499 response = xmalloc_sockaddr2dotted_noport(&G.local_addr->u.sa);
500 else /* seen this in the wild done by other ftp servers: */ 500 else /* seen this in the wild done by other ftp servers: */
501 addr = xstrdup("0.0.0.0"); 501 response = xstrdup("0.0.0.0");
502 replace_char(addr, '.', ','); 502 replace_char(response, '.', ',');
503 503
504 response = xasprintf(STR(FTP_PASVOK)" PASV ok (%s,%u,%u)\r\n", 504 xasprintf_inplace(response, STR(FTP_PASVOK)" PASV ok (%s,%u,%u)\r\n",
505 addr, (int)(port >> 8), (int)(port & 255)); 505 response, (int)(port >> 8), (int)(port & 255));
506 free(addr);
507 cmdio_write_raw(response); 506 cmdio_write_raw(response);
508 free(response); 507 free(response);
509} 508}
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 9c3640be7..bc2dca506 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -895,16 +895,15 @@ static struct interfaces_file_t *read_interfaces(const char *filename, struct in
895 while ((buf = xmalloc_fgetline(f)) != NULL) { 895 while ((buf = xmalloc_fgetline(f)) != NULL) {
896#if ENABLE_DESKTOP 896#if ENABLE_DESKTOP
897 /* Trailing "\" concatenates lines */ 897 /* Trailing "\" concatenates lines */
898//TODO: check how to handle "line\\" (double backslashes)
898 char *p; 899 char *p;
899 while ((p = last_char_is(buf, '\\')) != NULL) { 900 while ((p = last_char_is(buf, '\\')) != NULL) {
900 *p = '\0'; 901 *p = '\0';
901 rest_of_line = xmalloc_fgetline(f); 902 rest_of_line = xmalloc_fgetline(f);
902 if (!rest_of_line) 903 if (!rest_of_line)
903 break; 904 break;
904 p = xasprintf("%s%s", buf, rest_of_line); 905 xasprintf_inplace(buf, "%s%s", buf, rest_of_line);
905 free(buf);
906 free(rest_of_line); 906 free(rest_of_line);
907 buf = p;
908 } 907 }
909#endif 908#endif
910 rest_of_line = buf; 909 rest_of_line = buf;
diff --git a/networking/netstat.c b/networking/netstat.c
index 807800a62..d7afa8fdd 100644
--- a/networking/netstat.c
+++ b/networking/netstat.c
@@ -391,7 +391,7 @@ static const char *get_sname(int port, const char *proto, int numeric)
391 391
392static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int numeric) 392static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int numeric)
393{ 393{
394 char *host, *host_port; 394 char *host;
395 395
396 /* Code which used "*" for INADDR_ANY is removed: it's ambiguous 396 /* Code which used "*" for INADDR_ANY is removed: it's ambiguous
397 * in IPv6, while "0.0.0.0" is not. */ 397 * in IPv6, while "0.0.0.0" is not. */
@@ -402,9 +402,8 @@ static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int
402 if (!host) 402 if (!host)
403 host = xmalloc_sockaddr2dotted_noport(addr); 403 host = xmalloc_sockaddr2dotted_noport(addr);
404 404
405 host_port = xasprintf("%s:%s", host, get_sname(htons(port), proto, numeric)); 405 xasprintf_inplace(host, "%s:%s", host, get_sname(htons(port), proto, numeric));
406 free(host); 406 return host;
407 return host_port;
408} 407}
409 408
410struct inet_params { 409struct inet_params {
diff --git a/networking/ntpd.c b/networking/ntpd.c
index efe9f5326..595000b11 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -2395,7 +2395,7 @@ static NOINLINE void ntp_init(char **argv)
2395 while (peers) { 2395 while (peers) {
2396 char *peer = llist_pop(&peers); 2396 char *peer = llist_pop(&peers);
2397 key_entry_t *key_entry = NULL; 2397 key_entry_t *key_entry = NULL;
2398 if (strncmp(peer, "keyno:", 6) == 0) { 2398 if (is_prefixed_with(peer, "keyno:")) {
2399 char *end; 2399 char *end;
2400 int key_id; 2400 int key_id;
2401 peer += 6; 2401 peer += 6;
diff --git a/networking/tls.h b/networking/tls.h
index eee5a7617..fde2e4d3d 100644
--- a/networking/tls.h
+++ b/networking/tls.h
@@ -10,7 +10,6 @@
10 */ 10 */
11#include "libbb.h" 11#include "libbb.h"
12 12
13
14#if !ENABLE_FEATURE_TLS_SCHANNEL 13#if !ENABLE_FEATURE_TLS_SCHANNEL
15/* Config tweaks */ 14/* Config tweaks */
16#define HAVE_NATIVE_INT64 15#define HAVE_NATIVE_INT64
@@ -32,16 +31,18 @@
32# define PSTM_32BIT 31# define PSTM_32BIT
33# define PSTM_X86 32# define PSTM_X86
34#endif 33#endif
35//#if defined(__GNUC__) && defined(__x86_64__) 34#if defined(__GNUC__) && defined(__x86_64__)
36// /* PSTM_X86_64 works correctly, but +782 bytes. */ 35 /* PSTM_64BIT + PSTM_X86_64 works correctly, but:
37// /* Looks like most of the growth is because of PSTM_64BIT. */ 36 * +928 bytes if PSTM_64BIT but !PSTM_X86_64
37 * +1003 bytes with INNERMUL8 (loop unrolling in pstm_montgomery_reduce())
38 * +664 bytes without INNERMUL8
39 */
38//# define PSTM_64BIT 40//# define PSTM_64BIT
39//# define PSTM_X86_64 41//# define PSTM_X86_64
40//#endif 42#endif
41//#if SOME_COND #define PSTM_MIPS, #define PSTM_32BIT 43//#if SOME_COND #define PSTM_MIPS, #define PSTM_32BIT
42//#if SOME_COND #define PSTM_ARM, #define PSTM_32BIT 44//#if SOME_COND #define PSTM_ARM, #define PSTM_32BIT
43 45
44
45#define PS_SUCCESS 0 46#define PS_SUCCESS 0
46#define PS_FAILURE -1 47#define PS_FAILURE -1
47#define PS_ARG_FAIL -6 /* Failure due to bad function param */ 48#define PS_ARG_FAIL -6 /* Failure due to bad function param */
@@ -52,14 +53,14 @@
52#define PS_TRUE 1 53#define PS_TRUE 1
53#define PS_FALSE 0 54#define PS_FALSE 0
54 55
56#undef ENDIAN_BIG
57#undef ENDIAN_LITTLE
55#if BB_BIG_ENDIAN 58#if BB_BIG_ENDIAN
56# define ENDIAN_BIG 1 59# define ENDIAN_BIG 1
57# undef ENDIAN_LITTLE
58//#???? ENDIAN_32BITWORD 60//#???? ENDIAN_32BITWORD
59// controls only STORE32L, which we don't use 61// controls only STORE32L, which we don't use
60#else 62#else
61# define ENDIAN_LITTLE 1 63# define ENDIAN_LITTLE 1
62# undef ENDIAN_BIG
63#endif 64#endif
64 65
65typedef uint64_t uint64; 66typedef uint64_t uint64;
@@ -99,7 +100,6 @@ void tls_get_random(void *buf, unsigned len) FAST_FUNC;
99#undef min 100#undef min
100#define min(x, y) ((x) < (y) ? (x) : (y)) 101#define min(x, y) ((x) < (y) ? (x) : (y))
101 102
102
103#include "tls_pstm.h" 103#include "tls_pstm.h"
104#include "tls_aes.h" 104#include "tls_aes.h"
105#include "tls_aesgcm.h" 105#include "tls_aesgcm.h"
diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c
index 4181a0590..e63e590db 100644
--- a/networking/tls_pstm_montgomery_reduce.c
+++ b/networking/tls_pstm_montgomery_reduce.c
@@ -135,7 +135,7 @@ asm( \
135 :"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \ 135 :"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \
136 : "%rax", "%rdx", "cc") 136 : "%rax", "%rdx", "cc")
137 137
138#define INNERMUL8 \ 138#define INNERMUL8_disabled_for_bbox \
139asm( \ 139asm( \
140 "movq 0(%5),%%rax \n\t" \ 140 "movq 0(%5),%%rax \n\t" \
141 "movq 0(%2),%%r10 \n\t" \ 141 "movq 0(%2),%%r10 \n\t" \
@@ -398,7 +398,7 @@ int32 FAST_FUNC pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m,
398 _c = c + x; 398 _c = c + x;
399 tmpm = m->dp; 399 tmpm = m->dp;
400 y = 0; 400 y = 0;
401#ifdef PSTM_X86_64 401#ifdef INNERMUL8 //bbox: PSTM_X86_64
402 for (; y < (pa & ~7); y += 8) { 402 for (; y < (pa & ~7); y += 8) {
403 INNERMUL8; 403 INNERMUL8;
404 _c += 8; 404 _c += 8;
diff --git a/procps/watch.c b/procps/watch.c
index d7c3ad55e..51b324b44 100644
--- a/procps/watch.c
+++ b/procps/watch.c
@@ -19,11 +19,12 @@
19//kbuild:lib-$(CONFIG_WATCH) += watch.o 19//kbuild:lib-$(CONFIG_WATCH) += watch.o
20 20
21//usage:#define watch_trivial_usage 21//usage:#define watch_trivial_usage
22//usage: "[-n SEC] [-t] PROG ARGS" 22//usage: "[-n SEC] [-tx] PROG ARGS"
23//usage:#define watch_full_usage "\n\n" 23//usage:#define watch_full_usage "\n\n"
24//usage: "Run PROG periodically\n" 24//usage: "Run PROG periodically\n"
25//usage: "\n -n SEC Period (default 2)" 25//usage: "\n -n SEC Period (default 2)"
26//usage: "\n -t Don't print header" 26//usage: "\n -t Don't print header"
27//usage: "\n -x exec(PROG,ARGS) instead of sh -c 'PROG ARGS'"
27//usage: 28//usage:
28//usage:#define watch_example_usage 29//usage:#define watch_example_usage
29//usage: "$ watch date\n" 30//usage: "$ watch date\n"
@@ -56,6 +57,7 @@ int watch_main(int argc UNUSED_PARAM, char **argv)
56 unsigned opt; 57 unsigned opt;
57 unsigned width, new_width; 58 unsigned width, new_width;
58 char *header; 59 char *header;
60 char **argv0;
59 char *cmd; 61 char *cmd;
60 62
61#if 0 // maybe ENABLE_DESKTOP? 63#if 0 // maybe ENABLE_DESKTOP?
@@ -66,27 +68,32 @@ int watch_main(int argc UNUSED_PARAM, char **argv)
66 68
67 // "+": stop at first non-option (procps 3.x only); -n NUM 69 // "+": stop at first non-option (procps 3.x only); -n NUM
68 // at least one param 70 // at least one param
69 opt = getopt32(argv, "^+" "dtn:" "\0" "-1", &period_str); 71 opt = getopt32(argv, "^+" "dtn:x" "\0" "-1", &period_str);
70 argv += optind; 72 argv += optind;
71 73
72 // watch from both procps 2.x and 3.x does concatenation. Example: 74 // watch from both procps 2.x and 3.x concatenates (unless -x).
73 // watch ls -l "a /tmp" "2>&1" - ls won't see "a /tmp" as one param 75 // Example:
76 // watch ls -l "a /tmp" "2>&1" - ls won't see "a /tmp" as one param.
77 argv0 = argv;
78 // If -x, cmd is only used for printing header
74#if ENABLE_PLATFORM_MINGW32 79#if ENABLE_PLATFORM_MINGW32
75 cmd = NULL; 80 cmd = NULL;
76 do { 81 do {
77 cmd = xappendword(cmd, *argv); 82 cmd = xappendword(cmd, *argv);
78 } while (*++argv); 83 } while (*++argv);
79#else 84#else
80 cmd = *argv; 85 cmd = xstrdup(*argv);
81 while (*++argv) 86 while (*++argv)
82 cmd = xasprintf("%s %s", cmd, *argv); // leaks cmd 87 xasprintf_inplace(cmd, "%s %s", cmd, *argv);
83#endif 88#endif
89 if (opt & (1 << 3))
90 argv = argv0; // If -x, restore argv[0] to !NULL
84 91
85 period = parse_duration_str(period_str); 92 period = parse_duration_str(period_str);
86 width = (unsigned)-1; // make sure first time new_width != width 93 width = (unsigned)-1; // make sure first time new_width != width
87 header = NULL; 94 header = NULL;
88 while (1) { 95 while (1) {
89 /* home; clear to the end of screen */ 96 // home; clear to the end of screen
90 printf(ESC"[H" ESC"[J"); 97 printf(ESC"[H" ESC"[J");
91 if (!(opt & 0x2)) { // no -t 98 if (!(opt & 0x2)) { // no -t
92 const unsigned time_len = sizeof("1234-67-90 23:56:89"); 99 const unsigned time_len = sizeof("1234-67-90 23:56:89");
@@ -119,7 +126,10 @@ int watch_main(int argc UNUSED_PARAM, char **argv)
119 // TODO: 'real' watch pipes cmd's output to itself 126 // TODO: 'real' watch pipes cmd's output to itself
120 // and does not allow it to overflow the screen 127 // and does not allow it to overflow the screen
121 // (taking into account linewrap!) 128 // (taking into account linewrap!)
122 system(cmd); 129 if (argv[0]) // -x?
130 spawn_and_wait(argv); // yes
131 else
132 system(cmd);
123 sleep_for_duration(period); 133 sleep_for_duration(period);
124 } 134 }
125 return 0; // gcc thinks we can reach this :) 135 return 0; // gcc thinks we can reach this :)
diff --git a/shell/ash.c b/shell/ash.c
index 43f92bfae..bb8ac53d6 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -1384,7 +1384,7 @@ static void dbg_show_dirtymem(const char *msg)
1384 p = buf; 1384 p = buf;
1385 for (;;) { 1385 for (;;) {
1386 char *e = strchrnul(p, '\n'); 1386 char *e = strchrnul(p, '\n');
1387 if (strncmp(p, "Private_Dirty:", 14) == 0) { 1387 if (is_prefixed_with(p, "Private_Dirty:")) {
1388 p = skip_whitespace(p + 14); 1388 p = skip_whitespace(p + 14);
1389 bb_error_msg("%s:%.*s", msg, (int)(e - p), p); 1389 bb_error_msg("%s:%.*s", msg, (int)(e - p), p);
1390 break; 1390 break;
diff --git a/shell/hush.c b/shell/hush.c
index da0db7948..23e7f512f 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2941,12 +2941,9 @@ static void i_prepend_to_alias_buffer(struct in_str *i, char *prepend, char ch)
2941 * a 2941 * a
2942 * ^^^ runs "echo A: c" 2942 * ^^^ runs "echo A: c"
2943 */ 2943 */
2944 char *old = i->albuf;
2945 //bb_error_msg("before'%s' p'%s'", i->albuf, i->p); 2944 //bb_error_msg("before'%s' p'%s'", i->albuf, i->p);
2946 i->albuf = xasprintf("%s%c%s", prepend, ch, i->p); 2945 i->p = xasprintf_inplace(i->albuf, "%s%c%s", prepend, ch, i->p);
2947 i->p = i->albuf;
2948 //bb_error_msg("after'%s' p'%s'", i->albuf, i->p); 2946 //bb_error_msg("after'%s' p'%s'", i->albuf, i->p);
2949 free(old);
2950 return; 2947 return;
2951 } 2948 }
2952 i->saved_ibuf = i->p; 2949 i->saved_ibuf = i->p;
diff --git a/util-linux/acpid.c b/util-linux/acpid.c
index 5c0bb1768..386b988d2 100644
--- a/util-linux/acpid.c
+++ b/util-linux/acpid.c
@@ -145,7 +145,7 @@ struct globals {
145static void process_event(const char *event) 145static void process_event(const char *event)
146{ 146{
147 struct stat st; 147 struct stat st;
148 char *handler = xasprintf("./%s", event); 148 char *handler = concat_path_file(".", event);
149 const char *args[] = { "run-parts", handler, NULL }; 149 const char *args[] = { "run-parts", handler, NULL };
150 150
151 // log the event 151 // log the event
diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c
index 5d8f01a64..39eecc345 100644
--- a/util-linux/dmesg.c
+++ b/util-linux/dmesg.c
@@ -91,7 +91,6 @@ int dmesg_main(int argc UNUSED_PARAM, char **argv)
91 if (len == 0) 91 if (len == 0)
92 return EXIT_SUCCESS; 92 return EXIT_SUCCESS;
93 93
94
95 if (ENABLE_FEATURE_DMESG_PRETTY && !(opts & OPT_r)) { 94 if (ENABLE_FEATURE_DMESG_PRETTY && !(opts & OPT_r)) {
96 int last = '\n'; 95 int last = '\n';
97 int in = 0; 96 int in = 0;
diff --git a/util-linux/lsblk.c b/util-linux/lsblk.c
index a482bfbbc..3bd40bcb4 100644
--- a/util-linux/lsblk.c
+++ b/util-linux/lsblk.c
@@ -101,10 +101,10 @@ static char *get_mountpoints(const char *majmin)
101 101
102 mountpoints = NULL; 102 mountpoints = NULL;
103 len = strlen(majmin); 103 len = strlen(majmin);
104 p = G.mountinfo; // "/proc/self/mountinfo" 104 p = G.mountinfo; // contents of "/proc/self/mountinfo"
105 /* lines a-la "63 1 259:3 / /MNTPOINT per-mount_options - ext4 /dev/NAME per-superblock_options" */ 105 /* lines a-la "63 1 259:3 / /MNTPOINT per-mount_options - ext4 /dev/NAME per-superblock_options" */
106 while (*p) { 106 while (*p) {
107 char *e, *f; 107 char *e;
108 108
109 p = skip_non_whitespace(p); 109 p = skip_non_whitespace(p);
110 if (*p != ' ') break; 110 if (*p != ' ') break;
@@ -127,12 +127,11 @@ static char *get_mountpoints(const char *majmin)
127 // at " /MNTPOINT" 127 // at " /MNTPOINT"
128 e = skip_non_whitespace(p + 1); 128 e = skip_non_whitespace(p + 1);
129 // e is at the end of " /MNTPOINT" 129 // e is at the end of " /MNTPOINT"
130 f = mountpoints;
131// NO. We return " /MNT1 /MNT2 /MNT3" _with_ leading space! 130// NO. We return " /MNT1 /MNT2 /MNT3" _with_ leading space!
132// if (!f) 131// if (!mountpoints)
133// p++; 132// p++;
134 mountpoints = xasprintf("%s%.*s", f ? f : "", (int)(e - p), p); 133 xasprintf_inplace(mountpoints, "%s%.*s",
135 free(f); 134 mountpoints ? mountpoints : "", (int)(e - p), p);
136 } 135 }
137 return mountpoints; 136 return mountpoints;
138} 137}
diff --git a/util-linux/lspci.c b/util-linux/lspci.c
index 25be23a01..1a43f71e2 100644
--- a/util-linux/lspci.c
+++ b/util-linux/lspci.c
@@ -81,7 +81,6 @@ static int FAST_FUNC fileAction(struct recursive_state *state UNUSED_PARAM,
81 } 81 }
82 config_close(parser); 82 config_close(parser);
83 83
84
85 if (option_mask32 & OPT_m) { 84 if (option_mask32 & OPT_m) {
86 printf("%s \"Class %04x\" \"%04x\" \"%04x\" \"%04x\" \"%04x\"", 85 printf("%s \"Class %04x\" \"%04x\" \"%04x\" \"%04x\" \"%04x\"",
87 pci_slot_name, pci_class, pci_vid, pci_did, 86 pci_slot_name, pci_class, pci_vid, pci_did,
diff --git a/util-linux/mount.c b/util-linux/mount.c
index d0f0ae1ad..d0d109c09 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -556,27 +556,33 @@ static int verbose_mount(const char *source, const char *target,
556#endif 556#endif
557 557
558// Append mount options to string 558// Append mount options to string
559// ("merge two comma-separated lists" is a good candidate for libbb!)
559static void append_mount_options(char **oldopts, const char *newopts) 560static void append_mount_options(char **oldopts, const char *newopts)
560{ 561{
561 if (*oldopts && **oldopts) { 562 if (*oldopts && **oldopts) {
563//TODO: do this unconditionally?
564//this way, newopts of "opt1,opt2,opt1"
565//will be de-duped into "opt1,opt2" in _both_ cases
566//(whether or now old opts are empty)
567//the only modification needed is to not prepend extra comma
568//when old opts is "".
562 // Do not insert options which are already there 569 // Do not insert options which are already there
563 while (newopts[0]) { 570 while (*newopts) {
564 char *p; 571 char *p;
565 int len; 572 int len;
566 573
574 //if (*newopts == ',') { newopts++; continue; }
567 len = strchrnul(newopts, ',') - newopts; 575 len = strchrnul(newopts, ',') - newopts;
568 p = *oldopts; 576 p = *oldopts;
569 while (1) { 577 while (1) {
570 if (!strncmp(p, newopts, len) 578 if (strncmp(p, newopts, len) == 0
571 && (p[len] == ',' || p[len] == '\0')) 579 && (p[len] == ',' || p[len] == '\0'))
572 goto skip; 580 goto skip;
573 p = strchr(p,','); 581 p = strchr(p, ',');
574 if (!p) break; 582 if (!p) break;
575 p++; 583 p++;
576 } 584 }
577 p = xasprintf("%s,%.*s", *oldopts, len, newopts); 585 xasprintf_inplace(*oldopts, "%s,%.*s", *oldopts, len, newopts);
578 free(*oldopts);
579 *oldopts = p;
580 skip: 586 skip:
581 newopts += len; 587 newopts += len;
582 while (*newopts == ',') newopts++; 588 while (*newopts == ',') newopts++;
@@ -2065,12 +2071,11 @@ static int singlemount(struct mntent *mp, int ignore_busy)
2065 if (!is_prefixed_with(filteropts, ",ip="+1) 2071 if (!is_prefixed_with(filteropts, ",ip="+1)
2066 && !strstr(filteropts, ",ip=") 2072 && !strstr(filteropts, ",ip=")
2067 ) { 2073 ) {
2068 char *dotted, *ip; 2074 char *ip;
2069 // Insert "ip=..." option into options 2075 // Insert "ip=..." option into options
2070 dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); 2076 ip = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
2071 if (ENABLE_FEATURE_CLEAN_UP) free(lsa); 2077 if (ENABLE_FEATURE_CLEAN_UP) free(lsa);
2072 ip = xasprintf("ip=%s", dotted); 2078 xasprintf_inplace(ip, "ip=%s", ip);
2073 if (ENABLE_FEATURE_CLEAN_UP) free(dotted);
2074// Note: IPv6 scoped addresses ("host%iface", see RFC 4007) should be 2079// Note: IPv6 scoped addresses ("host%iface", see RFC 4007) should be
2075// handled by libc in getnameinfo() (inside xmalloc_sockaddr2dotted_noport()). 2080// handled by libc in getnameinfo() (inside xmalloc_sockaddr2dotted_noport()).
2076// Currently, glibc does not support that (has no NI_NUMERICSCOPE), 2081// Currently, glibc does not support that (has no NI_NUMERICSCOPE),
diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c
index 39155f256..52bb8e03a 100644
--- a/util-linux/volume_id/get_devname.c
+++ b/util-linux/volume_id/get_devname.c
@@ -110,7 +110,7 @@ uuidcache_check_device(struct recursive_state *state UNUSED_PARAM,
110 /* note: this check rejects links to devices, among other nodes */ 110 /* note: this check rejects links to devices, among other nodes */
111 if (!S_ISBLK(statbuf->st_mode) 111 if (!S_ISBLK(statbuf->st_mode)
112#if ENABLE_FEATURE_VOLUMEID_UBIFS 112#if ENABLE_FEATURE_VOLUMEID_UBIFS
113 && !(S_ISCHR(statbuf->st_mode) && strncmp(bb_basename(device), "ubi", 3) == 0) 113 && !(S_ISCHR(statbuf->st_mode) && is_prefixed_with(bb_basename(device), "ubi"))
114#endif 114#endif
115 ) 115 )
116 return TRUE; 116 return TRUE;
diff --git a/util-linux/volume_id/unused_lvm.c b/util-linux/volume_id/unused_lvm.c
index 649306c85..512aa7962 100644
--- a/util-linux/volume_id/unused_lvm.c
+++ b/util-linux/volume_id/unused_lvm.c
@@ -74,7 +74,6 @@ int FAST_FUNC volume_id_probe_lvm2(struct volume_id *id, uint64_t off)
74 if (buf == NULL) 74 if (buf == NULL)
75 return -1; 75 return -1;
76 76
77
78 for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) { 77 for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) {
79 lvm = (struct lvm2_super_block *) &buf[soff]; 78 lvm = (struct lvm2_super_block *) &buf[soff];
80 79