aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2011-01-04 19:56:15 +0700
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2011-01-04 19:56:15 +0700
commit5f6f2162512106adf120d4b528bb125e93e34429 (patch)
tree7d7449f755633c263be7125ad58d21cc3ca5b8a7 /libbb
parent9db69882bee2d528d706d61d34ef7741122330be (diff)
parenta116552869db5e7793ae10968eb3c962c69b3d8c (diff)
downloadbusybox-w32-5f6f2162512106adf120d4b528bb125e93e34429.tar.gz
busybox-w32-5f6f2162512106adf120d4b528bb125e93e34429.tar.bz2
busybox-w32-5f6f2162512106adf120d4b528bb125e93e34429.zip
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Config.src2
-rw-r--r--libbb/Kbuild.src1
-rw-r--r--libbb/appletlib.c79
-rw-r--r--libbb/find_root_device.c9
-rw-r--r--libbb/getopt32.c2
-rw-r--r--libbb/hash_md5_sha.c8
-rw-r--r--libbb/lineedit.c99
-rw-r--r--libbb/procps.c2
-rw-r--r--libbb/pw_encrypt_sha.c56
-rw-r--r--libbb/read_printf.c2
-rw-r--r--libbb/simplify_path.c10
-rw-r--r--libbb/time.c12
-rw-r--r--libbb/u_signal_names.c68
-rw-r--r--libbb/unicode.c7
-rw-r--r--libbb/update_passwd.c2
-rw-r--r--libbb/xfuncs.c2
16 files changed, 235 insertions, 126 deletions
diff --git a/libbb/Config.src b/libbb/Config.src
index f6c7a11ea..85892d3fe 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -135,7 +135,7 @@ config FEATURE_NON_POSIX_CP
135 and create a regular file. This does not conform to POSIX, 135 and create a regular file. This does not conform to POSIX,
136 but prevents a symlink attack. 136 but prevents a symlink attack.
137 Similarly, "cp file device" will not send file's data 137 Similarly, "cp file device" will not send file's data
138 to the device. 138 to the device. (To do that, use "cat file >device")
139 139
140config FEATURE_VERBOSE_CP_MESSAGE 140config FEATURE_VERBOSE_CP_MESSAGE
141 bool "Give more precise messages when copy fails (cp, mv etc)" 141 bool "Give more precise messages when copy fails (cp, mv etc)"
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index e3866e456..b88fa8fe7 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -159,6 +159,7 @@ lib-$(CONFIG_RTCWAKE) += rtc.o
159 159
160lib-$(CONFIG_IOSTAT) += get_cpu_count.o 160lib-$(CONFIG_IOSTAT) += get_cpu_count.o
161lib-$(CONFIG_MPSTAT) += get_cpu_count.o 161lib-$(CONFIG_MPSTAT) += get_cpu_count.o
162lib-$(CONFIG_POWERTOP) += get_cpu_count.o
162 163
163# We shouldn't build xregcomp.c if we don't need it - this ensures we don't 164# We shouldn't build xregcomp.c if we don't need it - this ensures we don't
164# require regex.h to be in the include dir even if we don't need it thereby 165# require regex.h to be in the include dir even if we don't need it thereby
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 3b691f945..b1c772cf3 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -28,7 +28,11 @@
28 */ 28 */
29#include "busybox.h" 29#include "busybox.h"
30#include <assert.h> 30#include <assert.h>
31#include <malloc.h> 31#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
32 || defined(__APPLE__) \
33 )
34# include <malloc.h> /* for mallopt */
35#endif
32/* Try to pull in PAGE_SIZE */ 36/* Try to pull in PAGE_SIZE */
33#ifdef __linux__ 37#ifdef __linux__
34# include <sys/user.h> 38# include <sys/user.h>
@@ -66,7 +70,7 @@ static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
66#if ENABLE_FEATURE_COMPRESS_USAGE 70#if ENABLE_FEATURE_COMPRESS_USAGE
67 71
68static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; 72static const char packed_usage[] ALIGN1 = { PACKED_USAGE };
69# include "unarchive.h" 73# include "archive.h"
70static const char *unpack_usage_messages(void) 74static const char *unpack_usage_messages(void)
71{ 75{
72 char *outbuf = NULL; 76 char *outbuf = NULL;
@@ -75,7 +79,7 @@ static const char *unpack_usage_messages(void)
75 79
76 i = start_bunzip(&bd, 80 i = start_bunzip(&bd,
77 /* src_fd: */ -1, 81 /* src_fd: */ -1,
78 /* inbuf: */ (void *)packed_usage, 82 /* inbuf: */ packed_usage,
79 /* len: */ sizeof(packed_usage)); 83 /* len: */ sizeof(packed_usage));
80 /* read_bunzip can longjmp to start_bunzip, and ultimately 84 /* read_bunzip can longjmp to start_bunzip, and ultimately
81 * end up here with i != 0 on read data errors! Not trivial */ 85 * end up here with i != 0 on read data errors! Not trivial */
@@ -103,14 +107,13 @@ void FAST_FUNC bb_show_usage(void)
103 if (ENABLE_SHOW_USAGE) { 107 if (ENABLE_SHOW_USAGE) {
104#ifdef SINGLE_APPLET_STR 108#ifdef SINGLE_APPLET_STR
105 /* Imagine that this applet is "true". Dont suck in printf! */ 109 /* Imagine that this applet is "true". Dont suck in printf! */
106 const char *p; 110 const char *usage_string = unpack_usage_messages();
107 const char *usage_string = p = unpack_usage_messages();
108 111
109 if (*p == '\b') { 112 if (*usage_string == '\b') {
110 full_write2_str("No help available.\n\n"); 113 full_write2_str("No help available.\n\n");
111 } else { 114 } else {
112 full_write2_str("Usage: "SINGLE_APPLET_STR" "); 115 full_write2_str("Usage: "SINGLE_APPLET_STR" ");
113 full_write2_str(p); 116 full_write2_str(usage_string);
114 full_write2_str("\n\n"); 117 full_write2_str("\n\n");
115 } 118 }
116 if (ENABLE_FEATURE_CLEAN_UP) 119 if (ENABLE_FEATURE_CLEAN_UP)
@@ -228,7 +231,7 @@ bool re_execed;
228 231
229IF_FEATURE_SUID(static uid_t ruid;) /* real uid */ 232IF_FEATURE_SUID(static uid_t ruid;) /* real uid */
230 233
231#if ENABLE_FEATURE_SUID_CONFIG 234# if ENABLE_FEATURE_SUID_CONFIG
232 235
233/* applets[] is const, so we have to define this "override" structure */ 236/* applets[] is const, so we have to define this "override" structure */
234static struct BB_suid_config { 237static struct BB_suid_config {
@@ -499,15 +502,15 @@ static void parse_config_file(void)
499 sct_head = sct; 502 sct_head = sct;
500 } 503 }
501} 504}
502#else 505# else
503static inline void parse_config_file(void) 506static inline void parse_config_file(void)
504{ 507{
505 IF_FEATURE_SUID(ruid = getuid();) 508 IF_FEATURE_SUID(ruid = getuid();)
506} 509}
507#endif /* FEATURE_SUID_CONFIG */ 510# endif /* FEATURE_SUID_CONFIG */
508 511
509 512
510#if ENABLE_FEATURE_SUID 513# if ENABLE_FEATURE_SUID
511static void check_suid(int applet_no) 514static void check_suid(int applet_no)
512{ 515{
513 gid_t rgid; /* real gid */ 516 gid_t rgid; /* real gid */
@@ -516,7 +519,7 @@ static void check_suid(int applet_no)
516 return; /* run by root - no need to check more */ 519 return; /* run by root - no need to check more */
517 rgid = getgid(); 520 rgid = getgid();
518 521
519#if ENABLE_FEATURE_SUID_CONFIG 522# if ENABLE_FEATURE_SUID_CONFIG
520 if (suid_cfg_readable) { 523 if (suid_cfg_readable) {
521 uid_t uid; 524 uid_t uid;
522 struct BB_suid_config *sct; 525 struct BB_suid_config *sct;
@@ -559,7 +562,7 @@ static void check_suid(int applet_no)
559 bb_perror_msg_and_die("setresuid"); 562 bb_perror_msg_and_die("setresuid");
560 return; 563 return;
561 } 564 }
562#if !ENABLE_FEATURE_SUID_CONFIG_QUIET 565# if !ENABLE_FEATURE_SUID_CONFIG_QUIET
563 { 566 {
564 static bool onetime = 0; 567 static bool onetime = 0;
565 568
@@ -568,9 +571,9 @@ static void check_suid(int applet_no)
568 fprintf(stderr, "Using fallback suid method\n"); 571 fprintf(stderr, "Using fallback suid method\n");
569 } 572 }
570 } 573 }
571#endif 574# endif
572 check_need_suid: 575 check_need_suid:
573#endif 576# endif
574 if (APPLET_SUID(applet_no) == _BB_SUID_REQUIRE) { 577 if (APPLET_SUID(applet_no) == _BB_SUID_REQUIRE) {
575 /* Real uid is not 0. If euid isn't 0 too, suid bit 578 /* Real uid is not 0. If euid isn't 0 too, suid bit
576 * is most probably not set on our executable */ 579 * is most probably not set on our executable */
@@ -581,25 +584,24 @@ static void check_suid(int applet_no)
581 xsetuid(ruid); 584 xsetuid(ruid);
582 } 585 }
583} 586}
584#else 587# else
585#define check_suid(x) ((void)0) 588# define check_suid(x) ((void)0)
586#endif /* FEATURE_SUID */ 589# endif /* FEATURE_SUID */
587 590
588 591
589#if ENABLE_FEATURE_INSTALLER 592# if ENABLE_FEATURE_INSTALLER
590static const char usr_bin [] ALIGN1 = "/usr/bin/"; 593static const char usr_bin [] ALIGN1 = "/usr/bin/";
591static const char usr_sbin[] ALIGN1 = "/usr/sbin/"; 594static const char usr_sbin[] ALIGN1 = "/usr/sbin/";
592static const char *const install_dir[] = { 595static const char *const install_dir[] = {
593 &usr_bin [8], /* "/" */ 596 &usr_bin [8], /* "/" */
594 &usr_bin [4], /* "/bin/" */ 597 &usr_bin [4], /* "/bin/" */
595 &usr_sbin[4] /* "/sbin/" */ 598 &usr_sbin[4] /* "/sbin/" */
596# if !ENABLE_INSTALL_NO_USR 599# if !ENABLE_INSTALL_NO_USR
597 ,usr_bin 600 ,usr_bin
598 ,usr_sbin 601 ,usr_sbin
599# endif 602# endif
600}; 603};
601 604
602
603/* create (sym)links for each applet */ 605/* create (sym)links for each applet */
604static void install_links(const char *busybox, int use_symbolic_links, 606static void install_links(const char *busybox, int use_symbolic_links,
605 char *custom_install_dir) 607 char *custom_install_dir)
@@ -629,9 +631,9 @@ static void install_links(const char *busybox, int use_symbolic_links,
629 free(fpc); 631 free(fpc);
630 } 632 }
631} 633}
632#else 634# else
633# define install_links(x,y,z) ((void)0) 635# define install_links(x,y,z) ((void)0)
634#endif 636# endif
635 637
636/* If we were called as "busybox..." */ 638/* If we were called as "busybox..." */
637static int busybox_main(char **argv) 639static int busybox_main(char **argv)
@@ -696,10 +698,10 @@ static int busybox_main(char **argv)
696 const char *a = applet_names; 698 const char *a = applet_names;
697 dup2(1, 2); 699 dup2(1, 2);
698 while (*a) { 700 while (*a) {
699#if ENABLE_FEATURE_INSTALLER 701# if ENABLE_FEATURE_INSTALLER
700 if (argv[1][6]) /* --list-path? */ 702 if (argv[1][6]) /* --list-path? */
701 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); 703 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1);
702#endif 704# endif
703 full_write2_str(a); 705 full_write2_str(a);
704 full_write2_str("\n"); 706 full_write2_str("\n");
705 i++; 707 i++;
@@ -772,7 +774,7 @@ void FAST_FUNC run_applet_and_exit(const char *name, char **argv)
772 int applet = find_applet_by_name(name); 774 int applet = find_applet_by_name(name);
773 if (applet >= 0) 775 if (applet >= 0)
774 run_applet_no_and_exit(applet, argv); 776 run_applet_no_and_exit(applet, argv);
775 if (!strncmp(name, "busybox", 7)) 777 if (strncmp(name, "busybox", 7) == 0)
776 exit(busybox_main(argv)); 778 exit(busybox_main(argv));
777} 779}
778 780
@@ -804,14 +806,6 @@ int main(int argc UNUSED_PARAM, char **argv)
804 mallopt(M_MMAP_THRESHOLD, 8 * PAGE_SIZE - 256); 806 mallopt(M_MMAP_THRESHOLD, 8 * PAGE_SIZE - 256);
805#endif 807#endif
806 808
807#if defined(SINGLE_APPLET_MAIN)
808 /* Only one applet is selected by the user! */
809 /* applet_names in this case is just "applet\0\0" */
810 lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv));
811 return SINGLE_APPLET_MAIN(argc, argv);
812#else
813 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
814
815#if !BB_MMU 809#if !BB_MMU
816 /* NOMMU re-exec trick sets high-order bit in first byte of name */ 810 /* NOMMU re-exec trick sets high-order bit in first byte of name */
817 if (argv[0][0] & 0x80) { 811 if (argv[0][0] & 0x80) {
@@ -819,6 +813,19 @@ int main(int argc UNUSED_PARAM, char **argv)
819 argv[0][0] &= 0x7f; 813 argv[0][0] &= 0x7f;
820 } 814 }
821#endif 815#endif
816
817#if defined(SINGLE_APPLET_MAIN)
818 /* Only one applet is selected in .config */
819 if (argv[1] && strncmp(argv[0], "busybox", 7) == 0) {
820 /* "busybox <applet> <params>" should still work as expected */
821 argv++;
822 }
823 /* applet_names in this case is just "applet\0\0" */
824 lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv));
825 return SINGLE_APPLET_MAIN(argc, argv);
826#else
827 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
828
822 applet_name = argv[0]; 829 applet_name = argv[0];
823 if (applet_name[0] == '-') 830 if (applet_name[0] == '-')
824 applet_name++; 831 applet_name++;
diff --git a/libbb/find_root_device.c b/libbb/find_root_device.c
index 32c86cea8..8436cd664 100644
--- a/libbb/find_root_device.c
+++ b/libbb/find_root_device.c
@@ -29,14 +29,15 @@ static char *find_block_device_in_dir(struct arena *ap)
29 char *retpath = NULL; 29 char *retpath = NULL;
30 int len, rem; 30 int len, rem;
31 31
32 dir = opendir(ap->devpath);
33 if (!dir)
34 return NULL;
35
36 len = strlen(ap->devpath); 32 len = strlen(ap->devpath);
37 rem = DEVNAME_MAX-2 - len; 33 rem = DEVNAME_MAX-2 - len;
38 if (rem <= 0) 34 if (rem <= 0)
39 return NULL; 35 return NULL;
36
37 dir = opendir(ap->devpath);
38 if (!dir)
39 return NULL;
40
40 ap->devpath[len++] = '/'; 41 ap->devpath[len++] = '/';
41 42
42 while ((entry = readdir(dir)) != NULL) { 43 while ((entry = readdir(dir)) != NULL) {
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index ab77755fc..187cb3a79 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -115,7 +115,7 @@ const char *opt_complementary
115 found. 115 found.
116 116
117 "ww" Adjacent double options have a counter associated which indicates 117 "ww" Adjacent double options have a counter associated which indicates
118 the number of occurences of the option. 118 the number of occurrences of the option.
119 For example the ps applet needs: 119 For example the ps applet needs:
120 if w is given once, GNU ps sets the width to 132, 120 if w is given once, GNU ps sets the width to 132,
121 if w is given more than once, it is "unlimited" 121 if w is given more than once, it is "unlimited"
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
index e427f6080..b87d1dde8 100644
--- a/libbb/hash_md5_sha.c
+++ b/libbb/hash_md5_sha.c
@@ -158,11 +158,11 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
158 }; 158 };
159 static const char P_array[] ALIGN1 = { 159 static const char P_array[] ALIGN1 = {
160# if MD5_SIZE_VS_SPEED > 1 160# if MD5_SIZE_VS_SPEED > 1
161 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ 161 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
162# endif 162# endif
163 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ 163 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
164 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ 164 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
165 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ 165 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
166 }; 166 };
167#endif 167#endif
168 uint32_t *words = (void*) ctx->wbuffer; 168 uint32_t *words = (void*) ctx->wbuffer;
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 182dfac13..f9658711a 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -94,8 +94,10 @@ static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); }
94#endif 94#endif
95 95
96 96
97#define SEQ_CLEAR_TILL_END_OF_SCREEN "\033[J" 97#define ESC "\033"
98//#define SEQ_CLEAR_TILL_END_OF_LINE "\033[K" 98
99#define SEQ_CLEAR_TILL_END_OF_SCREEN ESC"[J"
100//#define SEQ_CLEAR_TILL_END_OF_LINE ESC"[K"
99 101
100 102
101enum { 103enum {
@@ -446,7 +448,7 @@ static void input_backward(unsigned num)
446 } while (--num); 448 } while (--num);
447 return; 449 return;
448 } 450 }
449 printf("\033[%uD", num); 451 printf(ESC"[%uD", num);
450 return; 452 return;
451 } 453 }
452 454
@@ -471,7 +473,7 @@ static void input_backward(unsigned num)
471 */ 473 */
472 unsigned sv_cursor; 474 unsigned sv_cursor;
473 /* go to 1st column; go up to first line */ 475 /* go to 1st column; go up to first line */
474 printf("\r" "\033[%uA", cmdedit_y); 476 printf("\r" ESC"[%uA", cmdedit_y);
475 cmdedit_y = 0; 477 cmdedit_y = 0;
476 sv_cursor = cursor; 478 sv_cursor = cursor;
477 put_prompt(); /* sets cursor to 0 */ 479 put_prompt(); /* sets cursor to 0 */
@@ -488,12 +490,12 @@ static void input_backward(unsigned num)
488 cmdedit_x = (width * cmdedit_y - num) % width; 490 cmdedit_x = (width * cmdedit_y - num) % width;
489 cmdedit_y -= lines_up; 491 cmdedit_y -= lines_up;
490 /* go to 1st column; go up */ 492 /* go to 1st column; go up */
491 printf("\r" "\033[%uA", lines_up); 493 printf("\r" ESC"[%uA", lines_up);
492 /* go to correct column. 494 /* go to correct column.
493 * xterm, konsole, Linux VT interpret 0 as 1 below! wow. 495 * xterm, konsole, Linux VT interpret 0 as 1 below! wow.
494 * need to *make sure* we skip it if cmdedit_x == 0 */ 496 * need to *make sure* we skip it if cmdedit_x == 0 */
495 if (cmdedit_x) 497 if (cmdedit_x)
496 printf("\033[%uC", cmdedit_x); 498 printf(ESC"[%uC", cmdedit_x);
497 } 499 }
498} 500}
499 501
@@ -501,7 +503,7 @@ static void input_backward(unsigned num)
501static void redraw(int y, int back_cursor) 503static void redraw(int y, int back_cursor)
502{ 504{
503 if (y > 0) /* up y lines */ 505 if (y > 0) /* up y lines */
504 printf("\033[%uA", y); 506 printf(ESC"[%uA", y);
505 bb_putchar('\r'); 507 bb_putchar('\r');
506 put_prompt(); 508 put_prompt();
507 put_till_end_and_adv_cursor(); 509 put_till_end_and_adv_cursor();
@@ -582,6 +584,12 @@ static void input_forward(void)
582 584
583#if ENABLE_FEATURE_TAB_COMPLETION 585#if ENABLE_FEATURE_TAB_COMPLETION
584 586
587//FIXME:
588//needs to be more clever: currently it thinks that "foo\ b<TAB>
589//matches the file named "foo bar", which is untrue.
590//Also, perhaps "foo b<TAB> needs to complete to "foo bar" <cursor>,
591//not "foo bar <cursor>...
592
585static void free_tab_completion_data(void) 593static void free_tab_completion_data(void)
586{ 594{
587 if (matches) { 595 if (matches) {
@@ -599,7 +607,7 @@ static void add_match(char *matched)
599 num_matches++; 607 num_matches++;
600} 608}
601 609
602#if ENABLE_FEATURE_USERNAME_COMPLETION 610# if ENABLE_FEATURE_USERNAME_COMPLETION
603/* Replace "~user/..." with "/homedir/...". 611/* Replace "~user/..." with "/homedir/...".
604 * The parameter is malloced, free it or return it 612 * The parameter is malloced, free it or return it
605 * unchanged if no user is matched. 613 * unchanged if no user is matched.
@@ -655,7 +663,7 @@ static NOINLINE unsigned complete_username(const char *ud)
655 663
656 return 1 + userlen; 664 return 1 + userlen;
657} 665}
658#endif /* FEATURE_USERNAME_COMPLETION */ 666# endif /* FEATURE_USERNAME_COMPLETION */
659 667
660enum { 668enum {
661 FIND_EXE_ONLY = 0, 669 FIND_EXE_ONLY = 0,
@@ -740,10 +748,10 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
740 pfind++; 748 pfind++;
741 /* dirbuf = ".../.../.../" */ 749 /* dirbuf = ".../.../.../" */
742 dirbuf = xstrndup(command, pfind - command); 750 dirbuf = xstrndup(command, pfind - command);
743#if ENABLE_FEATURE_USERNAME_COMPLETION 751# if ENABLE_FEATURE_USERNAME_COMPLETION
744 if (dirbuf[0] == '~') /* ~/... or ~user/... */ 752 if (dirbuf[0] == '~') /* ~/... or ~user/... */
745 dirbuf = username_path_completion(dirbuf); 753 dirbuf = username_path_completion(dirbuf);
746#endif 754# endif
747 path1[0] = dirbuf; 755 path1[0] = dirbuf;
748 } 756 }
749 pf_len = strlen(pfind); 757 pf_len = strlen(pfind);
@@ -1021,13 +1029,18 @@ static void showfiles(void)
1021 } 1029 }
1022} 1030}
1023 1031
1024static char *add_quote_for_spec_chars(char *found) 1032static const char *is_special_char(char c)
1033{
1034 return strchr(" `\"#$%^&*()=+{}[]:;'|\\<>", c);
1035}
1036
1037static char *quote_special_chars(char *found)
1025{ 1038{
1026 int l = 0; 1039 int l = 0;
1027 char *s = xzalloc((strlen(found) + 1) * 2); 1040 char *s = xzalloc((strlen(found) + 1) * 2);
1028 1041
1029 while (*found) { 1042 while (*found) {
1030 if (strchr(" `\"#$%^&*()=+{}[]:;'|\\<>", *found)) 1043 if (is_special_char(*found))
1031 s[l++] = '\\'; 1044 s[l++] = '\\';
1032 s[l++] = *found++; 1045 s[l++] = *found++;
1033 } 1046 }
@@ -1044,10 +1057,10 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1044 /* Length of string used for matching */ 1057 /* Length of string used for matching */
1045 unsigned match_pfx_len = match_pfx_len; 1058 unsigned match_pfx_len = match_pfx_len;
1046 int find_type; 1059 int find_type;
1047#if ENABLE_UNICODE_SUPPORT 1060# if ENABLE_UNICODE_SUPPORT
1048 /* cursor pos in command converted to multibyte form */ 1061 /* cursor pos in command converted to multibyte form */
1049 int cursor_mb; 1062 int cursor_mb;
1050#endif 1063# endif
1051 if (!(state->flags & TAB_COMPLETION)) 1064 if (!(state->flags & TAB_COMPLETION))
1052 return; 1065 return;
1053 1066
@@ -1074,9 +1087,9 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1074 * (we then also (ab)use this extra space later - see (**)) 1087 * (we then also (ab)use this extra space later - see (**))
1075 */ 1088 */
1076 match_buf = xmalloc(MAX_LINELEN * sizeof(int16_t)); 1089 match_buf = xmalloc(MAX_LINELEN * sizeof(int16_t));
1077#if !ENABLE_UNICODE_SUPPORT 1090# if !ENABLE_UNICODE_SUPPORT
1078 save_string(match_buf, cursor + 1); /* +1 for NUL */ 1091 save_string(match_buf, cursor + 1); /* +1 for NUL */
1079#else 1092# else
1080 { 1093 {
1081 CHAR_T wc = command_ps[cursor]; 1094 CHAR_T wc = command_ps[cursor];
1082 command_ps[cursor] = BB_NUL; 1095 command_ps[cursor] = BB_NUL;
@@ -1084,26 +1097,37 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1084 command_ps[cursor] = wc; 1097 command_ps[cursor] = wc;
1085 cursor_mb = strlen(match_buf); 1098 cursor_mb = strlen(match_buf);
1086 } 1099 }
1087#endif 1100# endif
1088 find_type = build_match_prefix(match_buf); 1101 find_type = build_match_prefix(match_buf);
1089 1102
1090 /* Free up any memory already allocated */ 1103 /* Free up any memory already allocated */
1091 free_tab_completion_data(); 1104 free_tab_completion_data();
1092 1105
1093#if ENABLE_FEATURE_USERNAME_COMPLETION 1106# if ENABLE_FEATURE_USERNAME_COMPLETION
1094 /* If the word starts with `~' and there is no slash in the word, 1107 /* If the word starts with ~ and there is no slash in the word,
1095 * then try completing this word as a username. */ 1108 * then try completing this word as a username. */
1096 if (state->flags & USERNAME_COMPLETION) 1109 if (state->flags & USERNAME_COMPLETION)
1097 if (match_buf[0] == '~' && strchr(match_buf, '/') == NULL) 1110 if (match_buf[0] == '~' && strchr(match_buf, '/') == NULL)
1098 match_pfx_len = complete_username(match_buf); 1111 match_pfx_len = complete_username(match_buf);
1099#endif 1112# endif
1100 /* Try to match a command in $PATH, or a directory, or a file */ 1113 /* If complete_username() did not match,
1114 * try to match a command in $PATH, or a directory, or a file */
1101 if (!matches) 1115 if (!matches)
1102 match_pfx_len = complete_cmd_dir_file(match_buf, find_type); 1116 match_pfx_len = complete_cmd_dir_file(match_buf, find_type);
1117
1118 /* Account for backslashes which will be inserted
1119 * by quote_special_chars() later */
1120 {
1121 const char *e = match_buf + strlen(match_buf);
1122 const char *s = e - match_pfx_len;
1123 while (s < e)
1124 if (is_special_char(*s++))
1125 match_pfx_len++;
1126 }
1127
1103 /* Remove duplicates */ 1128 /* Remove duplicates */
1104 if (matches) { 1129 if (matches) {
1105 unsigned i; 1130 unsigned i, n = 0;
1106 unsigned n = 0;
1107 qsort_string_vector(matches, num_matches); 1131 qsort_string_vector(matches, num_matches);
1108 for (i = 0; i < num_matches - 1; ++i) { 1132 for (i = 0; i < num_matches - 1; ++i) {
1109 //if (matches[i] && matches[i+1]) { /* paranoia */ 1133 //if (matches[i] && matches[i+1]) { /* paranoia */
@@ -1118,6 +1142,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1118 matches[n++] = matches[i]; 1142 matches[n++] = matches[i];
1119 num_matches = n; 1143 num_matches = n;
1120 } 1144 }
1145
1121 /* Did we find exactly one match? */ 1146 /* Did we find exactly one match? */
1122 if (num_matches != 1) { /* no */ 1147 if (num_matches != 1) { /* no */
1123 char *cp; 1148 char *cp;
@@ -1139,7 +1164,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1139 goto ret; /* no */ 1164 goto ret; /* no */
1140 } 1165 }
1141 *cp = '\0'; 1166 *cp = '\0';
1142 cp = add_quote_for_spec_chars(chosen_match); 1167 cp = quote_special_chars(chosen_match);
1143 free(chosen_match); 1168 free(chosen_match);
1144 chosen_match = cp; 1169 chosen_match = cp;
1145 len_found = strlen(chosen_match); 1170 len_found = strlen(chosen_match);
@@ -1147,7 +1172,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1147 /* Next <tab> is not a double-tab */ 1172 /* Next <tab> is not a double-tab */
1148 *lastWasTab = 0; 1173 *lastWasTab = 0;
1149 1174
1150 chosen_match = add_quote_for_spec_chars(matches[0]); 1175 chosen_match = quote_special_chars(matches[0]);
1151 len_found = strlen(chosen_match); 1176 len_found = strlen(chosen_match);
1152 if (chosen_match[len_found-1] != '/') { 1177 if (chosen_match[len_found-1] != '/') {
1153 chosen_match[len_found] = ' '; 1178 chosen_match[len_found] = ' ';
@@ -1155,7 +1180,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1155 } 1180 }
1156 } 1181 }
1157 1182
1158#if !ENABLE_UNICODE_SUPPORT 1183# if !ENABLE_UNICODE_SUPPORT
1159 /* Have space to place the match? */ 1184 /* Have space to place the match? */
1160 /* The result consists of three parts with these lengths: */ 1185 /* The result consists of three parts with these lengths: */
1161 /* cursor + (len_found - match_pfx_len) + (command_len - cursor) */ 1186 /* cursor + (len_found - match_pfx_len) + (command_len - cursor) */
@@ -1172,7 +1197,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1172 /* write out the matched command */ 1197 /* write out the matched command */
1173 redraw(cmdedit_y, command_len - pos); 1198 redraw(cmdedit_y, command_len - pos);
1174 } 1199 }
1175#else 1200# else
1176 { 1201 {
1177 /* Use 2nd half of match_buf as scratch space - see (**) */ 1202 /* Use 2nd half of match_buf as scratch space - see (**) */
1178 char *command = match_buf + MAX_LINELEN; 1203 char *command = match_buf + MAX_LINELEN;
@@ -1196,7 +1221,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1196 redraw(cmdedit_y, pos >= 0 ? pos : 0); 1221 redraw(cmdedit_y, pos >= 0 ? pos : 0);
1197 } 1222 }
1198 } 1223 }
1199#endif 1224# endif
1200 ret: 1225 ret:
1201 free(chosen_match); 1226 free(chosen_match);
1202 free(match_buf); 1227 free(match_buf);
@@ -1342,7 +1367,7 @@ static void save_history(char *str)
1342 int fd; 1367 int fd;
1343 int len, len2; 1368 int len, len2;
1344 1369
1345 fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0666); 1370 fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600);
1346 if (fd < 0) 1371 if (fd < 0)
1347 return; 1372 return;
1348 xlseek(fd, 0, SEEK_END); /* paranoia */ 1373 xlseek(fd, 0, SEEK_END); /* paranoia */
@@ -1357,10 +1382,8 @@ static void save_history(char *str)
1357 /* did we write so much that history file needs trimming? */ 1382 /* did we write so much that history file needs trimming? */
1358 state->cnt_history_in_file++; 1383 state->cnt_history_in_file++;
1359 if (state->cnt_history_in_file > MAX_HISTORY * 4) { 1384 if (state->cnt_history_in_file > MAX_HISTORY * 4) {
1360 FILE *fp;
1361 char *new_name; 1385 char *new_name;
1362 line_input_t *st_temp; 1386 line_input_t *st_temp;
1363 int i;
1364 1387
1365 /* we may have concurrently written entries from others. 1388 /* we may have concurrently written entries from others.
1366 * load them */ 1389 * load them */
@@ -1370,8 +1393,12 @@ static void save_history(char *str)
1370 1393
1371 /* write out temp file and replace hist_file atomically */ 1394 /* write out temp file and replace hist_file atomically */
1372 new_name = xasprintf("%s.%u.new", state->hist_file, (int) getpid()); 1395 new_name = xasprintf("%s.%u.new", state->hist_file, (int) getpid());
1373 fp = fopen_for_write(new_name); 1396 fd = open(state->hist_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1374 if (fp) { 1397 if (fd >= 0) {
1398 FILE *fp;
1399 int i;
1400
1401 fp = xfdopen_for_write(fd);
1375 for (i = 0; i < st_temp->cnt_history; i++) 1402 for (i = 0; i < st_temp->cnt_history; i++)
1376 fprintf(fp, "%s\n", st_temp->history[i]); 1403 fprintf(fp, "%s\n", st_temp->history[i]);
1377 fclose(fp); 1404 fclose(fp);
@@ -1634,7 +1661,7 @@ static void ask_terminal(void)
1634 pfd.events = POLLIN; 1661 pfd.events = POLLIN;
1635 if (safe_poll(&pfd, 1, 0) == 0) { 1662 if (safe_poll(&pfd, 1, 0) == 0) {
1636 S.sent_ESC_br6n = 1; 1663 S.sent_ESC_br6n = 1;
1637 fputs("\033" "[6n", stdout); 1664 fputs(ESC"[6n", stdout);
1638 fflush_all(); /* make terminal see it ASAP! */ 1665 fflush_all(); /* make terminal see it ASAP! */
1639 } 1666 }
1640} 1667}
@@ -2089,7 +2116,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
2089 case CTRL('L'): 2116 case CTRL('L'):
2090 vi_case(CTRL('L')|VI_CMDMODE_BIT:) 2117 vi_case(CTRL('L')|VI_CMDMODE_BIT:)
2091 /* Control-l -- clear screen */ 2118 /* Control-l -- clear screen */
2092 printf("\033[H"); /* cursor to top,left */ 2119 printf(ESC"[H"); /* cursor to top,left */
2093 redraw(0, command_len - cursor); 2120 redraw(0, command_len - cursor);
2094 break; 2121 break;
2095#if MAX_HISTORY > 0 2122#if MAX_HISTORY > 0
diff --git a/libbb/procps.c b/libbb/procps.c
index ec43b221e..fcf86d9bb 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -303,6 +303,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
303 goto got_entry; 303 goto got_entry;
304 closedir(sp->task_dir); 304 closedir(sp->task_dir);
305 sp->task_dir = NULL; 305 sp->task_dir = NULL;
306 sp->main_thread_pid = 0;
306 } 307 }
307#endif 308#endif
308 entry = readdir(sp->dir); 309 entry = readdir(sp->dir);
@@ -322,6 +323,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
322 char task_dir[sizeof("/proc/%u/task") + sizeof(int)*3]; 323 char task_dir[sizeof("/proc/%u/task") + sizeof(int)*3];
323 sprintf(task_dir, "/proc/%u/task", pid); 324 sprintf(task_dir, "/proc/%u/task", pid);
324 sp->task_dir = xopendir(task_dir); 325 sp->task_dir = xopendir(task_dir);
326 sp->main_thread_pid = pid;
325 continue; 327 continue;
326 } 328 }
327#endif 329#endif
diff --git a/libbb/pw_encrypt_sha.c b/libbb/pw_encrypt_sha.c
index 070e0d442..8aeaacad6 100644
--- a/libbb/pw_encrypt_sha.c
+++ b/libbb/pw_encrypt_sha.c
@@ -3,7 +3,7 @@
3 */ 3 */
4 4
5/* Prefix for optional rounds specification. */ 5/* Prefix for optional rounds specification. */
6static const char str_rounds[] = "rounds=%u$"; 6static const char str_rounds[] ALIGN1 = "rounds=%u$";
7 7
8/* Maximum salt string length. */ 8/* Maximum salt string length. */
9#define SALT_LEN_MAX 16 9#define SALT_LEN_MAX 16
@@ -19,8 +19,8 @@ NOINLINE
19sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) 19sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data)
20{ 20{
21 void (*sha_begin)(void *ctx) FAST_FUNC; 21 void (*sha_begin)(void *ctx) FAST_FUNC;
22 void (*sha_hash)(const void *buffer, size_t len, void *ctx) FAST_FUNC; 22 void (*sha_hash)(void *ctx, const void *buffer, size_t len) FAST_FUNC;
23 void (*sha_end)(void *resbuf, void *ctx) FAST_FUNC; 23 void (*sha_end)(void *ctx, void *resbuf) FAST_FUNC;
24 int _32or64; 24 int _32or64;
25 25
26 char *result, *resptr; 26 char *result, *resptr;
@@ -103,40 +103,40 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data)
103 103
104 /* Add KEY, SALT. */ 104 /* Add KEY, SALT. */
105 sha_begin(&ctx); 105 sha_begin(&ctx);
106 sha_hash(key_data, key_len, &ctx); 106 sha_hash(&ctx, key_data, key_len);
107 sha_hash(salt_data, salt_len, &ctx); 107 sha_hash(&ctx, salt_data, salt_len);
108 108
109 /* Compute alternate SHA sum with input KEY, SALT, and KEY. 109 /* Compute alternate SHA sum with input KEY, SALT, and KEY.
110 The final result will be added to the first context. */ 110 The final result will be added to the first context. */
111 sha_begin(&alt_ctx); 111 sha_begin(&alt_ctx);
112 sha_hash(key_data, key_len, &alt_ctx); 112 sha_hash(&alt_ctx, key_data, key_len);
113 sha_hash(salt_data, salt_len, &alt_ctx); 113 sha_hash(&alt_ctx, salt_data, salt_len);
114 sha_hash(key_data, key_len, &alt_ctx); 114 sha_hash(&alt_ctx, key_data, key_len);
115 sha_end(alt_result, &alt_ctx); 115 sha_end(&alt_ctx, alt_result);
116 116
117 /* Add result of this to the other context. */ 117 /* Add result of this to the other context. */
118 /* Add for any character in the key one byte of the alternate sum. */ 118 /* Add for any character in the key one byte of the alternate sum. */
119 for (cnt = key_len; cnt > _32or64; cnt -= _32or64) 119 for (cnt = key_len; cnt > _32or64; cnt -= _32or64)
120 sha_hash(alt_result, _32or64, &ctx); 120 sha_hash(&ctx, alt_result, _32or64);
121 sha_hash(alt_result, cnt, &ctx); 121 sha_hash(&ctx, alt_result, cnt);
122 122
123 /* Take the binary representation of the length of the key and for every 123 /* Take the binary representation of the length of the key and for every
124 1 add the alternate sum, for every 0 the key. */ 124 1 add the alternate sum, for every 0 the key. */
125 for (cnt = key_len; cnt != 0; cnt >>= 1) 125 for (cnt = key_len; cnt != 0; cnt >>= 1)
126 if ((cnt & 1) != 0) 126 if ((cnt & 1) != 0)
127 sha_hash(alt_result, _32or64, &ctx); 127 sha_hash(&ctx, alt_result, _32or64);
128 else 128 else
129 sha_hash(key_data, key_len, &ctx); 129 sha_hash(&ctx, key_data, key_len);
130 130
131 /* Create intermediate result. */ 131 /* Create intermediate result. */
132 sha_end(alt_result, &ctx); 132 sha_end(&ctx, alt_result);
133 133
134 /* Start computation of P byte sequence. */ 134 /* Start computation of P byte sequence. */
135 /* For every character in the password add the entire password. */ 135 /* For every character in the password add the entire password. */
136 sha_begin(&alt_ctx); 136 sha_begin(&alt_ctx);
137 for (cnt = 0; cnt < key_len; ++cnt) 137 for (cnt = 0; cnt < key_len; ++cnt)
138 sha_hash(key_data, key_len, &alt_ctx); 138 sha_hash(&alt_ctx, key_data, key_len);
139 sha_end(temp_result, &alt_ctx); 139 sha_end(&alt_ctx, temp_result);
140 140
141 /* NB: past this point, raw key_data is not used anymore */ 141 /* NB: past this point, raw key_data is not used anymore */
142 142
@@ -153,8 +153,8 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data)
153 /* For every character in the password add the entire password. */ 153 /* For every character in the password add the entire password. */
154 sha_begin(&alt_ctx); 154 sha_begin(&alt_ctx);
155 for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) 155 for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
156 sha_hash(salt_data, salt_len, &alt_ctx); 156 sha_hash(&alt_ctx, salt_data, salt_len);
157 sha_end(temp_result, &alt_ctx); 157 sha_end(&alt_ctx, temp_result);
158 158
159 /* NB: past this point, raw salt_data is not used anymore */ 159 /* NB: past this point, raw salt_data is not used anymore */
160 160
@@ -174,31 +174,31 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data)
174 174
175 /* Add key or last result. */ 175 /* Add key or last result. */
176 if ((cnt & 1) != 0) 176 if ((cnt & 1) != 0)
177 sha_hash(p_bytes, key_len, &ctx); 177 sha_hash(&ctx, p_bytes, key_len);
178 else 178 else
179 sha_hash(alt_result, _32or64, &ctx); 179 sha_hash(&ctx, alt_result, _32or64);
180 /* Add salt for numbers not divisible by 3. */ 180 /* Add salt for numbers not divisible by 3. */
181 if (cnt % 3 != 0) 181 if (cnt % 3 != 0)
182 sha_hash(s_bytes, salt_len, &ctx); 182 sha_hash(&ctx, s_bytes, salt_len);
183 /* Add key for numbers not divisible by 7. */ 183 /* Add key for numbers not divisible by 7. */
184 if (cnt % 7 != 0) 184 if (cnt % 7 != 0)
185 sha_hash(p_bytes, key_len, &ctx); 185 sha_hash(&ctx, p_bytes, key_len);
186 /* Add key or last result. */ 186 /* Add key or last result. */
187 if ((cnt & 1) != 0) 187 if ((cnt & 1) != 0)
188 sha_hash(alt_result, _32or64, &ctx); 188 sha_hash(&ctx, alt_result, _32or64);
189 else 189 else
190 sha_hash(p_bytes, key_len, &ctx); 190 sha_hash(&ctx, p_bytes, key_len);
191 191
192 sha_end(alt_result, &ctx); 192 sha_end(&ctx, alt_result);
193 } 193 }
194 194
195 /* Append encrypted password to result buffer */ 195 /* Append encrypted password to result buffer */
196//TODO: replace with something like 196//TODO: replace with something like
197// bb_uuencode(cp, src, length, bb_uuenc_tbl_XXXbase64); 197// bb_uuencode(cp, src, length, bb_uuenc_tbl_XXXbase64);
198#define b64_from_24bit(B2, B1, B0, N) \ 198#define b64_from_24bit(B2, B1, B0, N) \
199do { \ 199do { \
200 unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \ 200 unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \
201 resptr = to64(resptr, w, N); \ 201 resptr = to64(resptr, w, N); \
202} while (0) 202} while (0)
203 if (is_sha512 == '5') { 203 if (is_sha512 == '5') {
204 unsigned i = 0; 204 unsigned i = 0;
diff --git a/libbb/read_printf.c b/libbb/read_printf.c
index 7ca3d68c3..8664bc625 100644
--- a/libbb/read_printf.c
+++ b/libbb/read_printf.c
@@ -15,7 +15,7 @@
15) 15)
16 16
17#if ZIPPED 17#if ZIPPED
18# include "unarchive.h" 18# include "archive.h"
19#endif 19#endif
20 20
21 21
diff --git a/libbb/simplify_path.c b/libbb/simplify_path.c
index 3818d32be..89dc5bdf2 100644
--- a/libbb/simplify_path.c
+++ b/libbb/simplify_path.c
@@ -15,17 +15,17 @@ char* FAST_FUNC bb_simplify_abs_path_inplace(char *start)
15 p = s = start; 15 p = s = start;
16 do { 16 do {
17 if (*p == '/') { 17 if (*p == '/') {
18 if (*s == '/') { /* skip duplicate (or initial) slash */ 18 if (*s == '/') { /* skip duplicate (or initial) slash */
19 continue; 19 continue;
20 } 20 }
21 if (*s == '.') { 21 if (*s == '.') {
22 if (s[1] == '/' || !s[1]) { /* remove extra '.' */ 22 if (s[1] == '/' || !s[1]) { /* remove extra '.' */
23 continue; 23 continue;
24 } 24 }
25 if ((s[1] == '.') && (s[2] == '/' || !s[2])) { 25 if ((s[1] == '.') && (s[2] == '/' || !s[2])) {
26 ++s; 26 ++s;
27 if (p > start) { 27 if (p > start) {
28 while (*--p != '/') /* omit previous dir */ 28 while (*--p != '/') /* omit previous dir */
29 continue; 29 continue;
30 } 30 }
31 continue; 31 continue;
@@ -35,8 +35,8 @@ char* FAST_FUNC bb_simplify_abs_path_inplace(char *start)
35 *++p = *s; 35 *++p = *s;
36 } while (*++s); 36 } while (*++s);
37 37
38 if ((p == start) || (*p != '/')) { /* not a trailing slash */ 38 if ((p == start) || (*p != '/')) { /* not a trailing slash */
39 ++p; /* so keep last character */ 39 ++p; /* so keep last character */
40 } 40 }
41 *p = '\0'; 41 *p = '\0';
42 return p; 42 return p;
diff --git a/libbb/time.c b/libbb/time.c
index 2a74d34c2..1eb2d75c2 100644
--- a/libbb/time.c
+++ b/libbb/time.c
@@ -93,6 +93,7 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
93 * 93 *
94 * This coincides with the format of "touch -t TIME" 94 * This coincides with the format of "touch -t TIME"
95 */ 95 */
96 unsigned cur_year = ptm->tm_year;
96 int len = strchrnul(date_str, '.') - date_str; 97 int len = strchrnul(date_str, '.') - date_str;
97 98
98 /* MM[.SS] */ 99 /* MM[.SS] */
@@ -133,6 +134,17 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
133 &end) >= 5) { 134 &end) >= 5) {
134 /* Adjust month from 1-12 to 0-11 */ 135 /* Adjust month from 1-12 to 0-11 */
135 ptm->tm_mon -= 1; 136 ptm->tm_mon -= 1;
137 if ((int)cur_year >= 50) { /* >= 1950 */
138 /* Adjust year: */
139 /* 1. Put it in the current century */
140 ptm->tm_year += (cur_year / 100) * 100;
141 /* 2. If too far in the past, +100 years */
142 if (ptm->tm_year < cur_year - 50)
143 ptm->tm_year += 100;
144 /* 3. If too far in the future, -100 years */
145 if (ptm->tm_year > cur_year + 50)
146 ptm->tm_year -= 100;
147 }
136 } else 148 } else
137 /* ccyymmddHHMM[.SS] */ 149 /* ccyymmddHHMM[.SS] */
138 if (len == 12 && sscanf(date_str, "%4u%2u%2u%2u%2u%c", 150 if (len == 12 && sscanf(date_str, "%4u%2u%2u%2u%2u%c",
diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c
index 9263859f5..8c78f5e20 100644
--- a/libbb/u_signal_names.c
+++ b/libbb/u_signal_names.c
@@ -7,6 +7,13 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9 9
10//config:config FEATURE_RTMINMAX
11//config: bool "Support RTMIN[+n] and RTMAX[-n] signal names"
12//config: default y
13//config: help
14//config: Support RTMIN[+n] and RTMAX[-n] signal names
15//config: in kill, killall etc. This costs ~250 bytes.
16
10#include "libbb.h" 17#include "libbb.h"
11 18
12/* Believe it or not, but some arches have more than 32 SIGs! 19/* Believe it or not, but some arches have more than 32 SIGs!
@@ -117,6 +124,16 @@ static const char signals[][7] = {
117#ifdef SIGSYS 124#ifdef SIGSYS
118 [SIGSYS ] = "SYS", 125 [SIGSYS ] = "SYS",
119#endif 126#endif
127#if ENABLE_FEATURE_RTMINMAX
128# ifdef __SIGRTMIN
129 [__SIGRTMIN] = "RTMIN",
130# endif
131// This makes array about x2 bigger.
132// More compact approach is to special-case SIGRTMAX in print_signames()
133//# ifdef __SIGRTMAX
134// [__SIGRTMAX] = "RTMAX",
135//# endif
136#endif
120}; 137};
121 138
122// Convert signal name to number. 139// Convert signal name to number.
@@ -134,20 +151,54 @@ int FAST_FUNC get_signum(const char *name)
134 if (strcasecmp(name, signals[i]) == 0) 151 if (strcasecmp(name, signals[i]) == 0)
135 return i; 152 return i;
136 153
137#if ENABLE_DESKTOP && (defined(SIGIOT) || defined(SIGIO)) 154#if ENABLE_DESKTOP
155# if defined(SIGIOT) || defined(SIGIO)
138 /* SIGIO[T] are aliased to other names, 156 /* SIGIO[T] are aliased to other names,
139 * thus cannot be stored in the signals[] array. 157 * thus cannot be stored in the signals[] array.
140 * Need special code to recognize them */ 158 * Need special code to recognize them */
141 if ((name[0] | 0x20) == 'i' && (name[1] | 0x20) == 'o') { 159 if ((name[0] | 0x20) == 'i' && (name[1] | 0x20) == 'o') {
142#ifdef SIGIO 160# ifdef SIGIO
143 if (!name[2]) 161 if (!name[2])
144 return SIGIO; 162 return SIGIO;
145#endif 163# endif
146#ifdef SIGIOT 164# ifdef SIGIOT
147 if ((name[2] | 0x20) == 't' && !name[3]) 165 if ((name[2] | 0x20) == 't' && !name[3])
148 return SIGIOT; 166 return SIGIOT;
149#endif 167# endif
150 } 168 }
169# endif
170#endif
171
172#if ENABLE_FEATURE_RTMINMAX
173# if defined(SIGRTMIN) && defined(SIGRTMAX)
174/* libc may use some rt sigs for pthreads and therefore "remap" SIGRTMIN/MAX,
175 * but we want to use "raw" SIGRTMIN/MAX. Underscored names, if exist, provide
176 * them. If they don't exist, fall back to non-underscored ones: */
177# if !defined(__SIGRTMIN)
178# define __SIGRTMIN SIGRTMIN
179# endif
180# if !defined(__SIGRTMAX)
181# define __SIGRTMAX SIGRTMAX
182# endif
183 if (strncasecmp(name, "RTMIN", 5) == 0) {
184 if (!name[5])
185 return __SIGRTMIN;
186 if (name[5] == '+') {
187 i = bb_strtou(name + 6, NULL, 10);
188 if (!errno && i <= __SIGRTMAX - __SIGRTMIN)
189 return __SIGRTMIN + i;
190 }
191 }
192 else if (strncasecmp(name, "RTMAX", 5) == 0) {
193 if (!name[5])
194 return __SIGRTMAX;
195 if (name[5] == '-') {
196 i = bb_strtou(name + 6, NULL, 10);
197 if (!errno && i <= __SIGRTMAX - __SIGRTMIN)
198 return __SIGRTMAX - i;
199 }
200 }
201# endif
151#endif 202#endif
152 203
153 return -1; 204 return -1;
@@ -175,6 +226,11 @@ void FAST_FUNC print_signames(void)
175 for (signo = 1; signo < ARRAY_SIZE(signals); signo++) { 226 for (signo = 1; signo < ARRAY_SIZE(signals); signo++) {
176 const char *name = signals[signo]; 227 const char *name = signals[signo];
177 if (name[0]) 228 if (name[0])
178 puts(name); 229 printf("%2u) %s\n", signo, name);
179 } 230 }
231#if ENABLE_FEATURE_RTMINMAX
232# ifdef __SIGRTMAX
233 printf("%2u) %s\n", __SIGRTMAX, "RTMAX");
234# endif
235#endif
180} 236}
diff --git a/libbb/unicode.c b/libbb/unicode.c
index 70c6abe00..cf0c6bed9 100644
--- a/libbb/unicode.c
+++ b/libbb/unicode.c
@@ -1005,8 +1005,11 @@ static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t *stats, const char
1005 d++; 1005 d++;
1006 } 1006 }
1007 } 1007 }
1008 if (stats) 1008 if (stats) {
1009 stats->byte_count = stats->unicode_count = (d - dst); 1009 stats->byte_count = (d - dst);
1010 stats->unicode_count = (d - dst);
1011 stats->unicode_width = (d - dst);
1012 }
1010 return dst; 1013 return dst;
1011 } 1014 }
1012 1015
diff --git a/libbb/update_passwd.c b/libbb/update_passwd.c
index dc5029223..a30af6f72 100644
--- a/libbb/update_passwd.c
+++ b/libbb/update_passwd.c
@@ -58,7 +58,7 @@ static void check_selinux_update_passwd(const char *username)
58 6) delete a user from a group: update_passwd(FILE, GROUP, NULL, MEMBER) 58 6) delete a user from a group: update_passwd(FILE, GROUP, NULL, MEMBER)
59 only if CONFIG_FEATURE_DEL_USER_FROM_GROUP=y and member != NULL 59 only if CONFIG_FEATURE_DEL_USER_FROM_GROUP=y and member != NULL
60 60
61 7) change user's passord: update_passwd(FILE, USER, NEW_PASSWD, NULL) 61 7) change user's password: update_passwd(FILE, USER, NEW_PASSWD, NULL)
62 only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd 62 only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd
63 or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd 63 or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd
64 64
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 07504b75b..a02a504b0 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -234,7 +234,7 @@ static int wh_helper(int value, int def_val, const char *env_name, int *err)
234 char *s = getenv(env_name); 234 char *s = getenv(env_name);
235 if (s) { 235 if (s) {
236 value = atoi(s); 236 value = atoi(s);
237 /* If LINES/COLUMNS are set, pretent that there is 237 /* If LINES/COLUMNS are set, pretend that there is
238 * no error getting w/h, this prevents some ugly 238 * no error getting w/h, this prevents some ugly
239 * cursor tricks by our callers */ 239 * cursor tricks by our callers */
240 *err = 0; 240 *err = 0;