diff options
| author | Ron Yorston <rmy@pobox.com> | 2022-10-12 10:43:26 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2022-10-12 10:43:26 +0100 |
| commit | 49c6f079acb4edae84b4496bd941cdbb5048ba01 (patch) | |
| tree | ac54ecaad45050f7bfe274a11db29882aa32a9a8 | |
| parent | a55cf07365ec2ff51749a77e09ae9edac79a99fe (diff) | |
| parent | c8c1fcdba163f264a503380bc63485aacd09214c (diff) | |
| download | busybox-w32-49c6f079acb4edae84b4496bd941cdbb5048ba01.tar.gz busybox-w32-49c6f079acb4edae84b4496bd941cdbb5048ba01.tar.bz2 busybox-w32-49c6f079acb4edae84b4496bd941cdbb5048ba01.zip | |
Merge branch 'busybox' into merge
46 files changed, 678 insertions, 186 deletions
| @@ -181,3 +181,6 @@ Jie Zhang <jie.zhang@analog.com> | |||
| 181 | 181 | ||
| 182 | Maxime Coste <mawww@kakoune.org> | 182 | Maxime Coste <mawww@kakoune.org> |
| 183 | paste implementation | 183 | paste implementation |
| 184 | |||
| 185 | Roger Knecht <rknecht@pm.me> | ||
| 186 | tree | ||
diff --git a/archival/dpkg.c b/archival/dpkg.c index 8e1f9431d..a6a8333a8 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
| @@ -1120,7 +1120,7 @@ static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count | |||
| 1120 | if (package_edge->type == EDGE_PRE_DEPENDS | 1120 | if (package_edge->type == EDGE_PRE_DEPENDS |
| 1121 | || package_edge->type == EDGE_DEPENDS | 1121 | || package_edge->type == EDGE_DEPENDS |
| 1122 | ) { | 1122 | ) { |
| 1123 | int result=1; | 1123 | int result = 1; |
| 1124 | status_num = 0; | 1124 | status_num = 0; |
| 1125 | 1125 | ||
| 1126 | /* If we are inside an alternative then check | 1126 | /* If we are inside an alternative then check |
diff --git a/coreutils/cut.c b/coreutils/cut.c index 7009e74cf..55bdd9386 100644 --- a/coreutils/cut.c +++ b/coreutils/cut.c | |||
| @@ -167,7 +167,7 @@ static void cut_file(FILE *file, const char *delim, const char *odelim, | |||
| 167 | if (!cl_pos && !dcount && !shoe) { | 167 | if (!cl_pos && !dcount && !shoe) { |
| 168 | if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) | 168 | if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) |
| 169 | goto next_line; | 169 | goto next_line; |
| 170 | } else if (dcount<cut_lists[cl_pos].startpos) | 170 | } else if (dcount < cut_lists[cl_pos].startpos) |
| 171 | start = linelen; | 171 | start = linelen; |
| 172 | end = linelen; | 172 | end = linelen; |
| 173 | } else { | 173 | } else { |
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 0e57673f1..b4bdc262c 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c | |||
| @@ -301,9 +301,7 @@ int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv) | |||
| 301 | 301 | ||
| 302 | count_total++; | 302 | count_total++; |
| 303 | filename_ptr = strchr(line, ' '); | 303 | filename_ptr = strchr(line, ' '); |
| 304 | if (filename_ptr == NULL | 304 | if (!filename_ptr) { |
| 305 | || (filename_ptr[1] != ' ' && filename_ptr[1] != '*') | ||
| 306 | ) { | ||
| 307 | if (flags & FLAG_WARN) { | 305 | if (flags & FLAG_WARN) { |
| 308 | bb_simple_error_msg("invalid format"); | 306 | bb_simple_error_msg("invalid format"); |
| 309 | } | 307 | } |
| @@ -312,8 +310,13 @@ int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv) | |||
| 312 | free(line); | 310 | free(line); |
| 313 | continue; | 311 | continue; |
| 314 | } | 312 | } |
| 315 | *filename_ptr = '\0'; | 313 | *filename_ptr++ = '\0'; |
| 316 | filename_ptr += 2; | 314 | /* coreutils 9.1 allows "HASH FILENAME" format, |
| 315 | * with only one space. Skip the 'correct' | ||
| 316 | * " " or " *" delimiter if it is there: | ||
| 317 | */ | ||
| 318 | if (*filename_ptr == ' ' || *filename_ptr == '*') | ||
| 319 | filename_ptr++; | ||
| 317 | 320 | ||
| 318 | hash_value = hash_file(in_buf, filename_ptr, sha3_width); | 321 | hash_value = hash_file(in_buf, filename_ptr, sha3_width); |
| 319 | 322 | ||
diff --git a/coreutils/sleep.c b/coreutils/sleep.c index 2658e84df..442841210 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | //applet:IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP)) | 37 | //applet:IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP)) |
| 38 | 38 | ||
| 39 | //kbuild:lib-$(CONFIG_SLEEP) += sleep.o | 39 | //kbuild:lib-$(CONFIG_SLEEP) += sleep.o |
| 40 | //kbuild:lib-$(CONFIG_ASH_SLEEP) += sleep.o | ||
| 40 | 41 | ||
| 41 | /* BB_AUDIT SUSv3 compliant */ | 42 | /* BB_AUDIT SUSv3 compliant */ |
| 42 | /* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */ | 43 | /* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */ |
diff --git a/coreutils/sort.c b/coreutils/sort.c index 9aac656fe..01b7c44e5 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c | |||
| @@ -357,9 +357,9 @@ static int compare_keys(const void *xarg, const void *yarg) | |||
| 357 | int dx; | 357 | int dx; |
| 358 | char *xx, *yy; | 358 | char *xx, *yy; |
| 359 | 359 | ||
| 360 | xx = strptime(x, "%b", &thyme); | 360 | xx = strptime(skip_whitespace(x), "%b", &thyme); |
| 361 | dx = thyme.tm_mon; | 361 | dx = thyme.tm_mon; |
| 362 | yy = strptime(y, "%b", &thyme); | 362 | yy = strptime(skip_whitespace(y), "%b", &thyme); |
| 363 | if (!xx) | 363 | if (!xx) |
| 364 | retval = (!yy) ? 0 : -1; | 364 | retval = (!yy) ? 0 : -1; |
| 365 | else if (!yy) | 365 | else if (!yy) |
| @@ -652,11 +652,12 @@ int sort_main(int argc UNUSED_PARAM, char **argv) | |||
| 652 | /* Handle -u */ | 652 | /* Handle -u */ |
| 653 | if (option_mask32 & FLAG_u) { | 653 | if (option_mask32 & FLAG_u) { |
| 654 | int j = 0; | 654 | int j = 0; |
| 655 | /* coreutils 6.3 drop lines for which only key is the same | 655 | /* coreutils 6.3 drop lines for which only key is the same: |
| 656 | * -- disabling last-resort compare, or else compare_keys() | 656 | * - disabling last-resort compare, or else compare_keys() |
| 657 | * will be the same only for completely identical lines. | 657 | * will be the same only for completely identical lines |
| 658 | * - disabling -s (same reasons) | ||
| 658 | */ | 659 | */ |
| 659 | option_mask32 |= FLAG_no_tie_break; | 660 | option_mask32 = (option_mask32 | FLAG_no_tie_break) & (~FLAG_s); |
| 660 | for (i = 1; i < linecount; i++) { | 661 | for (i = 1; i < linecount; i++) { |
| 661 | if (compare_keys(&lines[j], &lines[i]) == 0) | 662 | if (compare_keys(&lines[j], &lines[i]) == 0) |
| 662 | free(lines[i]); | 663 | free(lines[i]); |
diff --git a/coreutils/test.c b/coreutils/test.c index 840a0daaf..1d1e6d18b 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
| @@ -859,7 +859,7 @@ static number_t primary(enum token n) | |||
| 859 | if (check_operator(args[1]) != EOI) { /* if args[1] != NULL */ | 859 | if (check_operator(args[1]) != EOI) { /* if args[1] != NULL */ |
| 860 | if (args[2]) { | 860 | if (args[2]) { |
| 861 | // coreutils also does this: | 861 | // coreutils also does this: |
| 862 | // if (args[3] && args[0]="-l" && args[2] is BINOP) | 862 | // if (args[3] && args[0] = "-l" && args[2] is BINOP) |
| 863 | // return binop(1 /* prepended by -l */); | 863 | // return binop(1 /* prepended by -l */); |
| 864 | if (last_operator->op_type == BINOP) | 864 | if (last_operator->op_type == BINOP) |
| 865 | unnest_msg_and_return(binop(), "<primary: binop:%lld\n"); | 865 | unnest_msg_and_return(binop(), "<primary: binop:%lld\n"); |
diff --git a/editors/awk.c b/editors/awk.c index 9b4d4dc3d..eedb7aa84 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
| @@ -3147,6 +3147,9 @@ static var *evaluate(node *op, var *res) | |||
| 3147 | 3147 | ||
| 3148 | case XC( OC_MOVE ): | 3148 | case XC( OC_MOVE ): |
| 3149 | debug_printf_eval("MOVE\n"); | 3149 | debug_printf_eval("MOVE\n"); |
| 3150 | /* make sure that we never return a temp var */ | ||
| 3151 | if (L.v == TMPVAR0) | ||
| 3152 | L.v = res; | ||
| 3150 | /* if source is a temporary string, jusk relink it to dest */ | 3153 | /* if source is a temporary string, jusk relink it to dest */ |
| 3151 | if (R.v == TMPVAR1 | 3154 | if (R.v == TMPVAR1 |
| 3152 | && !(R.v->type & VF_NUMBER) | 3155 | && !(R.v->type & VF_NUMBER) |
diff --git a/editors/patch.c b/editors/patch.c index aebb5073e..f90d6854d 100644 --- a/editors/patch.c +++ b/editors/patch.c | |||
| @@ -138,9 +138,9 @@ static void do_line(void *data) | |||
| 138 | { | 138 | { |
| 139 | struct double_list *dlist = data; | 139 | struct double_list *dlist = data; |
| 140 | 140 | ||
| 141 | if (TT.state>1 && *dlist->data != TT.state) | 141 | if (TT.state > 1 && *dlist->data != TT.state) |
| 142 | fdprintf(TT.state == 2 ? 2 : TT.fileout, | 142 | fdprintf(TT.state == 2 ? 2 : TT.fileout, |
| 143 | "%s\n", dlist->data+(TT.state>3 ? 1 : 0)); | 143 | "%s\n", dlist->data + (TT.state > 3 ? 1 : 0)); |
| 144 | 144 | ||
| 145 | if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); | 145 | if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); |
| 146 | 146 | ||
| @@ -221,7 +221,7 @@ static int apply_one_hunk(void) | |||
| 221 | 221 | ||
| 222 | // Match EOF if there aren't as many ending context lines as beginning | 222 | // Match EOF if there aren't as many ending context lines as beginning |
| 223 | for (plist = TT.current_hunk; plist; plist = plist->next) { | 223 | for (plist = TT.current_hunk; plist; plist = plist->next) { |
| 224 | if (plist->data[0]==' ') matcheof++; | 224 | if (plist->data[0] == ' ') matcheof++; |
| 225 | else matcheof = 0; | 225 | else matcheof = 0; |
| 226 | if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); | 226 | if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); |
| 227 | } | 227 | } |
| @@ -433,15 +433,15 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
| 433 | 433 | ||
| 434 | // Are we assembling a hunk? | 434 | // Are we assembling a hunk? |
| 435 | if (state >= 2) { | 435 | if (state >= 2) { |
| 436 | if (*patchline==' ' || *patchline=='+' || *patchline=='-') { | 436 | if (*patchline == ' ' || *patchline == '+' || *patchline == '-') { |
| 437 | dlist_add(&TT.current_hunk, patchline); | 437 | dlist_add(&TT.current_hunk, patchline); |
| 438 | 438 | ||
| 439 | if (*patchline != '+') oldlen--; | 439 | if (*patchline != '+') oldlen--; |
| 440 | if (*patchline != '-') newlen--; | 440 | if (*patchline != '-') newlen--; |
| 441 | 441 | ||
| 442 | // Context line? | 442 | // Context line? |
| 443 | if (*patchline==' ' && state==2) TT.context++; | 443 | if (*patchline == ' ' && state == 2) TT.context++; |
| 444 | else state=3; | 444 | else state = 3; |
| 445 | 445 | ||
| 446 | // If we've consumed all expected hunk lines, apply the hunk. | 446 | // If we've consumed all expected hunk lines, apply the hunk. |
| 447 | 447 | ||
| @@ -469,9 +469,9 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
| 469 | free(*name); | 469 | free(*name); |
| 470 | // Trim date from end of filename (if any). We don't care. | 470 | // Trim date from end of filename (if any). We don't care. |
| 471 | for (s = patchline+4; *s && *s!='\t'; s++) | 471 | for (s = patchline+4; *s && *s!='\t'; s++) |
| 472 | if (*s=='\\' && s[1]) s++; | 472 | if (*s == '\\' && s[1]) s++; |
| 473 | i = atoi(s); | 473 | i = atoi(s); |
| 474 | if (i>1900 && i<=1970) | 474 | if (i > 1900 && i <= 1970) |
| 475 | *name = xstrdup("/dev/null"); | 475 | *name = xstrdup("/dev/null"); |
| 476 | else { | 476 | else { |
| 477 | *s = 0; | 477 | *s = 0; |
diff --git a/editors/patch_toybox.c b/editors/patch_toybox.c index 69a508b2e..5478ece7d 100644 --- a/editors/patch_toybox.c +++ b/editors/patch_toybox.c | |||
| @@ -79,7 +79,7 @@ void TOY_llist_free(void *list, void (*freeit)(void *data)) | |||
| 79 | else free(pop); | 79 | else free(pop); |
| 80 | 80 | ||
| 81 | // End doubly linked list too. | 81 | // End doubly linked list too. |
| 82 | if (list==pop) break; | 82 | if (list == pop) break; |
| 83 | } | 83 | } |
| 84 | } | 84 | } |
| 85 | 85 | ||
| @@ -137,11 +137,11 @@ char *get_rawline(int fd, long *plen, char end) | |||
| 137 | long len = 0; | 137 | long len = 0; |
| 138 | 138 | ||
| 139 | for (;;) { | 139 | for (;;) { |
| 140 | if (1>read(fd, &c, 1)) break; | 140 | if (1 > read(fd, &c, 1)) break; |
| 141 | if (!(len & 63)) buf=xrealloc(buf, len+65); | 141 | if (!(len & 63)) buf=xrealloc(buf, len+65); |
| 142 | if ((buf[len++]=c) == end) break; | 142 | if ((buf[len++] = c) == end) break; |
| 143 | } | 143 | } |
| 144 | if (buf) buf[len]=0; | 144 | if (buf) buf[len] = 0; |
| 145 | if (plen) *plen = len; | 145 | if (plen) *plen = len; |
| 146 | 146 | ||
| 147 | return buf; | 147 | return buf; |
| @@ -153,7 +153,7 @@ char *get_line(int fd) | |||
| 153 | long len; | 153 | long len; |
| 154 | char *buf = get_rawline(fd, &len, '\n'); | 154 | char *buf = get_rawline(fd, &len, '\n'); |
| 155 | 155 | ||
| 156 | if (buf && buf[--len]=='\n') buf[len]=0; | 156 | if (buf && buf[--len] == '\n') buf[len] = 0; |
| 157 | 157 | ||
| 158 | return buf; | 158 | return buf; |
| 159 | } | 159 | } |
| @@ -165,10 +165,10 @@ void xsendfile(int in, int out) | |||
| 165 | long len; | 165 | long len; |
| 166 | char buf[4096]; | 166 | char buf[4096]; |
| 167 | 167 | ||
| 168 | if (in<0) return; | 168 | if (in < 0) return; |
| 169 | for (;;) { | 169 | for (;;) { |
| 170 | len = safe_read(in, buf, 4096); | 170 | len = safe_read(in, buf, 4096); |
| 171 | if (len<1) break; | 171 | if (len < 1) break; |
| 172 | xwrite(out, buf, len); | 172 | xwrite(out, buf, len); |
| 173 | } | 173 | } |
| 174 | } | 174 | } |
| @@ -179,7 +179,7 @@ void replace_tempfile(int fdin, int fdout, char **tempname) | |||
| 179 | { | 179 | { |
| 180 | char *temp = xstrdup(*tempname); | 180 | char *temp = xstrdup(*tempname); |
| 181 | 181 | ||
| 182 | temp[strlen(temp)-6]=0; | 182 | temp[strlen(temp)-6] = 0; |
| 183 | if (fdin != -1) { | 183 | if (fdin != -1) { |
| 184 | xsendfile(fdin, fdout); | 184 | xsendfile(fdin, fdout); |
| 185 | xclose(fdin); | 185 | xclose(fdin); |
| @@ -263,9 +263,9 @@ static void do_line(void *data) | |||
| 263 | { | 263 | { |
| 264 | struct double_list *dlist = (struct double_list *)data; | 264 | struct double_list *dlist = (struct double_list *)data; |
| 265 | 265 | ||
| 266 | if (TT.state>1 && *dlist->data != TT.state) | 266 | if (TT.state > 1 && *dlist->data != TT.state) |
| 267 | fdprintf(TT.state == 2 ? 2 : TT.fileout, | 267 | fdprintf(TT.state == 2 ? 2 : TT.fileout, |
| 268 | "%s\n", dlist->data+(TT.state>3 ? 1 : 0)); | 268 | "%s\n", dlist->data + (TT.state > 3 ? 1 : 0)); |
| 269 | 269 | ||
| 270 | if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); | 270 | if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); |
| 271 | 271 | ||
| @@ -314,7 +314,7 @@ static int apply_one_hunk(void) | |||
| 314 | 314 | ||
| 315 | // Match EOF if there aren't as many ending context lines as beginning | 315 | // Match EOF if there aren't as many ending context lines as beginning |
| 316 | for (plist = TT.current_hunk; plist; plist = plist->next) { | 316 | for (plist = TT.current_hunk; plist; plist = plist->next) { |
| 317 | if (plist->data[0]==' ') matcheof++; | 317 | if (plist->data[0] == ' ') matcheof++; |
| 318 | else matcheof = 0; | 318 | else matcheof = 0; |
| 319 | if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); | 319 | if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); |
| 320 | } | 320 | } |
| @@ -385,7 +385,7 @@ static int apply_one_hunk(void) | |||
| 385 | 385 | ||
| 386 | // If we've reached the end of the buffer without confirming a | 386 | // If we've reached the end of the buffer without confirming a |
| 387 | // match, read more lines. | 387 | // match, read more lines. |
| 388 | if (check==buf) { | 388 | if (check == buf) { |
| 389 | buf = 0; | 389 | buf = 0; |
| 390 | break; | 390 | break; |
| 391 | } | 391 | } |
| @@ -456,15 +456,15 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
| 456 | 456 | ||
| 457 | // Are we assembling a hunk? | 457 | // Are we assembling a hunk? |
| 458 | if (state >= 2) { | 458 | if (state >= 2) { |
| 459 | if (*patchline==' ' || *patchline=='+' || *patchline=='-') { | 459 | if (*patchline == ' ' || *patchline == '+' || *patchline == '-') { |
| 460 | dlist_add(&TT.current_hunk, patchline); | 460 | dlist_add(&TT.current_hunk, patchline); |
| 461 | 461 | ||
| 462 | if (*patchline != '+') TT.oldlen--; | 462 | if (*patchline != '+') TT.oldlen--; |
| 463 | if (*patchline != '-') TT.newlen--; | 463 | if (*patchline != '-') TT.newlen--; |
| 464 | 464 | ||
| 465 | // Context line? | 465 | // Context line? |
| 466 | if (*patchline==' ' && state==2) TT.context++; | 466 | if (*patchline == ' ' && state == 2) TT.context++; |
| 467 | else state=3; | 467 | else state = 3; |
| 468 | 468 | ||
| 469 | // If we've consumed all expected hunk lines, apply the hunk. | 469 | // If we've consumed all expected hunk lines, apply the hunk. |
| 470 | 470 | ||
| @@ -491,9 +491,9 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
| 491 | 491 | ||
| 492 | // Trim date from end of filename (if any). We don't care. | 492 | // Trim date from end of filename (if any). We don't care. |
| 493 | for (s = patchline+4; *s && *s!='\t'; s++) | 493 | for (s = patchline+4; *s && *s!='\t'; s++) |
| 494 | if (*s=='\\' && s[1]) s++; | 494 | if (*s == '\\' && s[1]) s++; |
| 495 | i = atoi(s); | 495 | i = atoi(s); |
| 496 | if (i>1900 && i<=1970) | 496 | if (i > 1900 && i <= 1970) |
| 497 | *name = xstrdup("/dev/null"); | 497 | *name = xstrdup("/dev/null"); |
| 498 | else { | 498 | else { |
| 499 | *s = 0; | 499 | *s = 0; |
| @@ -537,7 +537,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
| 537 | // handle -p path truncation. | 537 | // handle -p path truncation. |
| 538 | for (i=0, s = name; *s;) { | 538 | for (i=0, s = name; *s;) { |
| 539 | if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i) break; | 539 | if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i) break; |
| 540 | if (*(s++)=='/') { | 540 | if (*(s++) == '/') { |
| 541 | name = s; | 541 | name = s; |
| 542 | i++; | 542 | i++; |
| 543 | } | 543 | } |
diff --git a/editors/vi.c b/editors/vi.c index b813747d1..574feb465 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
| @@ -4480,8 +4480,14 @@ static void do_cmd(int c) | |||
| 4480 | goto dc_i; // start inserting | 4480 | goto dc_i; // start inserting |
| 4481 | break; | 4481 | break; |
| 4482 | case 'Z': // Z- if modified, {write}; exit | 4482 | case 'Z': // Z- if modified, {write}; exit |
| 4483 | // ZZ means to save file (if necessary), then exit | ||
| 4484 | c1 = get_one_char(); | 4483 | c1 = get_one_char(); |
| 4484 | // ZQ means to exit without saving | ||
| 4485 | if (c1 == 'Q') { | ||
| 4486 | editing = 0; | ||
| 4487 | optind = cmdline_filecnt; | ||
| 4488 | break; | ||
| 4489 | } | ||
| 4490 | // ZZ means to save file (if necessary), then exit | ||
| 4485 | if (c1 != 'Z') { | 4491 | if (c1 != 'Z') { |
| 4486 | indicate_error(); | 4492 | indicate_error(); |
| 4487 | break; | 4493 | break; |
diff --git a/examples/shutdown-1.0/script/hardshutdown.c b/examples/shutdown-1.0/script/hardshutdown.c index b4af26f0f..c90f55396 100644 --- a/examples/shutdown-1.0/script/hardshutdown.c +++ b/examples/shutdown-1.0/script/hardshutdown.c | |||
| @@ -115,7 +115,7 @@ int main(int argc, char **argv) | |||
| 115 | if (ptr) | 115 | if (ptr) |
| 116 | prog = ptr+1; | 116 | prog = ptr+1; |
| 117 | 117 | ||
| 118 | for (c=1; c < argc; c++) { | 118 | for (c = 1; c < argc; c++) { |
| 119 | if (argv[c][0] >= '0' && argv[c][0] <= '9') { | 119 | if (argv[c][0] >= '0' && argv[c][0] <= '9') { |
| 120 | t.tv_sec = strtol(argv[c], NULL, 10); | 120 | t.tv_sec = strtol(argv[c], NULL, 10); |
| 121 | continue; | 121 | continue; |
| @@ -124,7 +124,7 @@ int main(int argc, char **argv) | |||
| 124 | usage(); | 124 | usage(); |
| 125 | return 1; | 125 | return 1; |
| 126 | } | 126 | } |
| 127 | for (i=1; argv[c][i]; i++) { | 127 | for (i = 1; argv[c][i]; i++) { |
| 128 | switch (argv[c][i]) { | 128 | switch (argv[c][i]) { |
| 129 | case 'h': | 129 | case 'h': |
| 130 | action = HALT; | 130 | action = HALT; |
diff --git a/include/libbb.h b/include/libbb.h index c5691c76d..1b1e5cab1 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
| @@ -1568,6 +1568,7 @@ int ash_main(int argc, char** argv) IF_SHELL_ASH(MAIN_EXTERNALLY_VISIBLE); | |||
| 1568 | int hush_main(int argc, char** argv) IF_SHELL_HUSH(MAIN_EXTERNALLY_VISIBLE); | 1568 | int hush_main(int argc, char** argv) IF_SHELL_HUSH(MAIN_EXTERNALLY_VISIBLE); |
| 1569 | /* If shell needs them, they exist even if not enabled as applets */ | 1569 | /* If shell needs them, they exist even if not enabled as applets */ |
| 1570 | int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); | 1570 | int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); |
| 1571 | int sleep_main(int argc, char **argv) IF_SLEEP(MAIN_EXTERNALLY_VISIBLE); | ||
| 1571 | int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); | 1572 | int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); |
| 1572 | int test_main(int argc, char **argv) | 1573 | int test_main(int argc, char **argv) |
| 1573 | #if ENABLE_TEST || ENABLE_TEST1 || ENABLE_TEST2 | 1574 | #if ENABLE_TEST || ENABLE_TEST1 || ENABLE_TEST2 |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 99f0cb89c..a90d0cdb5 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
| @@ -319,7 +319,6 @@ void lbb_prepare(const char *applet | |||
| 319 | /* Redundant for busybox (run_applet_and_exit covers that case) | 319 | /* Redundant for busybox (run_applet_and_exit covers that case) |
| 320 | * but needed for "individual applet" mode */ | 320 | * but needed for "individual applet" mode */ |
| 321 | if (argv[1] | 321 | if (argv[1] |
| 322 | && !argv[2] | ||
| 323 | && strcmp(argv[1], "--help") == 0 | 322 | && strcmp(argv[1], "--help") == 0 |
| 324 | && !is_prefixed_with(applet, "busybox") | 323 | && !is_prefixed_with(applet, "busybox") |
| 325 | ) { | 324 | ) { |
| @@ -1115,12 +1114,15 @@ void FAST_FUNC show_usage_if_dash_dash_help(int applet_no, char **argv) | |||
| 1115 | # if defined APPLET_NO_echo | 1114 | # if defined APPLET_NO_echo |
| 1116 | && applet_no != APPLET_NO_echo | 1115 | && applet_no != APPLET_NO_echo |
| 1117 | # endif | 1116 | # endif |
| 1117 | # if ENABLE_TEST1 || ENABLE_TEST2 | ||
| 1118 | && argv[0][0] != '[' /* exclude [ --help ] and [[ --help ]] too */ | ||
| 1119 | # endif | ||
| 1118 | # if ENABLE_PLATFORM_MINGW32 && defined APPLET_NO_busybox | 1120 | # if ENABLE_PLATFORM_MINGW32 && defined APPLET_NO_busybox |
| 1119 | && applet_no != APPLET_NO_busybox | 1121 | && applet_no != APPLET_NO_busybox |
| 1120 | # endif | 1122 | # endif |
| 1121 | ) { | 1123 | ) { |
| 1122 | if (argv[1] && !argv[2] && strcmp(argv[1], "--help") == 0) { | 1124 | if (argv[1] && strcmp(argv[1], "--help") == 0) { |
| 1123 | /* Make "foo --help" exit with 0: */ | 1125 | /* Make "foo --help [...]" exit with 0: */ |
| 1124 | xfunc_error_retval = 0; | 1126 | xfunc_error_retval = 0; |
| 1125 | bb_show_usage(); | 1127 | bb_show_usage(); |
| 1126 | } | 1128 | } |
diff --git a/libbb/duration.c b/libbb/duration.c index a6a29ddae..793d02f42 100644 --- a/libbb/duration.c +++ b/libbb/duration.c | |||
| @@ -76,6 +76,12 @@ void FAST_FUNC sleep_for_duration(duration_t duration) | |||
| 76 | ts.tv_sec = duration; | 76 | ts.tv_sec = duration; |
| 77 | ts.tv_nsec = (duration - ts.tv_sec) * 1000000000; | 77 | ts.tv_nsec = (duration - ts.tv_sec) * 1000000000; |
| 78 | } | 78 | } |
| 79 | /* NB: if ENABLE_ASH_SLEEP, we end up here if "sleep N" | ||
| 80 | * is run in ash. ^C will still work, because ash's signal handler | ||
| 81 | * does not return (it longjumps), the below loop | ||
| 82 | * will not continue looping. | ||
| 83 | * (This wouldn't work in hush) | ||
| 84 | */ | ||
| 79 | do { | 85 | do { |
| 80 | errno = 0; | 86 | errno = 0; |
| 81 | nanosleep(&ts, &ts); | 87 | nanosleep(&ts, &ts); |
diff --git a/libbb/hash_md5_sha256_x86-32_shaNI.S b/libbb/hash_md5_sha256_x86-32_shaNI.S index 3905bad9a..a0e4a571a 100644 --- a/libbb/hash_md5_sha256_x86-32_shaNI.S +++ b/libbb/hash_md5_sha256_x86-32_shaNI.S | |||
| @@ -19,6 +19,9 @@ | |||
| 19 | // We do not check SSSE3 in cpuid, | 19 | // We do not check SSSE3 in cpuid, |
| 20 | // all SHA-capable CPUs support it as well. | 20 | // all SHA-capable CPUs support it as well. |
| 21 | 21 | ||
| 22 | #ifdef __linux__ | ||
| 23 | .section .note.GNU-stack, "", @progbits | ||
| 24 | #endif | ||
| 22 | .section .text.sha256_process_block64_shaNI, "ax", @progbits | 25 | .section .text.sha256_process_block64_shaNI, "ax", @progbits |
| 23 | .globl sha256_process_block64_shaNI | 26 | .globl sha256_process_block64_shaNI |
| 24 | .hidden sha256_process_block64_shaNI | 27 | .hidden sha256_process_block64_shaNI |
diff --git a/libbb/hash_md5_sha256_x86-64_shaNI.S b/libbb/hash_md5_sha256_x86-64_shaNI.S index 082ceafe4..172c2eae2 100644 --- a/libbb/hash_md5_sha256_x86-64_shaNI.S +++ b/libbb/hash_md5_sha256_x86-64_shaNI.S | |||
| @@ -19,6 +19,9 @@ | |||
| 19 | // We do not check SSSE3 in cpuid, | 19 | // We do not check SSSE3 in cpuid, |
| 20 | // all SHA-capable CPUs support it as well. | 20 | // all SHA-capable CPUs support it as well. |
| 21 | 21 | ||
| 22 | #ifdef __linux__ | ||
| 23 | .section .note.GNU-stack, "", @progbits | ||
| 24 | #endif | ||
| 22 | .section .text.sha256_process_block64_shaNI, "ax", @progbits | 25 | .section .text.sha256_process_block64_shaNI, "ax", @progbits |
| 23 | .globl sha256_process_block64_shaNI | 26 | .globl sha256_process_block64_shaNI |
| 24 | .hidden sha256_process_block64_shaNI | 27 | .hidden sha256_process_block64_shaNI |
diff --git a/libbb/hash_md5_sha_x86-32_shaNI.S b/libbb/hash_md5_sha_x86-32_shaNI.S index 2366b046a..7455a29f0 100644 --- a/libbb/hash_md5_sha_x86-32_shaNI.S +++ b/libbb/hash_md5_sha_x86-32_shaNI.S | |||
| @@ -25,6 +25,9 @@ | |||
| 25 | // We do not check SSSE3/SSE4.1 in cpuid, | 25 | // We do not check SSSE3/SSE4.1 in cpuid, |
| 26 | // all SHA-capable CPUs support them as well. | 26 | // all SHA-capable CPUs support them as well. |
| 27 | 27 | ||
| 28 | #ifdef __linux__ | ||
| 29 | .section .note.GNU-stack, "", @progbits | ||
| 30 | #endif | ||
| 28 | .section .text.sha1_process_block64_shaNI, "ax", @progbits | 31 | .section .text.sha1_process_block64_shaNI, "ax", @progbits |
| 29 | .globl sha1_process_block64_shaNI | 32 | .globl sha1_process_block64_shaNI |
| 30 | .hidden sha1_process_block64_shaNI | 33 | .hidden sha1_process_block64_shaNI |
diff --git a/libbb/hash_md5_sha_x86-64.S b/libbb/hash_md5_sha_x86-64.S index 1d55b91f8..2cdd22015 100644 --- a/libbb/hash_md5_sha_x86-64.S +++ b/libbb/hash_md5_sha_x86-64.S | |||
| @@ -1,6 +1,9 @@ | |||
| 1 | ### Generated by hash_md5_sha_x86-64.S.sh ### | 1 | ### Generated by hash_md5_sha_x86-64.S.sh ### |
| 2 | 2 | ||
| 3 | #if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__) | 3 | #if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__) |
| 4 | #ifdef __linux__ | ||
| 5 | .section .note.GNU-stack, "", @progbits | ||
| 6 | #endif | ||
| 4 | .section .text.sha1_process_block64, "ax", @progbits | 7 | .section .text.sha1_process_block64, "ax", @progbits |
| 5 | .globl sha1_process_block64 | 8 | .globl sha1_process_block64 |
| 6 | .hidden sha1_process_block64 | 9 | .hidden sha1_process_block64 |
diff --git a/libbb/hash_md5_sha_x86-64.S.sh b/libbb/hash_md5_sha_x86-64.S.sh index 40c979d35..653fe4989 100755 --- a/libbb/hash_md5_sha_x86-64.S.sh +++ b/libbb/hash_md5_sha_x86-64.S.sh | |||
| @@ -127,6 +127,9 @@ echo \ | |||
| 127 | "### Generated by hash_md5_sha_x86-64.S.sh ### | 127 | "### Generated by hash_md5_sha_x86-64.S.sh ### |
| 128 | 128 | ||
| 129 | #if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__) | 129 | #if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__) |
| 130 | #ifdef __linux__ | ||
| 131 | .section .note.GNU-stack, \"\", @progbits | ||
| 132 | #endif | ||
| 130 | .section .text.sha1_process_block64, \"ax\", @progbits | 133 | .section .text.sha1_process_block64, \"ax\", @progbits |
| 131 | .globl sha1_process_block64 | 134 | .globl sha1_process_block64 |
| 132 | .hidden sha1_process_block64 | 135 | .hidden sha1_process_block64 |
diff --git a/libbb/hash_md5_sha_x86-64_shaNI.S b/libbb/hash_md5_sha_x86-64_shaNI.S index 794e97040..2f03e1ce4 100644 --- a/libbb/hash_md5_sha_x86-64_shaNI.S +++ b/libbb/hash_md5_sha_x86-64_shaNI.S | |||
| @@ -25,6 +25,9 @@ | |||
| 25 | // We do not check SSSE3/SSE4.1 in cpuid, | 25 | // We do not check SSSE3/SSE4.1 in cpuid, |
| 26 | // all SHA-capable CPUs support them as well. | 26 | // all SHA-capable CPUs support them as well. |
| 27 | 27 | ||
| 28 | #ifdef __linux__ | ||
| 29 | .section .note.GNU-stack, "", @progbits | ||
| 30 | #endif | ||
| 28 | .section .text.sha1_process_block64_shaNI, "ax", @progbits | 31 | .section .text.sha1_process_block64_shaNI, "ax", @progbits |
| 29 | .globl sha1_process_block64_shaNI | 32 | .globl sha1_process_block64_shaNI |
| 30 | .hidden sha1_process_block64_shaNI | 33 | .hidden sha1_process_block64_shaNI |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 6994d1da7..c5d5808f5 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
| @@ -2154,7 +2154,13 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
| 2154 | case 'W': /* basename of cur dir */ | 2154 | case 'W': /* basename of cur dir */ |
| 2155 | if (!cwd_buf) { | 2155 | if (!cwd_buf) { |
| 2156 | const char *home; | 2156 | const char *home; |
| 2157 | #if ENABLE_SHELL_ASH | ||
| 2158 | cwd_buf = state->sh_get_var | ||
| 2159 | ? xstrdup(state->sh_get_var("PWD")) | ||
| 2160 | : xrealloc_getcwd_or_warn(NULL); | ||
| 2161 | #else | ||
| 2157 | cwd_buf = xrealloc_getcwd_or_warn(NULL); | 2162 | cwd_buf = xrealloc_getcwd_or_warn(NULL); |
| 2163 | #endif | ||
| 2158 | if (!cwd_buf) | 2164 | if (!cwd_buf) |
| 2159 | cwd_buf = (char *)bb_msg_unknown; | 2165 | cwd_buf = (char *)bb_msg_unknown; |
| 2160 | else if ((home = get_homedir_or_NULL()) != NULL && home[0]) { | 2166 | else if ((home = get_homedir_or_NULL()) != NULL && home[0]) { |
diff --git a/miscutils/bc.c b/miscutils/bc.c index fe555d018..01402b311 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
| @@ -2892,6 +2892,8 @@ static char peek_inbuf(void) | |||
| 2892 | ) { | 2892 | ) { |
| 2893 | xc_read_line(&G.input_buffer, G.prs.lex_input_fp); | 2893 | xc_read_line(&G.input_buffer, G.prs.lex_input_fp); |
| 2894 | G.prs.lex_inbuf = G.input_buffer.v; | 2894 | G.prs.lex_inbuf = G.input_buffer.v; |
| 2895 | // lex_next_at may point to now-freed data, update it: | ||
| 2896 | G.prs.lex_next_at = G.prs.lex_inbuf; | ||
| 2895 | if (G.input_buffer.len <= 1) // on EOF, len is 1 (NUL byte) | 2897 | if (G.input_buffer.len <= 1) // on EOF, len is 1 (NUL byte) |
| 2896 | G.prs.lex_input_fp = NULL; | 2898 | G.prs.lex_input_fp = NULL; |
| 2897 | } | 2899 | } |
| @@ -3103,7 +3105,7 @@ static BC_STATUS zbc_lex_identifier(void) | |||
| 3103 | continue; | 3105 | continue; |
| 3104 | match: | 3106 | match: |
| 3105 | // buf starts with keyword bc_lex_kws[i] | 3107 | // buf starts with keyword bc_lex_kws[i] |
| 3106 | if (isalnum(buf[j]) || buf[j]=='_') | 3108 | if (isalnum(buf[j]) || buf[j] == '_') |
| 3107 | continue; // "ifz" does not match "if" keyword, "if." does | 3109 | continue; // "ifz" does not match "if" keyword, "if." does |
| 3108 | p->lex = BC_LEX_KEY_1st_keyword + i; | 3110 | p->lex = BC_LEX_KEY_1st_keyword + i; |
| 3109 | if (!keyword_is_POSIX(i)) { | 3111 | if (!keyword_is_POSIX(i)) { |
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index fb9ebcf60..297693f8c 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c | |||
| @@ -976,7 +976,7 @@ static void action_compat(const struct devfsd_notify_struct *info, unsigned int | |||
| 976 | rewind_ = info->devname[info->namelen - 1]; | 976 | rewind_ = info->devname[info->namelen - 1]; |
| 977 | if (rewind_ != 'n') | 977 | if (rewind_ != 'n') |
| 978 | rewind_ = '\0'; | 978 | rewind_ = '\0'; |
| 979 | mode=0; | 979 | mode = 0; |
| 980 | if (ptr[2] == 'l' /*108*/ || ptr[2] == 'm'/*109*/) | 980 | if (ptr[2] == 'l' /*108*/ || ptr[2] == 'm'/*109*/) |
| 981 | mode = ptr[2] - 107; /* 1 or 2 */ | 981 | mode = ptr[2] - 107; /* 1 or 2 */ |
| 982 | if (ptr[2] == 'a') | 982 | if (ptr[2] == 'a') |
| @@ -1595,11 +1595,11 @@ static char *write_old_sd_name(char *buffer, | |||
| 1595 | return buffer; | 1595 | return buffer; |
| 1596 | } | 1596 | } |
| 1597 | if ((major > 64) && (major < 72)) { | 1597 | if ((major > 64) && (major < 72)) { |
| 1598 | disc_index = ((major - 64) << 4) +(minor >> 4); | 1598 | disc_index = ((major - 64) << 4) + (minor >> 4); |
| 1599 | if (disc_index < 26) | 1599 | if (disc_index < 26) |
| 1600 | sprintf(buffer, "sd%c%s", 'a' + disc_index, part); | 1600 | sprintf(buffer, "sd%c%s", 'a' + disc_index, part); |
| 1601 | else | 1601 | else |
| 1602 | sprintf(buffer, "sd%c%c%s", 'a' +(disc_index / 26) - 1, 'a' + disc_index % 26, part); | 1602 | sprintf(buffer, "sd%c%c%s", 'a' + (disc_index / 26) - 1, 'a' + disc_index % 26, part); |
| 1603 | return buffer; | 1603 | return buffer; |
| 1604 | } | 1604 | } |
| 1605 | return NULL; | 1605 | return NULL; |
diff --git a/miscutils/devmem.c b/miscutils/devmem.c index f9f0276bc..f21621bd6 100644 --- a/miscutils/devmem.c +++ b/miscutils/devmem.c | |||
| @@ -29,7 +29,6 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
| 29 | { | 29 | { |
| 30 | void *map_base, *virt_addr; | 30 | void *map_base, *virt_addr; |
| 31 | uint64_t read_result; | 31 | uint64_t read_result; |
| 32 | uint64_t writeval = writeval; /* for compiler */ | ||
| 33 | off_t target; | 32 | off_t target; |
| 34 | unsigned page_size, mapped_size, offset_in_page; | 33 | unsigned page_size, mapped_size, offset_in_page; |
| 35 | int fd; | 34 | int fd; |
| @@ -64,9 +63,6 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
| 64 | width = strchrnul(bhwl, (argv[2][0] | 0x20)) - bhwl; | 63 | width = strchrnul(bhwl, (argv[2][0] | 0x20)) - bhwl; |
| 65 | width = sizes[width]; | 64 | width = sizes[width]; |
| 66 | } | 65 | } |
| 67 | /* VALUE */ | ||
| 68 | if (argv[3]) | ||
| 69 | writeval = bb_strtoull(argv[3], NULL, 0); | ||
| 70 | } else { /* argv[2] == NULL */ | 66 | } else { /* argv[2] == NULL */ |
| 71 | /* make argv[3] to be a valid thing to fetch */ | 67 | /* make argv[3] to be a valid thing to fetch */ |
| 72 | argv--; | 68 | argv--; |
| @@ -96,28 +92,46 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
| 96 | virt_addr = (char*)map_base + offset_in_page; | 92 | virt_addr = (char*)map_base + offset_in_page; |
| 97 | 93 | ||
| 98 | if (!argv[3]) { | 94 | if (!argv[3]) { |
| 99 | switch (width) { | 95 | #ifdef __SIZEOF_INT128__ |
| 100 | case 8: | 96 | if (width == 128) { |
| 101 | read_result = *(volatile uint8_t*)virt_addr; | 97 | unsigned __int128 rd = |
| 102 | break; | 98 | *(volatile unsigned __int128 *)virt_addr; |
| 103 | case 16: | 99 | printf("0x%016llX%016llX\n", |
| 104 | read_result = *(volatile uint16_t*)virt_addr; | 100 | (unsigned long long)(uint64_t)(rd >> 64), |
| 105 | break; | 101 | (unsigned long long)(uint64_t)rd |
| 106 | case 32: | 102 | ); |
| 107 | read_result = *(volatile uint32_t*)virt_addr; | 103 | } else |
| 108 | break; | 104 | #endif |
| 109 | case 64: | 105 | { |
| 110 | read_result = *(volatile uint64_t*)virt_addr; | 106 | switch (width) { |
| 111 | break; | 107 | case 8: |
| 112 | default: | 108 | read_result = *(volatile uint8_t*)virt_addr; |
| 113 | bb_simple_error_msg_and_die("bad width"); | 109 | break; |
| 110 | case 16: | ||
| 111 | read_result = *(volatile uint16_t*)virt_addr; | ||
| 112 | break; | ||
| 113 | case 32: | ||
| 114 | read_result = *(volatile uint32_t*)virt_addr; | ||
| 115 | break; | ||
| 116 | case 64: | ||
| 117 | read_result = *(volatile uint64_t*)virt_addr; | ||
| 118 | break; | ||
| 119 | default: | ||
| 120 | bb_simple_error_msg_and_die("bad width"); | ||
| 121 | } | ||
| 122 | // printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n", | ||
| 123 | // target, virt_addr, | ||
| 124 | // (unsigned long long)read_result); | ||
| 125 | /* Zero-padded output shows the width of access just done */ | ||
| 126 | printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result); | ||
| 114 | } | 127 | } |
| 115 | // printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n", | ||
| 116 | // target, virt_addr, | ||
| 117 | // (unsigned long long)read_result); | ||
| 118 | /* Zero-padded output shows the width of access just done */ | ||
| 119 | printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result); | ||
| 120 | } else { | 128 | } else { |
| 129 | /* parse VALUE */ | ||
| 130 | #ifdef __SIZEOF_INT128__ | ||
| 131 | unsigned __int128 writeval = strtoumax(argv[3], NULL, 0); | ||
| 132 | #else | ||
| 133 | uint64_t writeval = bb_strtoull(argv[3], NULL, 0); | ||
| 134 | #endif | ||
| 121 | switch (width) { | 135 | switch (width) { |
| 122 | case 8: | 136 | case 8: |
| 123 | *(volatile uint8_t*)virt_addr = writeval; | 137 | *(volatile uint8_t*)virt_addr = writeval; |
| @@ -135,6 +149,12 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) | |||
| 135 | *(volatile uint64_t*)virt_addr = writeval; | 149 | *(volatile uint64_t*)virt_addr = writeval; |
| 136 | // read_result = *(volatile uint64_t*)virt_addr; | 150 | // read_result = *(volatile uint64_t*)virt_addr; |
| 137 | break; | 151 | break; |
| 152 | #ifdef __SIZEOF_INT128__ | ||
| 153 | case 128: | ||
| 154 | *(volatile unsigned __int128 *)virt_addr = writeval; | ||
| 155 | // read_result = *(volatile uint64_t*)virt_addr; | ||
| 156 | break; | ||
| 157 | #endif | ||
| 138 | default: | 158 | default: |
| 139 | bb_simple_error_msg_and_die("bad width"); | 159 | bb_simple_error_msg_and_die("bad width"); |
| 140 | } | 160 | } |
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c index d8d8f6166..83e2f8d53 100644 --- a/miscutils/hdparm.c +++ b/miscutils/hdparm.c | |||
| @@ -798,7 +798,7 @@ static void identify(uint16_t *val) | |||
| 798 | if (!(val[GEN_CONFIG] & NOT_ATA)) { | 798 | if (!(val[GEN_CONFIG] & NOT_ATA)) { |
| 799 | dev = ATA_DEV; | 799 | dev = ATA_DEV; |
| 800 | printf("ATA device, with "); | 800 | printf("ATA device, with "); |
| 801 | } else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) { | 801 | } else if (val[GEN_CONFIG] == CFA_SUPPORT_VAL) { |
| 802 | dev = ATA_DEV; | 802 | dev = ATA_DEV; |
| 803 | like_std = 4; | 803 | like_std = 4; |
| 804 | printf("CompactFlash ATA device, with "); | 804 | printf("CompactFlash ATA device, with "); |
| @@ -819,13 +819,13 @@ static void identify(uint16_t *val) | |||
| 819 | * specific, it should be safe to check it now, even though we don't | 819 | * specific, it should be safe to check it now, even though we don't |
| 820 | * know yet what standard this device is using. | 820 | * know yet what standard this device is using. |
| 821 | */ | 821 | */ |
| 822 | if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL) | 822 | if ((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == STBY_ID_VAL) |
| 823 | || (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL) | 823 | || (val[CONFIG] == PWRD_NID_VAL) || (val[CONFIG] == PWRD_ID_VAL) |
| 824 | ) { | 824 | ) { |
| 825 | like_std = 5; | 825 | like_std = 5; |
| 826 | if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)) | 826 | if ((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == STBY_ID_VAL)) |
| 827 | puts("powers-up in standby; SET FEATURES subcmd spins-up."); | 827 | puts("powers-up in standby; SET FEATURES subcmd spins-up."); |
| 828 | if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE)) | 828 | if (((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE)) |
| 829 | puts("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n"); | 829 | puts("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n"); |
| 830 | } | 830 | } |
| 831 | 831 | ||
| @@ -853,7 +853,7 @@ static void identify(uint16_t *val) | |||
| 853 | printf("\n\tSupported: "); | 853 | printf("\n\tSupported: "); |
| 854 | jj = val[MAJOR] << 1; | 854 | jj = val[MAJOR] << 1; |
| 855 | kk = like_std >4 ? like_std-4: 0; | 855 | kk = like_std >4 ? like_std-4: 0; |
| 856 | for (ii = 14; (ii >0)&&(ii>kk); ii--) { | 856 | for (ii = 14; (ii > 0) && (ii > kk); ii--) { |
| 857 | if (jj & 0x8000) { | 857 | if (jj & 0x8000) { |
| 858 | printf("%u ", ii); | 858 | printf("%u ", ii); |
| 859 | if (like_std < ii) { | 859 | if (like_std < ii) { |
| @@ -943,7 +943,7 @@ static void identify(uint16_t *val) | |||
| 943 | for (ii = 1; ii < 15; ii++) { | 943 | for (ii = 1; ii < 15; ii++) { |
| 944 | if (jj & 0x0001) | 944 | if (jj & 0x0001) |
| 945 | printf("\t%s\n", nth_string(ata1_cfg_str, ii)); | 945 | printf("\t%s\n", nth_string(ata1_cfg_str, ii)); |
| 946 | jj >>=1; | 946 | jj >>= 1; |
| 947 | } | 947 | } |
| 948 | } | 948 | } |
| 949 | if (dev == ATAPI_DEV) { | 949 | if (dev == ATAPI_DEV) { |
| @@ -952,7 +952,7 @@ static void identify(uint16_t *val) | |||
| 952 | else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_INTR_VAL) | 952 | else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_INTR_VAL) |
| 953 | strng = "<=10ms with INTRQ"; | 953 | strng = "<=10ms with INTRQ"; |
| 954 | else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL) | 954 | else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL) |
| 955 | strng ="50us"; | 955 | strng = "50us"; |
| 956 | else | 956 | else |
| 957 | strng = "unknown"; | 957 | strng = "unknown"; |
| 958 | printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */ | 958 | printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */ |
| @@ -1014,7 +1014,7 @@ static void identify(uint16_t *val) | |||
| 1014 | } | 1014 | } |
| 1015 | 1015 | ||
| 1016 | if (!bbbig) | 1016 | if (!bbbig) |
| 1017 | bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */ | 1017 | bbbig = (uint64_t)(ll > mm ? ll : mm); /* # 512 byte blocks */ |
| 1018 | printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11); | 1018 | printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11); |
| 1019 | bbbig = (bbbig << 9) / 1000000; | 1019 | bbbig = (bbbig << 9) / 1000000; |
| 1020 | printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig); | 1020 | printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig); |
| @@ -1160,7 +1160,7 @@ static void identify(uint16_t *val) | |||
| 1160 | jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007; | 1160 | jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007; |
| 1161 | for (ii = 0; ii <= PIO_MODE_MAX; ii++) { | 1161 | for (ii = 0; ii <= PIO_MODE_MAX; ii++) { |
| 1162 | if (jj & 0x0001) printf("pio%d ", ii); | 1162 | if (jj & 0x0001) printf("pio%d ", ii); |
| 1163 | jj >>=1; | 1163 | jj >>= 1; |
| 1164 | } | 1164 | } |
| 1165 | bb_putchar('\n'); | 1165 | bb_putchar('\n'); |
| 1166 | } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) { | 1166 | } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) { |
| @@ -1199,7 +1199,7 @@ static void identify(uint16_t *val) | |||
| 1199 | } | 1199 | } |
| 1200 | if (ii == 31) { | 1200 | if (ii == 31) { |
| 1201 | if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL) | 1201 | if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL) |
| 1202 | ii +=16; | 1202 | ii += 16; |
| 1203 | } | 1203 | } |
| 1204 | } | 1204 | } |
| 1205 | } | 1205 | } |
| @@ -1220,7 +1220,7 @@ static void identify(uint16_t *val) | |||
| 1220 | printf("\t%s\t%s\n", | 1220 | printf("\t%s\t%s\n", |
| 1221 | (!(jj & 0x0001)) ? "not" : "", | 1221 | (!(jj & 0x0001)) ? "not" : "", |
| 1222 | nth_string(secu_str, ii)); | 1222 | nth_string(secu_str, ii)); |
| 1223 | jj >>=1; | 1223 | jj >>= 1; |
| 1224 | } | 1224 | } |
| 1225 | if (val[SECU_STATUS] & SECU_ENABLED) { | 1225 | if (val[SECU_STATUS] & SECU_ENABLED) { |
| 1226 | printf("\tSecurity level %s\n", | 1226 | printf("\tSecurity level %s\n", |
diff --git a/miscutils/tree.c b/miscutils/tree.c new file mode 100644 index 000000000..fa55696c6 --- /dev/null +++ b/miscutils/tree.c | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | /* vi: set sw=4 ts=4: */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2022 Roger Knecht <rknecht@pm.me> | ||
| 4 | * | ||
| 5 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 6 | */ | ||
| 7 | //config:config TREE | ||
| 8 | //config: bool "tree (0.6 kb)" | ||
| 9 | //config: default y | ||
| 10 | //config: help | ||
| 11 | //config: List files and directories in a tree structure. | ||
| 12 | |||
| 13 | //applet:IF_TREE(APPLET(tree, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||
| 14 | |||
| 15 | //kbuild:lib-$(CONFIG_TREE) += tree.o | ||
| 16 | |||
| 17 | //usage:#define tree_trivial_usage NOUSAGE_STR | ||
| 18 | //usage:#define tree_full_usage "" | ||
| 19 | |||
| 20 | #include "libbb.h" | ||
| 21 | #include "common_bufsiz.h" | ||
| 22 | #include "unicode.h" | ||
| 23 | |||
| 24 | #define prefix_buf bb_common_bufsiz1 | ||
| 25 | |||
| 26 | static void tree_print(unsigned count[2], const char* directory_name, char* prefix_pos) | ||
| 27 | { | ||
| 28 | struct dirent **entries; | ||
| 29 | int index, size; | ||
| 30 | const char *bar = "| "; | ||
| 31 | const char *mid = "|-- "; | ||
| 32 | const char *end = "`-- "; | ||
| 33 | |||
| 34 | #if ENABLE_UNICODE_SUPPORT | ||
| 35 | if (unicode_status == UNICODE_ON) { | ||
| 36 | bar = "│ "; | ||
| 37 | mid = "├── "; | ||
| 38 | end = "└── "; | ||
| 39 | } | ||
| 40 | #endif | ||
| 41 | |||
| 42 | // read directory entries | ||
| 43 | size = scandir(directory_name, &entries, NULL, alphasort); | ||
| 44 | |||
| 45 | if (size < 0) { | ||
| 46 | fputs_stdout(directory_name); | ||
| 47 | puts(" [error opening dir]"); | ||
| 48 | return; | ||
| 49 | } | ||
| 50 | |||
| 51 | // print directory name | ||
| 52 | puts(directory_name); | ||
| 53 | |||
| 54 | // switch to sub directory | ||
| 55 | xchdir(directory_name); | ||
| 56 | |||
| 57 | // print all directory entries | ||
| 58 | for (index = 0; index < size;) { | ||
| 59 | struct dirent *dirent = entries[index++]; | ||
| 60 | |||
| 61 | // filter hidden files and directories | ||
| 62 | if (dirent->d_name[0] != '.') { | ||
| 63 | int status; | ||
| 64 | struct stat statBuf; | ||
| 65 | |||
| 66 | //TODO: when -l is implemented, use stat, not lstat, if -l | ||
| 67 | status = lstat(dirent->d_name, &statBuf); | ||
| 68 | |||
| 69 | if (index == size) { | ||
| 70 | strcpy(prefix_pos, end); | ||
| 71 | } else { | ||
| 72 | strcpy(prefix_pos, mid); | ||
| 73 | } | ||
| 74 | fputs_stdout(prefix_buf); | ||
| 75 | |||
| 76 | if (status == 0 && S_ISLNK(statBuf.st_mode)) { | ||
| 77 | // handle symlink | ||
| 78 | char* symlink_path = xmalloc_readlink(dirent->d_name); | ||
| 79 | printf("%s -> %s\n", dirent->d_name, symlink_path); | ||
| 80 | free(symlink_path); | ||
| 81 | count[1]++; | ||
| 82 | } else if (status == 0 && S_ISDIR(statBuf.st_mode) | ||
| 83 | && (prefix_pos - prefix_buf) < (COMMON_BUFSIZE - 16) | ||
| 84 | ) { | ||
| 85 | // handle directory | ||
| 86 | char* pos; | ||
| 87 | if (index == size) { | ||
| 88 | pos = stpcpy(prefix_pos, " "); | ||
| 89 | } else { | ||
| 90 | pos = stpcpy(prefix_pos, bar); | ||
| 91 | } | ||
| 92 | tree_print(count, dirent->d_name, pos); | ||
| 93 | count[0]++; | ||
| 94 | } else { | ||
| 95 | // handle file | ||
| 96 | puts(dirent->d_name); | ||
| 97 | count[1]++; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | // release directory entry | ||
| 102 | free(dirent); | ||
| 103 | } | ||
| 104 | |||
| 105 | // release directory array | ||
| 106 | free(entries); | ||
| 107 | |||
| 108 | // switch to parent directory | ||
| 109 | xchdir(".."); | ||
| 110 | } | ||
| 111 | |||
| 112 | int tree_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
| 113 | int tree_main(int argc UNUSED_PARAM, char **argv) | ||
| 114 | { | ||
| 115 | unsigned count[2] = { 0, 0 }; | ||
| 116 | |||
| 117 | setup_common_bufsiz(); | ||
| 118 | init_unicode(); | ||
| 119 | |||
| 120 | if (!argv[1]) | ||
| 121 | *argv-- = (char*)"."; | ||
| 122 | |||
| 123 | // list directories given as command line arguments | ||
| 124 | while (*(++argv)) | ||
| 125 | tree_print(count, *argv, prefix_buf); | ||
| 126 | |||
| 127 | // print statistic | ||
| 128 | printf("\n%u directories, %u files\n", count[0], count[1]); | ||
| 129 | |||
| 130 | return EXIT_SUCCESS; | ||
| 131 | } | ||
diff --git a/modutils/modutils-24.c b/modutils/modutils-24.c index d0bc2a6ef..37c303f90 100644 --- a/modutils/modutils-24.c +++ b/modutils/modutils-24.c | |||
| @@ -981,7 +981,7 @@ arch_apply_relocation(struct obj_file *f, | |||
| 981 | (loc[1] & 0xFFFF); | 981 | (loc[1] & 0xFFFF); |
| 982 | 982 | ||
| 983 | /* Add reloc offset */ | 983 | /* Add reloc offset */ |
| 984 | temp1+=v; | 984 | temp1 += v; |
| 985 | 985 | ||
| 986 | /* Store back into code */ | 986 | /* Store back into code */ |
| 987 | loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16; | 987 | loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16; |
diff --git a/networking/ping.c b/networking/ping.c index 86d8088de..9805695a1 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
| @@ -74,7 +74,7 @@ | |||
| 74 | //usage: "\n -c CNT Send only CNT pings" | 74 | //usage: "\n -c CNT Send only CNT pings" |
| 75 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" | 75 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" |
| 76 | //usage: "\n -i SECS Interval" | 76 | //usage: "\n -i SECS Interval" |
| 77 | //usage: "\n -A Ping as soon as reply is recevied" | 77 | //usage: "\n -A Ping as soon as reply is received" |
| 78 | //usage: "\n -t TTL Set TTL" | 78 | //usage: "\n -t TTL Set TTL" |
| 79 | //usage: "\n -I IFACE/IP Source interface or IP address" | 79 | //usage: "\n -I IFACE/IP Source interface or IP address" |
| 80 | //usage: "\n -W SEC Seconds to wait for the first response (default 10)" | 80 | //usage: "\n -W SEC Seconds to wait for the first response (default 10)" |
| @@ -91,7 +91,7 @@ | |||
| 91 | //usage: "\n -c CNT Send only CNT pings" | 91 | //usage: "\n -c CNT Send only CNT pings" |
| 92 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" | 92 | //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" |
| 93 | //usage: "\n -i SECS Interval" | 93 | //usage: "\n -i SECS Interval" |
| 94 | //usage: "\n -A Ping as soon as reply is recevied" | 94 | //usage: "\n -A Ping as soon as reply is received" |
| 95 | ///////: "\n -t TTL Set TTL" | 95 | ///////: "\n -t TTL Set TTL" |
| 96 | ///////^^^^^ -t not tested for IPv6, might be not working | 96 | ///////^^^^^ -t not tested for IPv6, might be not working |
| 97 | //usage: "\n -I IFACE/IP Source interface or IP address" | 97 | //usage: "\n -I IFACE/IP Source interface or IP address" |
diff --git a/networking/tc.c b/networking/tc.c index 46ad23d8b..43187f7ee 100644 --- a/networking/tc.c +++ b/networking/tc.c | |||
| @@ -214,7 +214,7 @@ static int prio_print_opt(struct rtattr *opt) | |||
| 214 | return 0; | 214 | return 0; |
| 215 | parse_rtattr_nested_compat(tb, TCA_PRIO_MAX, opt, qopt, sizeof(*qopt)); | 215 | parse_rtattr_nested_compat(tb, TCA_PRIO_MAX, opt, qopt, sizeof(*qopt)); |
| 216 | printf("bands %u priomap ", qopt->bands); | 216 | printf("bands %u priomap ", qopt->bands); |
| 217 | for (i=0; i<=TC_PRIO_MAX; i++) | 217 | for (i = 0; i <= TC_PRIO_MAX; i++) |
| 218 | printf(" %d", qopt->priomap[i]); | 218 | printf(" %d", qopt->priomap[i]); |
| 219 | 219 | ||
| 220 | if (tb[TCA_PRIO_MQ]) | 220 | if (tb[TCA_PRIO_MQ]) |
diff --git a/networking/tls.c b/networking/tls.c index 5f40aec70..9f1dd67ec 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
| @@ -948,11 +948,46 @@ static int tls_has_buffered_record(tls_state_t *tls) | |||
| 948 | 948 | ||
| 949 | static const char *alert_text(int code) | 949 | static const char *alert_text(int code) |
| 950 | { | 950 | { |
| 951 | //10 unexpected_message | ||
| 952 | //20 bad_record_mac | ||
| 953 | //21 decryption_failed | ||
| 954 | //22 record_overflow | ||
| 955 | //30 decompression_failure | ||
| 956 | //40 handshake_failure | ||
| 957 | //41 no_certificate | ||
| 958 | //42 bad_certificate | ||
| 959 | //43 unsupported_certificate | ||
| 960 | //44 certificate_revoked | ||
| 961 | //45 certificate_expired | ||
| 962 | //46 certificate_unknown | ||
| 963 | //47 illegal_parameter | ||
| 964 | //48 unknown_ca | ||
| 965 | //49 access_denied | ||
| 966 | //50 decode_error | ||
| 967 | //51 decrypt_error | ||
| 968 | //52 too_many_cids_requested | ||
| 969 | //60 export_restriction | ||
| 970 | //70 protocol_version | ||
| 971 | //71 insufficient_security | ||
| 972 | //80 internal_error | ||
| 973 | //86 inappropriate_fallback | ||
| 974 | //90 user_canceled | ||
| 975 | //100 no_renegotiation | ||
| 976 | //109 missing_extension | ||
| 977 | //110 unsupported_extension | ||
| 978 | //111 certificate_unobtainable | ||
| 979 | //112 unrecognized_name | ||
| 980 | //113 bad_certificate_status_response | ||
| 981 | //114 bad_certificate_hash_value | ||
| 982 | //115 unknown_psk_identity | ||
| 983 | //116 certificate_required | ||
| 984 | //120 no_application_protocol | ||
| 951 | switch (code) { | 985 | switch (code) { |
| 952 | case 20: return "bad MAC"; | 986 | case 20: return "bad MAC"; |
| 953 | case 50: return "decode error"; | 987 | case 50: return "decode error"; |
| 954 | case 51: return "decrypt error"; | ||
| 955 | case 40: return "handshake failure"; | 988 | case 40: return "handshake failure"; |
| 989 | case 51: return "decrypt error"; | ||
| 990 | case 80: return "internal error"; | ||
| 956 | case 112: return "unrecognized name"; | 991 | case 112: return "unrecognized name"; |
| 957 | } | 992 | } |
| 958 | return itoa(code); | 993 | return itoa(code); |
| @@ -1531,27 +1566,6 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
| 1531 | #endif | 1566 | #endif |
| 1532 | 0x01,0x00, //not a cipher - comprtypes_len, comprtype | 1567 | 0x01,0x00, //not a cipher - comprtypes_len, comprtype |
| 1533 | }; | 1568 | }; |
| 1534 | static const uint8_t supported_groups[] = { | ||
| 1535 | 0x00,0x0a, //extension_type: "supported_groups" | ||
| 1536 | 0x00,2 * (1 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //ext len | ||
| 1537 | 0x00,2 * (0 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //list len | ||
| 1538 | #if ALLOW_CURVE_P256 | ||
| 1539 | 0x00,0x17, //curve_secp256r1 (aka P256, aka prime256v1) | ||
| 1540 | #endif | ||
| 1541 | //0x00,0x18, //curve_secp384r1 | ||
| 1542 | //0x00,0x19, //curve_secp521r1 | ||
| 1543 | #if ALLOW_CURVE_X25519 | ||
| 1544 | 0x00,0x1d, //curve_x25519 (RFC 7748) | ||
| 1545 | #endif | ||
| 1546 | //0x00,0x1e, //curve_x448 (RFC 7748) | ||
| 1547 | }; | ||
| 1548 | //static const uint8_t signature_algorithms[] = { | ||
| 1549 | // 000d | ||
| 1550 | // 0020 | ||
| 1551 | // 001e | ||
| 1552 | // 0601 0602 0603 0501 0502 0503 0401 0402 0403 0301 0302 0303 0201 0202 0203 | ||
| 1553 | //}; | ||
| 1554 | |||
| 1555 | struct client_hello { | 1569 | struct client_hello { |
| 1556 | uint8_t type; | 1570 | uint8_t type; |
| 1557 | uint8_t len24_hi, len24_mid, len24_lo; | 1571 | uint8_t len24_hi, len24_mid, len24_lo; |
| @@ -1563,15 +1577,47 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
| 1563 | uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */ | 1577 | uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */ |
| 1564 | uint8_t comprtypes_len; | 1578 | uint8_t comprtypes_len; |
| 1565 | uint8_t comprtypes[1]; /* actually variable */ | 1579 | uint8_t comprtypes[1]; /* actually variable */ |
| 1566 | /* Extensions (SNI shown): | 1580 | }; |
| 1567 | * hi,lo // len of all extensions | 1581 | // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml |
| 1568 | * 00,00 // extension_type: "Server Name" | 1582 | static const uint8_t extensions[] = { |
| 1569 | * 00,0e // list len (there can be more than one SNI) | 1583 | // is.gd responds with "handshake failure" to our hello if there's no supported_groups |
| 1570 | * 00,0c // len of 1st Server Name Indication | 1584 | 0x00,0x0a, //extension_type: "supported_groups" |
| 1571 | * 00 // name type: host_name | 1585 | 0x00,2 * (1 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //ext len |
| 1572 | * 00,09 // name len | 1586 | 0x00,2 * (0 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //list len |
| 1573 | * "localhost" // name | 1587 | #if ALLOW_CURVE_P256 |
| 1574 | */ | 1588 | 0x00,0x17, //curve_secp256r1 (aka P256, aka prime256v1) |
| 1589 | #endif | ||
| 1590 | //0x00,0x18, //curve_secp384r1 | ||
| 1591 | //0x00,0x19, //curve_secp521r1 | ||
| 1592 | #if ALLOW_CURVE_X25519 | ||
| 1593 | 0x00,0x1d, //curve_x25519 (RFC 7748) | ||
| 1594 | #endif | ||
| 1595 | //0x00,0x1e, //curve_x448 (RFC 7748) | ||
| 1596 | |||
| 1597 | //0x00,0x0b,0x00,0x04,0x03,0x00,0x01,0x02, //extension_type: "ec_point_formats" | ||
| 1598 | //0x00,0x16,0x00,0x00, //extension_type: "encrpypt-then-mac" | ||
| 1599 | //0x00,0x17,0x00,0x00, //extension_type: "extended_master" | ||
| 1600 | //0x00,0x23,0x00,0x00, //extension_type: "session_ticket" | ||
| 1601 | |||
| 1602 | // kojipkgs.fedoraproject.org responds with alert code 80 ("internal error") | ||
| 1603 | // to our hello without signature_algorithms. | ||
| 1604 | // It is satisfied with just 0x04,0x01. | ||
| 1605 | 0x00,0x0d, //extension_type: "signature_algorithms" (RFC5246 section 7.4.1.4.1): | ||
| 1606 | #define SIGALGS (3 + 3 * ENABLE_FEATURE_TLS_SHA1) | ||
| 1607 | 0x00,2 * (1 + SIGALGS), //ext len | ||
| 1608 | 0x00,2 * (0 + SIGALGS), //list len | ||
| 1609 | //Format: two bytes | ||
| 1610 | // byte 1: 0:none,1:md5,2:sha1,3:sha224,4:sha256,5:sha384,6:sha512 | ||
| 1611 | // byte 2: 1:rsa,2:dsa,3:ecdsa | ||
| 1612 | // (note that TLS 1.3 changes this, see RFC8446 section 4.2.3) | ||
| 1613 | #if ENABLE_FEATURE_TLS_SHA1 | ||
| 1614 | 0x02,0x01, //sha1 + rsa | ||
| 1615 | 0x02,0x02, //sha1 + dsa | ||
| 1616 | 0x02,0x03, //sha1 + ecdsa | ||
| 1617 | #endif | ||
| 1618 | 0x04,0x01, //sha256 + rsa - kojipkgs.fedoraproject.org wants this | ||
| 1619 | 0x04,0x02, //sha256 + dsa | ||
| 1620 | 0x04,0x03, //sha256 + ecdsa | ||
| 1575 | // GNU Wget 1.18 to cdn.kernel.org sends these extensions: | 1621 | // GNU Wget 1.18 to cdn.kernel.org sends these extensions: |
| 1576 | // 0055 | 1622 | // 0055 |
| 1577 | // 0005 0005 0100000000 - status_request | 1623 | // 0005 0005 0100000000 - status_request |
| @@ -1591,8 +1637,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
| 1591 | int sni_len = sni ? strnlen(sni, 127 - 5) : 0; | 1637 | int sni_len = sni ? strnlen(sni, 127 - 5) : 0; |
| 1592 | 1638 | ||
| 1593 | ext_len = 0; | 1639 | ext_len = 0; |
| 1594 | /* is.gd responds with "handshake failure" to our hello if there's no supported_groups element */ | 1640 | ext_len += sizeof(extensions); |
| 1595 | ext_len += sizeof(supported_groups); | ||
| 1596 | if (sni_len) | 1641 | if (sni_len) |
| 1597 | ext_len += 9 + sni_len; | 1642 | ext_len += 9 + sni_len; |
| 1598 | 1643 | ||
| @@ -1626,7 +1671,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
| 1626 | ptr[8] = sni_len; //name len | 1671 | ptr[8] = sni_len; //name len |
| 1627 | ptr = mempcpy(&ptr[9], sni, sni_len); | 1672 | ptr = mempcpy(&ptr[9], sni, sni_len); |
| 1628 | } | 1673 | } |
| 1629 | memcpy(ptr, supported_groups, sizeof(supported_groups)); | 1674 | memcpy(ptr, extensions, sizeof(extensions)); |
| 1630 | 1675 | ||
| 1631 | tls->hsd = xzalloc(sizeof(*tls->hsd)); | 1676 | tls->hsd = xzalloc(sizeof(*tls->hsd)); |
| 1632 | /* HANDSHAKE HASH: ^^^ + len if need to save saved_client_hello */ | 1677 | /* HANDSHAKE HASH: ^^^ + len if need to save saved_client_hello */ |
diff --git a/networking/tls_sp_c32.c b/networking/tls_sp_c32.c index 292dda24e..a593c5c40 100644 --- a/networking/tls_sp_c32.c +++ b/networking/tls_sp_c32.c | |||
| @@ -68,9 +68,6 @@ static const sp_digit p256_mod[8] ALIGNED(8) = { | |||
| 68 | 68 | ||
| 69 | #define p256_mp_mod ((sp_digit)0x000001) | 69 | #define p256_mp_mod ((sp_digit)0x000001) |
| 70 | 70 | ||
| 71 | /* Normalize the values in each word to 32 bits - NOP */ | ||
| 72 | #define sp_256_norm_8(a) ((void)0) | ||
| 73 | |||
| 74 | /* Write r as big endian to byte array. | 71 | /* Write r as big endian to byte array. |
| 75 | * Fixed length number of bytes written: 32 | 72 | * Fixed length number of bytes written: 32 |
| 76 | * | 73 | * |
| @@ -83,8 +80,6 @@ static void sp_256_to_bin_8(const sp_digit* rr, uint8_t* a) | |||
| 83 | int i; | 80 | int i; |
| 84 | const uint64_t* r = (void*)rr; | 81 | const uint64_t* r = (void*)rr; |
| 85 | 82 | ||
| 86 | sp_256_norm_8(rr); | ||
| 87 | |||
| 88 | r += 4; | 83 | r += 4; |
| 89 | for (i = 0; i < 4; i++) { | 84 | for (i = 0; i < 4; i++) { |
| 90 | r--; | 85 | r--; |
| @@ -97,8 +92,6 @@ static void sp_256_to_bin_8(const sp_digit* r, uint8_t* a) | |||
| 97 | { | 92 | { |
| 98 | int i; | 93 | int i; |
| 99 | 94 | ||
| 100 | sp_256_norm_8(r); | ||
| 101 | |||
| 102 | r += 8; | 95 | r += 8; |
| 103 | for (i = 0; i < 8; i++) { | 96 | for (i = 0; i < 8; i++) { |
| 104 | r--; | 97 | r--; |
| @@ -641,7 +634,6 @@ static void sp_256_div2_8(sp_digit* r /*, const sp_digit* m*/) | |||
| 641 | int carry = 0; | 634 | int carry = 0; |
| 642 | if (r[0] & 1) | 635 | if (r[0] & 1) |
| 643 | carry = sp_256_add_8(r, r, m); | 636 | carry = sp_256_add_8(r, r, m); |
| 644 | sp_256_norm_8(r); | ||
| 645 | sp_256_rshift1_8(r, carry); | 637 | sp_256_rshift1_8(r, carry); |
| 646 | } | 638 | } |
| 647 | 639 | ||
| @@ -652,10 +644,8 @@ static void sp_256_mont_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b | |||
| 652 | // const sp_digit* m = p256_mod; | 644 | // const sp_digit* m = p256_mod; |
| 653 | 645 | ||
| 654 | int carry = sp_256_add_8(r, a, b); | 646 | int carry = sp_256_add_8(r, a, b); |
| 655 | sp_256_norm_8(r); | ||
| 656 | if (carry) { | 647 | if (carry) { |
| 657 | sp_256_sub_8_p256_mod(r); | 648 | sp_256_sub_8_p256_mod(r); |
| 658 | sp_256_norm_8(r); | ||
| 659 | } | 649 | } |
| 660 | } | 650 | } |
| 661 | 651 | ||
| @@ -667,10 +657,8 @@ static void sp_256_mont_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b | |||
| 667 | 657 | ||
| 668 | int borrow; | 658 | int borrow; |
| 669 | borrow = sp_256_sub_8(r, a, b); | 659 | borrow = sp_256_sub_8(r, a, b); |
| 670 | sp_256_norm_8(r); | ||
| 671 | if (borrow) { | 660 | if (borrow) { |
| 672 | sp_256_add_8(r, r, m); | 661 | sp_256_add_8(r, r, m); |
| 673 | sp_256_norm_8(r); | ||
| 674 | } | 662 | } |
| 675 | } | 663 | } |
| 676 | 664 | ||
| @@ -680,10 +668,8 @@ static void sp_256_mont_dbl_8(sp_digit* r, const sp_digit* a /*, const sp_digit* | |||
| 680 | // const sp_digit* m = p256_mod; | 668 | // const sp_digit* m = p256_mod; |
| 681 | 669 | ||
| 682 | int carry = sp_256_add_8(r, a, a); | 670 | int carry = sp_256_add_8(r, a, a); |
| 683 | sp_256_norm_8(r); | ||
| 684 | if (carry) | 671 | if (carry) |
| 685 | sp_256_sub_8_p256_mod(r); | 672 | sp_256_sub_8_p256_mod(r); |
| 686 | sp_256_norm_8(r); | ||
| 687 | } | 673 | } |
| 688 | 674 | ||
| 689 | /* Triple a Montgomery form number (r = a + a + a % m) */ | 675 | /* Triple a Montgomery form number (r = a + a + a % m) */ |
| @@ -692,16 +678,12 @@ static void sp_256_mont_tpl_8(sp_digit* r, const sp_digit* a /*, const sp_digit* | |||
| 692 | // const sp_digit* m = p256_mod; | 678 | // const sp_digit* m = p256_mod; |
| 693 | 679 | ||
| 694 | int carry = sp_256_add_8(r, a, a); | 680 | int carry = sp_256_add_8(r, a, a); |
| 695 | sp_256_norm_8(r); | ||
| 696 | if (carry) { | 681 | if (carry) { |
| 697 | sp_256_sub_8_p256_mod(r); | 682 | sp_256_sub_8_p256_mod(r); |
| 698 | sp_256_norm_8(r); | ||
| 699 | } | 683 | } |
| 700 | carry = sp_256_add_8(r, r, a); | 684 | carry = sp_256_add_8(r, r, a); |
| 701 | sp_256_norm_8(r); | ||
| 702 | if (carry) { | 685 | if (carry) { |
| 703 | sp_256_sub_8_p256_mod(r); | 686 | sp_256_sub_8_p256_mod(r); |
| 704 | sp_256_norm_8(r); | ||
| 705 | } | 687 | } |
| 706 | } | 688 | } |
| 707 | 689 | ||
| @@ -844,7 +826,6 @@ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* aa/*, const sp_digi | |||
| 844 | sp_512to256_mont_shift_8(r, aa); | 826 | sp_512to256_mont_shift_8(r, aa); |
| 845 | if (carry != 0) | 827 | if (carry != 0) |
| 846 | sp_256_sub_8_p256_mod(r); | 828 | sp_256_sub_8_p256_mod(r); |
| 847 | sp_256_norm_8(r); | ||
| 848 | } | 829 | } |
| 849 | 830 | ||
| 850 | #else /* Generic 32-bit version */ | 831 | #else /* Generic 32-bit version */ |
| @@ -1003,8 +984,6 @@ static int sp_256_mul_add_8(sp_digit* r /*, const sp_digit* a, sp_digit b*/) | |||
| 1003 | * [In our case, it is (p256_mp_mod * a[1]) << 32.] | 984 | * [In our case, it is (p256_mp_mod * a[1]) << 32.] |
| 1004 | * And so on. Eventually T is divisible by R, and after division by R | 985 | * And so on. Eventually T is divisible by R, and after division by R |
| 1005 | * the algorithm is in the same place as the usual Montgomery reduction. | 986 | * the algorithm is in the same place as the usual Montgomery reduction. |
| 1006 | * | ||
| 1007 | * TODO: Can conditionally use 64-bit (if bit-little-endian arch) logic? | ||
| 1008 | */ | 987 | */ |
| 1009 | static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit* m, sp_digit mp*/) | 988 | static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit* m, sp_digit mp*/) |
| 1010 | { | 989 | { |
| @@ -1032,7 +1011,6 @@ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit | |||
| 1032 | sp_512to256_mont_shift_8(r, a); | 1011 | sp_512to256_mont_shift_8(r, a); |
| 1033 | if (word16th != 0) | 1012 | if (word16th != 0) |
| 1034 | sp_256_sub_8_p256_mod(r); | 1013 | sp_256_sub_8_p256_mod(r); |
| 1035 | sp_256_norm_8(r); | ||
| 1036 | } | 1014 | } |
| 1037 | else { /* Same code for explicit mp == 1 (which is always the case for P256) */ | 1015 | else { /* Same code for explicit mp == 1 (which is always the case for P256) */ |
| 1038 | sp_digit word16th = 0; | 1016 | sp_digit word16th = 0; |
| @@ -1052,7 +1030,6 @@ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit | |||
| 1052 | sp_512to256_mont_shift_8(r, a); | 1030 | sp_512to256_mont_shift_8(r, a); |
| 1053 | if (word16th != 0) | 1031 | if (word16th != 0) |
| 1054 | sp_256_sub_8_p256_mod(r); | 1032 | sp_256_sub_8_p256_mod(r); |
| 1055 | sp_256_norm_8(r); | ||
| 1056 | } | 1033 | } |
| 1057 | } | 1034 | } |
| 1058 | #endif | 1035 | #endif |
| @@ -1208,14 +1185,12 @@ static void sp_256_map_8(sp_point* r, sp_point* p) | |||
| 1208 | /* Reduce x to less than modulus */ | 1185 | /* Reduce x to less than modulus */ |
| 1209 | if (sp_256_cmp_8(r->x, p256_mod) >= 0) | 1186 | if (sp_256_cmp_8(r->x, p256_mod) >= 0) |
| 1210 | sp_256_sub_8_p256_mod(r->x); | 1187 | sp_256_sub_8_p256_mod(r->x); |
| 1211 | sp_256_norm_8(r->x); | ||
| 1212 | 1188 | ||
| 1213 | /* y /= z^3 */ | 1189 | /* y /= z^3 */ |
| 1214 | sp_256_mont_mul_and_reduce_8(r->y, p->y, t1 /*, p256_mod, p256_mp_mod*/); | 1190 | sp_256_mont_mul_and_reduce_8(r->y, p->y, t1 /*, p256_mod, p256_mp_mod*/); |
| 1215 | /* Reduce y to less than modulus */ | 1191 | /* Reduce y to less than modulus */ |
| 1216 | if (sp_256_cmp_8(r->y, p256_mod) >= 0) | 1192 | if (sp_256_cmp_8(r->y, p256_mod) >= 0) |
| 1217 | sp_256_sub_8_p256_mod(r->y); | 1193 | sp_256_sub_8_p256_mod(r->y); |
| 1218 | sp_256_norm_8(r->y); | ||
| 1219 | 1194 | ||
| 1220 | memset(r->z, 0, sizeof(r->z)); | 1195 | memset(r->z, 0, sizeof(r->z)); |
| 1221 | r->z[0] = 1; | 1196 | r->z[0] = 1; |
| @@ -1300,7 +1275,6 @@ static NOINLINE void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point* | |||
| 1300 | 1275 | ||
| 1301 | /* Check double */ | 1276 | /* Check double */ |
| 1302 | sp_256_sub_8(t1, p256_mod, q->y); | 1277 | sp_256_sub_8(t1, p256_mod, q->y); |
| 1303 | sp_256_norm_8(t1); | ||
| 1304 | if (sp_256_cmp_equal_8(p->x, q->x) | 1278 | if (sp_256_cmp_equal_8(p->x, q->x) |
| 1305 | && sp_256_cmp_equal_8(p->z, q->z) | 1279 | && sp_256_cmp_equal_8(p->z, q->z) |
| 1306 | && (sp_256_cmp_equal_8(p->y, q->y) || sp_256_cmp_equal_8(p->y, t1)) | 1280 | && (sp_256_cmp_equal_8(p->y, q->y) || sp_256_cmp_equal_8(p->y, t1)) |
| @@ -1422,14 +1396,15 @@ static void sp_256_ecc_mulmod_8(sp_point* r, const sp_point* g, const sp_digit* | |||
| 1422 | static void sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k /*, int map*/) | 1396 | static void sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k /*, int map*/) |
| 1423 | { | 1397 | { |
| 1424 | /* Since this function is called only once, save space: | 1398 | /* Since this function is called only once, save space: |
| 1425 | * don't have "static const sp_point p256_base = {...}", | 1399 | * don't have "static const sp_point p256_base = {...}". |
| 1426 | * it would have more zeros than data. | ||
| 1427 | */ | 1400 | */ |
| 1428 | static const uint8_t p256_base_bin[] = { | 1401 | static const uint8_t p256_base_bin[] = { |
| 1429 | /* x (big-endian) */ | 1402 | /* x (big-endian) */ |
| 1430 | 0x6b,0x17,0xd1,0xf2,0xe1,0x2c,0x42,0x47,0xf8,0xbc,0xe6,0xe5,0x63,0xa4,0x40,0xf2,0x77,0x03,0x7d,0x81,0x2d,0xeb,0x33,0xa0,0xf4,0xa1,0x39,0x45,0xd8,0x98,0xc2,0x96, | 1403 | 0x6b,0x17,0xd1,0xf2,0xe1,0x2c,0x42,0x47,0xf8,0xbc,0xe6,0xe5,0x63,0xa4,0x40,0xf2, |
| 1404 | 0x77,0x03,0x7d,0x81,0x2d,0xeb,0x33,0xa0,0xf4,0xa1,0x39,0x45,0xd8,0x98,0xc2,0x96, | ||
| 1431 | /* y */ | 1405 | /* y */ |
| 1432 | 0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7,0xeb,0x4a,0x7c,0x0f,0x9e,0x16,0x2b,0xce,0x33,0x57,0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf,0x51,0xf5, | 1406 | 0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7,0xeb,0x4a,0x7c,0x0f,0x9e,0x16, |
| 1407 | 0x2b,0xce,0x33,0x57,0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf,0x51,0xf5, | ||
| 1433 | /* z will be set to 1, infinity flag to "false" */ | 1408 | /* z will be set to 1, infinity flag to "false" */ |
| 1434 | }; | 1409 | }; |
| 1435 | sp_point p256_base; | 1410 | sp_point p256_base; |
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 9fc690315..c7f130a70 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
| @@ -295,6 +295,7 @@ static void option_to_env(const uint8_t *option, const uint8_t *option_end) | |||
| 295 | *new_env() = xasprintf("ipv6=%s", ipv6str); | 295 | *new_env() = xasprintf("ipv6=%s", ipv6str); |
| 296 | 296 | ||
| 297 | move_from_unaligned32(v32, option + 4 + 16 + 4); | 297 | move_from_unaligned32(v32, option + 4 + 16 + 4); |
| 298 | v32 = ntohl(v32); | ||
| 298 | *new_env() = xasprintf("lease=%u", (unsigned)v32); | 299 | *new_env() = xasprintf("lease=%u", (unsigned)v32); |
| 299 | break; | 300 | break; |
| 300 | 301 | ||
| @@ -332,6 +333,7 @@ static void option_to_env(const uint8_t *option, const uint8_t *option_end) | |||
| 332 | * +-+-+-+-+-+-+-+-+ | 333 | * +-+-+-+-+-+-+-+-+ |
| 333 | */ | 334 | */ |
| 334 | move_from_unaligned32(v32, option + 4 + 4); | 335 | move_from_unaligned32(v32, option + 4 + 4); |
| 336 | v32 = ntohl(v32); | ||
| 335 | *new_env() = xasprintf("ipv6prefix_lease=%u", (unsigned)v32); | 337 | *new_env() = xasprintf("ipv6prefix_lease=%u", (unsigned)v32); |
| 336 | 338 | ||
| 337 | sprint_nip6(ipv6str, option + 4 + 4 + 4 + 1); | 339 | sprint_nip6(ipv6str, option + 4 + 4 + 4 + 1); |
| @@ -842,7 +844,7 @@ static NOINLINE int send_d6_renew(struct in6_addr *server_ipv6, struct in6_addr | |||
| 842 | uint8_t *opt_ptr; | 844 | uint8_t *opt_ptr; |
| 843 | 845 | ||
| 844 | /* Fill in: msg type, xid, ELAPSED_TIME */ | 846 | /* Fill in: msg type, xid, ELAPSED_TIME */ |
| 845 | opt_ptr = init_d6_packet(&packet, DHCPREQUEST); | 847 | opt_ptr = init_d6_packet(&packet, D6_MSG_RENEW); |
| 846 | 848 | ||
| 847 | /* server id */ | 849 | /* server id */ |
| 848 | opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); | 850 | opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); |
| @@ -1081,7 +1083,7 @@ static void change_listen_mode(int new_mode) | |||
| 1081 | client_data.sockfd = -1; | 1083 | client_data.sockfd = -1; |
| 1082 | } | 1084 | } |
| 1083 | if (new_mode == LISTEN_KERNEL) | 1085 | if (new_mode == LISTEN_KERNEL) |
| 1084 | client_data.sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT6, client_data.interface); | 1086 | client_data.sockfd = d6_listen_socket(CLIENT_PORT6, client_data.interface); |
| 1085 | else if (new_mode != LISTEN_NONE) | 1087 | else if (new_mode != LISTEN_NONE) |
| 1086 | client_data.sockfd = d6_raw_socket(client_data.ifindex); | 1088 | client_data.sockfd = d6_raw_socket(client_data.ifindex); |
| 1087 | /* else LISTEN_NONE: client_data.sockfd stays closed */ | 1089 | /* else LISTEN_NONE: client_data.sockfd stays closed */ |
| @@ -1487,6 +1489,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
| 1487 | if (opt & OPT_l) | 1489 | if (opt & OPT_l) |
| 1488 | send_d6_info_request(); | 1490 | send_d6_info_request(); |
| 1489 | else /* send a broadcast renew request */ | 1491 | else /* send a broadcast renew request */ |
| 1492 | //TODO: send_d6_renew uses D6_MSG_RENEW message, should we use D6_MSG_REBIND here instead? | ||
| 1490 | send_d6_renew(/*server_ipv6:*/ NULL, requested_ipv6); | 1493 | send_d6_renew(/*server_ipv6:*/ NULL, requested_ipv6); |
| 1491 | timeout = discover_timeout; | 1494 | timeout = discover_timeout; |
| 1492 | packet_num++; | 1495 | packet_num++; |
diff --git a/networking/udhcp/d6_socket.c b/networking/udhcp/d6_socket.c index 8ddee5a8e..21cf61c6e 100644 --- a/networking/udhcp/d6_socket.c +++ b/networking/udhcp/d6_socket.c | |||
| @@ -110,7 +110,7 @@ int FAST_FUNC d6_listen_socket(int port, const char *inf) | |||
| 110 | int fd; | 110 | int fd; |
| 111 | struct sockaddr_in6 addr; | 111 | struct sockaddr_in6 addr; |
| 112 | 112 | ||
| 113 | log1("opening listen socket on *:%d %s", port, inf); | 113 | log2("opening listen socket on *:%d %s", port, inf); |
| 114 | fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); | 114 | fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); |
| 115 | 115 | ||
| 116 | setsockopt_reuseaddr(fd); | 116 | setsockopt_reuseaddr(fd); |
diff --git a/procps/nmeter.c b/procps/nmeter.c index 088d366bf..68e6f3325 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c | |||
| @@ -515,7 +515,7 @@ static void FAST_FUNC collect_blk(blk_stat *s) | |||
| 515 | return; | 515 | return; |
| 516 | } | 516 | } |
| 517 | 517 | ||
| 518 | for (i=0; i<2; i++) { | 518 | for (i = 0; i < 2; i++) { |
| 519 | ullong old = s->old[i]; | 519 | ullong old = s->old[i]; |
| 520 | if (data[i] < old) old = data[i]; //sanitize | 520 | if (data[i] < old) old = data[i]; //sanitize |
| 521 | s->old[i] = data[i]; | 521 | s->old[i] = data[i]; |
| @@ -597,7 +597,7 @@ static void FAST_FUNC collect_if(if_stat *s) | |||
| 597 | return; | 597 | return; |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | for (i=0; i<4; i++) { | 600 | for (i = 0; i < 4; i++) { |
| 601 | ullong old = s->old[i]; | 601 | ullong old = s->old[i]; |
| 602 | if (data[i] < old) old = data[i]; //sanitize | 602 | if (data[i] < old) old = data[i]; //sanitize |
| 603 | s->old[i] = data[i]; | 603 | s->old[i] = data[i]; |
diff --git a/shell/ash.c b/shell/ash.c index 28c7fe2db..8497538b1 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -149,6 +149,11 @@ | |||
| 149 | //config: default y | 149 | //config: default y |
| 150 | //config: depends on SHELL_ASH | 150 | //config: depends on SHELL_ASH |
| 151 | //config: | 151 | //config: |
| 152 | //config:config ASH_SLEEP | ||
| 153 | //config: bool "sleep builtin" | ||
| 154 | //config: default y | ||
| 155 | //config: depends on SHELL_ASH | ||
| 156 | //config: | ||
| 152 | //config:config ASH_HELP | 157 | //config:config ASH_HELP |
| 153 | //config: bool "help builtin" | 158 | //config: bool "help builtin" |
| 154 | //config: default y | 159 | //config: default y |
| @@ -7702,6 +7707,7 @@ varunset(const char *end, const char *var, const char *umsg, int varflags) | |||
| 7702 | msg = umsg; | 7707 | msg = umsg; |
| 7703 | } | 7708 | } |
| 7704 | } | 7709 | } |
| 7710 | ifsfree(); | ||
| 7705 | ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail); | 7711 | ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail); |
| 7706 | } | 7712 | } |
| 7707 | 7713 | ||
| @@ -7997,13 +8003,15 @@ subevalvar(char *start, char *str, int strloc, | |||
| 7997 | if (idx >= end) | 8003 | if (idx >= end) |
| 7998 | break; | 8004 | break; |
| 7999 | STPUTC(*idx, expdest); | 8005 | STPUTC(*idx, expdest); |
| 8006 | if (stackblock() != restart_detect) | ||
| 8007 | goto restart; | ||
| 8000 | if (quotes && (unsigned char)*idx == CTLESC) { | 8008 | if (quotes && (unsigned char)*idx == CTLESC) { |
| 8001 | idx++; | 8009 | idx++; |
| 8002 | len++; | 8010 | len++; |
| 8003 | STPUTC(*idx, expdest); | 8011 | STPUTC(*idx, expdest); |
| 8012 | if (stackblock() != restart_detect) | ||
| 8013 | goto restart; | ||
| 8004 | } | 8014 | } |
| 8005 | if (stackblock() != restart_detect) | ||
| 8006 | goto restart; | ||
| 8007 | idx++; | 8015 | idx++; |
| 8008 | len++; | 8016 | len++; |
| 8009 | rmesc++; | 8017 | rmesc++; |
| @@ -8028,6 +8036,13 @@ subevalvar(char *start, char *str, int strloc, | |||
| 8028 | idx = loc; | 8036 | idx = loc; |
| 8029 | } | 8037 | } |
| 8030 | 8038 | ||
| 8039 | /* The STPUTC invocations above may resize and move the | ||
| 8040 | * stack via realloc(3). Since repl is a pointer into the | ||
| 8041 | * stack, we need to reconstruct it relative to stackblock(). | ||
| 8042 | */ | ||
| 8043 | if (slash_pos >= 0) | ||
| 8044 | repl = (char *)stackblock() + strloc + slash_pos + 1; | ||
| 8045 | |||
| 8031 | //bb_error_msg("repl:'%s'", repl); | 8046 | //bb_error_msg("repl:'%s'", repl); |
| 8032 | for (loc = (char*)repl; *loc; loc++) { | 8047 | for (loc = (char*)repl; *loc; loc++) { |
| 8033 | char *restart_detect = stackblock(); | 8048 | char *restart_detect = stackblock(); |
| @@ -8127,6 +8142,7 @@ varvalue(char *name, int varflags, int flags, int quoted) | |||
| 8127 | if (discard) | 8142 | if (discard) |
| 8128 | return -1; | 8143 | return -1; |
| 8129 | 8144 | ||
| 8145 | ifsfree(); | ||
| 8130 | raise_error_syntax("bad substitution"); | 8146 | raise_error_syntax("bad substitution"); |
| 8131 | } | 8147 | } |
| 8132 | 8148 | ||
| @@ -11039,6 +11055,9 @@ static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, | |||
| 11039 | #if ENABLE_ASH_TEST || BASH_TEST2 | 11055 | #if ENABLE_ASH_TEST || BASH_TEST2 |
| 11040 | static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } | 11056 | static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } |
| 11041 | #endif | 11057 | #endif |
| 11058 | #if ENABLE_ASH_SLEEP | ||
| 11059 | static int FAST_FUNC sleepcmd(int argc, char **argv) { return sleep_main(argc, argv); } | ||
| 11060 | #endif | ||
| 11042 | 11061 | ||
| 11043 | /* Keep these in proper order since it is searched via bsearch() */ | 11062 | /* Keep these in proper order since it is searched via bsearch() */ |
| 11044 | static const struct builtincmd builtintab[] = { | 11063 | static const struct builtincmd builtintab[] = { |
| @@ -11101,6 +11120,9 @@ static const struct builtincmd builtintab[] = { | |||
| 11101 | { BUILTIN_SPEC_REG "return" , returncmd }, | 11120 | { BUILTIN_SPEC_REG "return" , returncmd }, |
| 11102 | { BUILTIN_SPEC_REG "set" , setcmd }, | 11121 | { BUILTIN_SPEC_REG "set" , setcmd }, |
| 11103 | { BUILTIN_SPEC_REG "shift" , shiftcmd }, | 11122 | { BUILTIN_SPEC_REG "shift" , shiftcmd }, |
| 11123 | #if ENABLE_ASH_SLEEP | ||
| 11124 | { BUILTIN_REGULAR "sleep" , sleepcmd }, | ||
| 11125 | #endif | ||
| 11104 | #if BASH_SOURCE | 11126 | #if BASH_SOURCE |
| 11105 | { BUILTIN_SPEC_REG "source" , dotcmd }, | 11127 | { BUILTIN_SPEC_REG "source" , dotcmd }, |
| 11106 | #endif | 11128 | #endif |
diff --git a/shell/ash_test/ash-heredoc/heredoc_and_cmd.right b/shell/ash_test/ash-heredoc/heredoc_and_cmd.right new file mode 100644 index 000000000..25ae70561 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_and_cmd.right | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | ./heredoc_and_cmd.tests: line 4: D: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||
| 2 | Y | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests b/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests new file mode 100755 index 000000000..197542de7 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | # The bug was only happening with <<REDIR;CMD form below: | ||
| 2 | M='AAAAAAAAAAAAAAAAA' | ||
| 3 | fff(){ | ||
| 4 | date <<000; echo Y | ||
| 5 | ${D?$M$M$M$M$M$M} | ||
| 6 | 000 | ||
| 7 | } | ||
| 8 | fff | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_and_cmd.right b/shell/hush_test/hush-heredoc/heredoc_and_cmd.right new file mode 100644 index 000000000..5c19a0621 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_and_cmd.right | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | hush: D: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||
| 2 | Y | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_and_cmd.tests b/shell/hush_test/hush-heredoc/heredoc_and_cmd.tests new file mode 100755 index 000000000..197542de7 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_and_cmd.tests | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | # The bug was only happening with <<REDIR;CMD form below: | ||
| 2 | M='AAAAAAAAAAAAAAAAA' | ||
| 3 | fff(){ | ||
| 4 | date <<000; echo Y | ||
| 5 | ${D?$M$M$M$M$M$M} | ||
| 6 | 000 | ||
| 7 | } | ||
| 8 | fff | ||
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 93e25d8c1..bbf0fbff1 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
| @@ -479,4 +479,10 @@ testing 'awk backslash+newline eaten with no trace' \ | |||
| 479 | "Hello world\n" \ | 479 | "Hello world\n" \ |
| 480 | '' '' | 480 | '' '' |
| 481 | 481 | ||
| 482 | testing 'awk assign while test' \ | ||
| 483 | "awk '\$1==\$1=\"foo\" {print \$1}'" \ | ||
| 484 | "foo\n" \ | ||
| 485 | "" \ | ||
| 486 | "foo" | ||
| 487 | |||
| 482 | exit $FAILCOUNT | 488 | exit $FAILCOUNT |
diff --git a/testsuite/sha1sum.tests b/testsuite/sha1sum.tests index a968fa87c..7ad1334c3 100755 --- a/testsuite/sha1sum.tests +++ b/testsuite/sha1sum.tests | |||
| @@ -1,3 +1,13 @@ | |||
| 1 | #!/bin/sh | 1 | #!/bin/sh |
| 2 | 2 | ||
| 3 | . ./testing.sh | ||
| 4 | |||
| 5 | # testing "test name" "cmd" "expected result" "file input" "stdin" | ||
| 6 | >EMPTY | ||
| 7 | testing "sha1sum: one-space separated input for -c" \ | ||
| 8 | 'echo "da39a3ee5e6b4b0d3255bfef95601890afd80709 EMPTY" | sha1sum -c' \ | ||
| 9 | "EMPTY: OK\n" \ | ||
| 10 | "" "" | ||
| 11 | rm EMPTY | ||
| 12 | |||
| 3 | . ./md5sum.tests sha1sum d41337e834377140ae7f98460d71d908598ef04f | 13 | . ./md5sum.tests sha1sum d41337e834377140ae7f98460d71d908598ef04f |
diff --git a/testsuite/sort.tests b/testsuite/sort.tests index ff33e21b4..8dbadbdae 100755 --- a/testsuite/sort.tests +++ b/testsuite/sort.tests | |||
| @@ -219,4 +219,25 @@ testing "sort -h" \ | |||
| 219 | 219 | ||
| 220 | # testing "description" "command(s)" "result" "infile" "stdin" | 220 | # testing "description" "command(s)" "result" "infile" "stdin" |
| 221 | 221 | ||
| 222 | testing "sort -k2,2M" \ | ||
| 223 | "sort -k2,2M input" "\ | ||
| 224 | 3 March | ||
| 225 | 2 April | ||
| 226 | 1 May | ||
| 227 | " "\ | ||
| 228 | 2 April | ||
| 229 | 1 May | ||
| 230 | 3 March | ||
| 231 | " "" | ||
| 232 | |||
| 233 | testing "sort -s -u" \ | ||
| 234 | "sort -s -u -k 2 input" "\ | ||
| 235 | z a | ||
| 236 | z b | ||
| 237 | " "\ | ||
| 238 | z b | ||
| 239 | a b | ||
| 240 | z a | ||
| 241 | a a" "" | ||
| 242 | |||
| 222 | exit $FAILCOUNT | 243 | exit $FAILCOUNT |
diff --git a/testsuite/tree.tests b/testsuite/tree.tests new file mode 100755 index 000000000..4f4a9e30b --- /dev/null +++ b/testsuite/tree.tests | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | # Copyright 2022 by Roger Knecht <rknecht@pm.me> | ||
| 4 | # Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 5 | |||
| 6 | . ./testing.sh -v | ||
| 7 | |||
| 8 | # testing "description" "command" "result" "infile" "stdin" | ||
| 9 | |||
| 10 | testing "tree error opening dir" \ | ||
| 11 | "tree tree.tempdir" \ | ||
| 12 | "\ | ||
| 13 | tree.tempdir [error opening dir]\n\ | ||
| 14 | \n\ | ||
| 15 | 0 directories, 0 files\n" \ | ||
| 16 | "" "" | ||
| 17 | |||
| 18 | mkdir -p tree2.tempdir | ||
| 19 | touch tree2.tempdir/testfile | ||
| 20 | |||
| 21 | testing "tree single file" \ | ||
| 22 | "cd tree2.tempdir && tree" \ | ||
| 23 | "\ | ||
| 24 | .\n\ | ||
| 25 | └── testfile\n\ | ||
| 26 | \n\ | ||
| 27 | 0 directories, 1 files\n" \ | ||
| 28 | "" "" | ||
| 29 | |||
| 30 | mkdir -p tree3.tempdir/test1 \ | ||
| 31 | tree3.tempdir/test2/a \ | ||
| 32 | tree3.tempdir/test2/b \ | ||
| 33 | tree3.tempdir/test3/c \ | ||
| 34 | tree3.tempdir/test3/d | ||
| 35 | |||
| 36 | touch tree3.tempdir/test2/a/testfile1 \ | ||
| 37 | tree3.tempdir/test2/a/testfile2 \ | ||
| 38 | tree3.tempdir/test2/a/testfile3 \ | ||
| 39 | tree3.tempdir/test2/b/testfile4 \ | ||
| 40 | tree3.tempdir/test3/c/testfile5 \ | ||
| 41 | tree3.tempdir/test3/d/testfile6 \ | ||
| 42 | tree3.tempdir/test3/d/.testfile7 | ||
| 43 | |||
| 44 | (cd tree3.tempdir/test2/a && ln -s ../b/testfile4 .) | ||
| 45 | (cd tree3.tempdir/test2/b && ln -s ../../test3 .) | ||
| 46 | |||
| 47 | testing "tree nested directories and files" \ | ||
| 48 | "cd tree3.tempdir && tree" \ | ||
| 49 | "\ | ||
| 50 | .\n\ | ||
| 51 | ├── test1\n\ | ||
| 52 | ├── test2\n\ | ||
| 53 | │  ├── a\n\ | ||
| 54 | │  │  ├── testfile1\n\ | ||
| 55 | │  │  ├── testfile2\n\ | ||
| 56 | │  │  ├── testfile3\n\ | ||
| 57 | │  │  └── testfile4 -> ../b/testfile4\n\ | ||
| 58 | │  └── b\n\ | ||
| 59 | │  ├── test3 -> ../../test3\n\ | ||
| 60 | │  └── testfile4\n\ | ||
| 61 | └── test3\n\ | ||
| 62 | ├── c\n\ | ||
| 63 | │  └── testfile5\n\ | ||
| 64 | └── d\n\ | ||
| 65 | └── testfile6\n\ | ||
| 66 | \n\ | ||
| 67 | 7 directories, 8 files\n" \ | ||
| 68 | "" "" | ||
| 69 | #note: tree v2.0.1 says "8 directories, 7 files": | ||
| 70 | #it counts "test3 -> ../../test3" as a directory, even though it does not follow this symlink | ||
| 71 | |||
| 72 | testing "tree multiple directories" \ | ||
| 73 | "tree tree2.tempdir tree3.tempdir" \ | ||
| 74 | "\ | ||
| 75 | tree2.tempdir\n\ | ||
| 76 | └── testfile\n\ | ||
| 77 | tree3.tempdir\n\ | ||
| 78 | ├── test1\n\ | ||
| 79 | ├── test2\n\ | ||
| 80 | │  ├── a\n\ | ||
| 81 | │  │  ├── testfile1\n\ | ||
| 82 | │  │  ├── testfile2\n\ | ||
| 83 | │  │  ├── testfile3\n\ | ||
| 84 | │  │  └── testfile4 -> ../b/testfile4\n\ | ||
| 85 | │  └── b\n\ | ||
| 86 | │  ├── test3 -> ../../test3\n\ | ||
| 87 | │  └── testfile4\n\ | ||
| 88 | └── test3\n\ | ||
| 89 | ├── c\n\ | ||
| 90 | │  └── testfile5\n\ | ||
| 91 | └── d\n\ | ||
| 92 | └── testfile6\n\ | ||
| 93 | \n\ | ||
| 94 | 7 directories, 9 files\n" \ | ||
| 95 | "" "" | ||
| 96 | #note: tree v2.0.1 says "8 directories, 7 files" (not "8 files", probably a/testfile4 -> ../b/testfile4 and b/testfile4 are counted as one file, not 2?) | ||
| 97 | |||
| 98 | rm -rf tree.tempdir tree2.tempdir tree3.tempdir | ||
| 99 | |||
| 100 | exit $FAILCOUNT | ||
diff --git a/testsuite/xxd.tests b/testsuite/xxd.tests index 76fa96af9..2c740abc8 100755 --- a/testsuite/xxd.tests +++ b/testsuite/xxd.tests | |||
| @@ -37,4 +37,27 @@ testing 'xxd -p -r' \ | |||
| 37 | '' \ | 37 | '' \ |
| 38 | '30313233343536373736353433323130 30313233343536373736353433323130' | 38 | '30313233343536373736353433323130 30313233343536373736353433323130' |
| 39 | 39 | ||
| 40 | testing 'xxd -r skips leading whitespace and truncates at two spaces' \ | ||
| 41 | 'xxd -r' \ | ||
| 42 | '0123456789:;<=>?@' \ | ||
| 43 | '' "\ | ||
| 44 | 00000000: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? | ||
| 45 | 00000010: 40 @ | ||
| 46 | " | ||
| 47 | |||
| 48 | testing 'xxd -p -r skips one bad char, truncates at two bad chars' \ | ||
| 49 | 'xxd -p -r' \ | ||
| 50 | '01' \ | ||
| 51 | '' "\ | ||
| 52 | 30 !31 !!32 | ||
| 53 | " | ||
| 54 | |||
| 55 | testing 'xxd -p -r ignores the nibble with 2nd char bad' \ | ||
| 56 | 'xxd -p -r' \ | ||
| 57 | '3C6' \ | ||
| 58 | '' "\ | ||
| 59 | 33 3!4 3!!5 | ||
| 60 | 36 | ||
| 61 | " | ||
| 62 | |||
| 40 | exit $FAILCOUNT | 63 | exit $FAILCOUNT |
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index 4372ac770..6629407de 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c | |||
| @@ -55,6 +55,7 @@ | |||
| 55 | //usage: "\n -r Reverse (with -p, assumes no offsets in input)" | 55 | //usage: "\n -r Reverse (with -p, assumes no offsets in input)" |
| 56 | 56 | ||
| 57 | #include "libbb.h" | 57 | #include "libbb.h" |
| 58 | #include "common_bufsiz.h" | ||
| 58 | #include "dump.h" | 59 | #include "dump.h" |
| 59 | 60 | ||
| 60 | /* This is a NOEXEC applet. Be very careful! */ | 61 | /* This is a NOEXEC applet. Be very careful! */ |
| @@ -69,61 +70,110 @@ | |||
| 69 | #define OPT_c (1 << 7) | 70 | #define OPT_c (1 << 7) |
| 70 | #define OPT_o (1 << 8) | 71 | #define OPT_o (1 << 8) |
| 71 | 72 | ||
| 72 | static void reverse(unsigned opt, const char *filename) | 73 | #define fillbuf bb_common_bufsiz1 |
| 74 | |||
| 75 | static void write_zeros(off_t count) | ||
| 76 | { | ||
| 77 | errno = 0; | ||
| 78 | do { | ||
| 79 | unsigned sz = count < COMMON_BUFSIZE ? (unsigned)count : COMMON_BUFSIZE; | ||
| 80 | if (fwrite(fillbuf, 1, sz, stdout) != sz) | ||
| 81 | bb_perror_msg_and_die("write error"); | ||
| 82 | count -= sz; | ||
| 83 | } while (count != 0); | ||
| 84 | } | ||
| 85 | |||
| 86 | static void reverse(unsigned opt, const char *filename, char *opt_s) | ||
| 73 | { | 87 | { |
| 74 | FILE *fp; | 88 | FILE *fp; |
| 75 | char *buf; | 89 | char *buf; |
| 90 | off_t cur, opt_s_ofs; | ||
| 91 | |||
| 92 | memset(fillbuf, 0, COMMON_BUFSIZE); | ||
| 93 | opt_s_ofs = cur = 0; | ||
| 94 | if (opt_s) { | ||
| 95 | opt_s_ofs = BB_STRTOOFF(opt_s, NULL, 0); | ||
| 96 | if (errno || opt_s_ofs < 0) | ||
| 97 | bb_error_msg_and_die("invalid number '%s'", opt_s); | ||
| 98 | } | ||
| 76 | 99 | ||
| 77 | fp = filename ? xfopen_for_read(filename) : stdin; | 100 | fp = filename ? xfopen_for_read(filename) : stdin; |
| 78 | 101 | ||
| 102 | get_new_line: | ||
| 79 | while ((buf = xmalloc_fgetline(fp)) != NULL) { | 103 | while ((buf = xmalloc_fgetline(fp)) != NULL) { |
| 80 | char *p; | 104 | char *p; |
| 81 | 105 | ||
| 82 | p = buf; | 106 | p = buf; |
| 83 | if (!(opt & OPT_p)) { | 107 | if (!(opt & OPT_p)) { |
| 84 | /* skip address */ | 108 | char *end; |
| 85 | while (isxdigit(*p)) p++; | 109 | off_t ofs; |
| 110 | skip_address: | ||
| 111 | p = skip_whitespace(p); | ||
| 112 | ofs = BB_STRTOOFF(p, &end, 16); | ||
| 113 | if ((errno && errno != EINVAL) | ||
| 114 | || ofs < 0 | ||
| 115 | /* -s SEEK value should be added before seeking */ | ||
| 116 | || (ofs += opt_s_ofs) < 0 | ||
| 117 | ) { | ||
| 118 | bb_error_msg_and_die("invalid number '%s'", p); | ||
| 119 | } | ||
| 120 | if (ofs != cur) { | ||
| 121 | if (fseeko(stdout, ofs, SEEK_SET) != 0) { | ||
| 122 | if (ofs < cur) | ||
| 123 | bb_perror_msg_and_die("cannot seek"); | ||
| 124 | write_zeros(ofs - cur); | ||
| 125 | } | ||
| 126 | cur = ofs; | ||
| 127 | } | ||
| 128 | p = end; | ||
| 86 | /* NB: for xxd -r, first hex portion is address even without colon */ | 129 | /* NB: for xxd -r, first hex portion is address even without colon */ |
| 87 | /* If it's there, skip it: */ | 130 | /* But if colon is there, skip it: */ |
| 88 | if (*p == ':') p++; | 131 | if (*p == ':') |
| 89 | 132 | p++; | |
| 90 | //TODO: seek (or zero-pad if unseekable) to the address position | ||
| 91 | //NOTE: -s SEEK value should be added to the address before seeking | ||
| 92 | } | 133 | } |
| 93 | 134 | ||
| 94 | /* Process hex bytes optionally separated by whitespace */ | 135 | /* Process hex bytes optionally separated by whitespace */ |
| 95 | for (;;) { | 136 | for (;;) { |
| 96 | uint8_t val, c; | 137 | uint8_t val, c; |
| 138 | int badchar = 0; | ||
| 97 | nibble1: | 139 | nibble1: |
| 98 | p = skip_whitespace(p); | 140 | if (opt & OPT_p) |
| 99 | 141 | p = skip_whitespace(p); | |
| 100 | c = *p++; | 142 | c = *p++; |
| 101 | if (isdigit(c)) | 143 | if (isdigit(c)) |
| 102 | val = c - '0'; | 144 | val = c - '0'; |
| 103 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') | 145 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') |
| 104 | val = (c|0x20) - ('a' - 10); | 146 | val = (c|0x20) - ('a' - 10); |
| 105 | else { | 147 | else { |
| 106 | /* xxd V1.10 is inconsistent here. | 148 | /* xxd V1.10 allows one non-hexnum char: |
| 107 | * echo -e "31 !3 0a 0a" | xxd -r -p | 149 | * echo -e "31 !3 0a 0a" | xxd -r -p |
| 108 | * is "10<a0>" (no <cr>) - "!" is ignored, | 150 | * is "10<a0>" (no <cr>) - "!" is ignored, |
| 109 | * but | 151 | * but stops for more than one: |
| 110 | * echo -e "31 !!343434\n30 0a" | xxd -r -p | 152 | * echo -e "31 !!343434\n30 0a" | xxd -r -p |
| 111 | * is "10<cr>" - "!!" drops rest of the line. | 153 | * is "10<cr>" - "!!" drops rest of the line. |
| 112 | * We will ignore all invalid chars: | 154 | * Note: this also covers whitespace chars: |
| 155 | * xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? | ||
| 156 | * detects this ^ - skips this one space | ||
| 157 | * xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? | ||
| 158 | * detects this ^^ - skips the rest | ||
| 113 | */ | 159 | */ |
| 114 | if (c != '\0') | 160 | if (c == '\0' || badchar) |
| 115 | goto nibble1; | 161 | break; |
| 116 | break; | 162 | badchar++; |
| 163 | goto nibble1; | ||
| 117 | } | 164 | } |
| 118 | val <<= 4; | 165 | val <<= 4; |
| 119 | 166 | ||
| 120 | /* Works the same with xxd V1.10: | ||
| 121 | * echo "31 09 32 0a" | xxd -r -p | ||
| 122 | * echo "31 0 9 32 0a" | xxd -r -p | ||
| 123 | * thus allow whitespace even within the byte: | ||
| 124 | */ | ||
| 125 | nibble2: | 167 | nibble2: |
| 126 | p = skip_whitespace(p); | 168 | if (opt & OPT_p) { |
| 169 | /* Works the same with xxd V1.10: | ||
| 170 | * echo "31 09 32 0a" | xxd -r -p | ||
| 171 | * echo "31 0 9 32 0a" | xxd -r -p | ||
| 172 | * thus allow whitespace (even multiple chars) | ||
| 173 | * after byte's 1st char: | ||
| 174 | */ | ||
| 175 | p = skip_whitespace(p); | ||
| 176 | } | ||
| 127 | 177 | ||
| 128 | c = *p++; | 178 | c = *p++; |
| 129 | if (isdigit(c)) | 179 | if (isdigit(c)) |
| @@ -132,7 +182,16 @@ static void reverse(unsigned opt, const char *filename) | |||
| 132 | val |= (c|0x20) - ('a' - 10); | 182 | val |= (c|0x20) - ('a' - 10); |
| 133 | else { | 183 | else { |
| 134 | if (c != '\0') { | 184 | if (c != '\0') { |
| 135 | /* "...3<not_hex_char>..." ignores both chars */ | 185 | /* "...3<not_hex_char>...": ignore "3", |
| 186 | * skip everything up to next hexchar or newline: | ||
| 187 | */ | ||
| 188 | while (!isxdigit(*p)) { | ||
| 189 | if (*p == '\0') { | ||
| 190 | free(buf); | ||
| 191 | goto get_new_line; | ||
| 192 | } | ||
| 193 | p++; | ||
| 194 | } | ||
| 136 | goto nibble1; | 195 | goto nibble1; |
| 137 | } | 196 | } |
| 138 | /* Nibbles can join even through newline: | 197 | /* Nibbles can join even through newline: |
| @@ -143,10 +202,13 @@ static void reverse(unsigned opt, const char *filename) | |||
| 143 | p = buf = xmalloc_fgetline(fp); | 202 | p = buf = xmalloc_fgetline(fp); |
| 144 | if (!buf) | 203 | if (!buf) |
| 145 | break; | 204 | break; |
| 205 | if (!(opt & OPT_p)) /* -p and !-p: different behavior */ | ||
| 206 | goto skip_address; | ||
| 146 | goto nibble2; | 207 | goto nibble2; |
| 147 | } | 208 | } |
| 148 | putchar(val); | 209 | putchar(val); |
| 149 | } | 210 | cur++; |
| 211 | } /* for(;;) */ | ||
| 150 | free(buf); | 212 | free(buf); |
| 151 | } | 213 | } |
| 152 | //fclose(fp); | 214 | //fclose(fp); |
| @@ -173,6 +235,8 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
| 173 | unsigned opt; | 235 | unsigned opt; |
| 174 | int r; | 236 | int r; |
| 175 | 237 | ||
| 238 | setup_common_bufsiz(); | ||
| 239 | |||
| 176 | dumper = alloc_dumper(); | 240 | dumper = alloc_dumper(); |
| 177 | 241 | ||
| 178 | opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */, | 242 | opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */, |
| @@ -200,7 +264,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
| 200 | } | 264 | } |
| 201 | 265 | ||
| 202 | if (opt & OPT_r) { | 266 | if (opt & OPT_r) { |
| 203 | reverse(opt, argv[0]); | 267 | reverse(opt, argv[0], opt_s); |
| 204 | } | 268 | } |
| 205 | 269 | ||
| 206 | if (opt & OPT_o) { | 270 | if (opt & OPT_o) { |
