aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/appletlib.c9
-rw-r--r--libbb/bb_strtonum.c59
-rw-r--r--libbb/dump.c25
-rw-r--r--libbb/find_mount_point.c3
-rw-r--r--libbb/isdirectory.c15
-rw-r--r--libbb/lineedit.c15
-rw-r--r--libbb/parse_config.c2
-rw-r--r--libbb/procps.c16
-rw-r--r--libbb/read_printf.c139
-rw-r--r--libbb/vfork_daemon_rexec.c10
-rw-r--r--libbb/xconnect.c16
-rw-r--r--libbb/xfuncs_printf.c1
12 files changed, 105 insertions, 205 deletions
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 0c675db4d..116e275be 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -632,7 +632,10 @@ static int busybox_main(char **argv)
632 "See source distribution for full notice.\n" 632 "See source distribution for full notice.\n"
633 "\n" 633 "\n"
634 "Usage: busybox [function] [arguments]...\n" 634 "Usage: busybox [function] [arguments]...\n"
635 " or: busybox --list[-full]\n" 635 " or: busybox --list"IF_FEATURE_INSTALLER("[-full]")"\n"
636 IF_FEATURE_INSTALLER(
637 " or: busybox --install [-s] [DIR]\n"
638 )
636 " or: function [arguments]...\n" 639 " or: function [arguments]...\n"
637 "\n" 640 "\n"
638 "\tBusyBox is a multi-call binary that combines many common Unix\n" 641 "\tBusyBox is a multi-call binary that combines many common Unix\n"
@@ -672,7 +675,7 @@ static int busybox_main(char **argv)
672 dup2(1, 2); 675 dup2(1, 2);
673 while (*a) { 676 while (*a) {
674# if ENABLE_FEATURE_INSTALLER 677# if ENABLE_FEATURE_INSTALLER
675 if (argv[1][6]) /* --list-path? */ 678 if (argv[1][6]) /* --list-full? */
676 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); 679 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1);
677# endif 680# endif
678 full_write2_str(a); 681 full_write2_str(a);
@@ -702,7 +705,7 @@ static int busybox_main(char **argv)
702 * -s: make symlinks 705 * -s: make symlinks
703 * DIR: directory to install links to 706 * DIR: directory to install links to
704 */ 707 */
705 use_symbolic_links = (argv[2] && strcmp(argv[2], "-s") == 0 && argv++); 708 use_symbolic_links = (argv[2] && strcmp(argv[2], "-s") == 0 && ++argv);
706 install_links(busybox, use_symbolic_links, argv[2]); 709 install_links(busybox, use_symbolic_links, argv[2]);
707 return 0; 710 return 0;
708 } 711 }
diff --git a/libbb/bb_strtonum.c b/libbb/bb_strtonum.c
index c66c774f4..949f26bee 100644
--- a/libbb/bb_strtonum.c
+++ b/libbb/bb_strtonum.c
@@ -36,14 +36,14 @@ static unsigned long long ret_ERANGE(void)
36 return ULLONG_MAX; 36 return ULLONG_MAX;
37} 37}
38 38
39static unsigned long long handle_errors(unsigned long long v, char **endp, char *endptr) 39static unsigned long long handle_errors(unsigned long long v, char **endp)
40{ 40{
41 if (endp) *endp = endptr; 41 char next_ch = **endp;
42 42
43 /* errno is already set to ERANGE by strtoXXX if value overflowed */ 43 /* errno is already set to ERANGE by strtoXXX if value overflowed */
44 if (endptr[0]) { 44 if (next_ch) {
45 /* "1234abcg" or out-of-range? */ 45 /* "1234abcg" or out-of-range? */
46 if (isalnum(endptr[0]) || errno) 46 if (isalnum(next_ch) || errno)
47 return ret_ERANGE(); 47 return ret_ERANGE();
48 /* good number, just suspicious terminator */ 48 /* good number, just suspicious terminator */
49 errno = EINVAL; 49 errno = EINVAL;
@@ -57,30 +57,37 @@ unsigned long long FAST_FUNC bb_strtoull(const char *arg, char **endp, int base)
57 unsigned long long v; 57 unsigned long long v;
58 char *endptr; 58 char *endptr;
59 59
60 if (!endp) endp = &endptr;
61 *endp = (char*) arg;
62
60 /* strtoul(" -4200000000") returns 94967296, errno 0 (!) */ 63 /* strtoul(" -4200000000") returns 94967296, errno 0 (!) */
61 /* I don't think that this is right. Preventing this... */ 64 /* I don't think that this is right. Preventing this... */
62 if (!isalnum(arg[0])) return ret_ERANGE(); 65 if (!isalnum(arg[0])) return ret_ERANGE();
63 66
64 /* not 100% correct for lib func, but convenient for the caller */ 67 /* not 100% correct for lib func, but convenient for the caller */
65 errno = 0; 68 errno = 0;
66 v = strtoull(arg, &endptr, base); 69 v = strtoull(arg, endp, base);
67 return handle_errors(v, endp, endptr); 70 return handle_errors(v, endp);
68} 71}
69 72
70long long FAST_FUNC bb_strtoll(const char *arg, char **endp, int base) 73long long FAST_FUNC bb_strtoll(const char *arg, char **endp, int base)
71{ 74{
72 unsigned long long v; 75 unsigned long long v;
73 char *endptr; 76 char *endptr;
77 char first;
78
79 if (!endp) endp = &endptr;
80 *endp = (char*) arg;
74 81
75 /* Check for the weird "feature": 82 /* Check for the weird "feature":
76 * a "-" string is apparently a valid "number" for strto[u]l[l]! 83 * a "-" string is apparently a valid "number" for strto[u]l[l]!
77 * It returns zero and errno is 0! :( */ 84 * It returns zero and errno is 0! :( */
78 char first = (arg[0] != '-' ? arg[0] : arg[1]); 85 first = (arg[0] != '-' ? arg[0] : arg[1]);
79 if (!isalnum(first)) return ret_ERANGE(); 86 if (!isalnum(first)) return ret_ERANGE();
80 87
81 errno = 0; 88 errno = 0;
82 v = strtoll(arg, &endptr, base); 89 v = strtoll(arg, endp, base);
83 return handle_errors(v, endp, endptr); 90 return handle_errors(v, endp);
84} 91}
85 92
86#if ULONG_MAX != ULLONG_MAX 93#if ULONG_MAX != ULLONG_MAX
@@ -89,23 +96,30 @@ unsigned long FAST_FUNC bb_strtoul(const char *arg, char **endp, int base)
89 unsigned long v; 96 unsigned long v;
90 char *endptr; 97 char *endptr;
91 98
99 if (!endp) endp = &endptr;
100 *endp = (char*) arg;
101
92 if (!isalnum(arg[0])) return ret_ERANGE(); 102 if (!isalnum(arg[0])) return ret_ERANGE();
93 errno = 0; 103 errno = 0;
94 v = strtoul(arg, &endptr, base); 104 v = strtoul(arg, endp, base);
95 return handle_errors(v, endp, endptr); 105 return handle_errors(v, endp);
96} 106}
97 107
98long FAST_FUNC bb_strtol(const char *arg, char **endp, int base) 108long FAST_FUNC bb_strtol(const char *arg, char **endp, int base)
99{ 109{
100 long v; 110 long v;
101 char *endptr; 111 char *endptr;
112 char first;
102 113
103 char first = (arg[0] != '-' ? arg[0] : arg[1]); 114 if (!endp) endp = &endptr;
115 *endp = (char*) arg;
116
117 first = (arg[0] != '-' ? arg[0] : arg[1]);
104 if (!isalnum(first)) return ret_ERANGE(); 118 if (!isalnum(first)) return ret_ERANGE();
105 119
106 errno = 0; 120 errno = 0;
107 v = strtol(arg, &endptr, base); 121 v = strtol(arg, endp, base);
108 return handle_errors(v, endp, endptr); 122 return handle_errors(v, endp);
109} 123}
110#endif 124#endif
111 125
@@ -115,25 +129,32 @@ unsigned FAST_FUNC bb_strtou(const char *arg, char **endp, int base)
115 unsigned long v; 129 unsigned long v;
116 char *endptr; 130 char *endptr;
117 131
132 if (!endp) endp = &endptr;
133 *endp = (char*) arg;
134
118 if (!isalnum(arg[0])) return ret_ERANGE(); 135 if (!isalnum(arg[0])) return ret_ERANGE();
119 errno = 0; 136 errno = 0;
120 v = strtoul(arg, &endptr, base); 137 v = strtoul(arg, endp, base);
121 if (v > UINT_MAX) return ret_ERANGE(); 138 if (v > UINT_MAX) return ret_ERANGE();
122 return handle_errors(v, endp, endptr); 139 return handle_errors(v, endp);
123} 140}
124 141
125int FAST_FUNC bb_strtoi(const char *arg, char **endp, int base) 142int FAST_FUNC bb_strtoi(const char *arg, char **endp, int base)
126{ 143{
127 long v; 144 long v;
128 char *endptr; 145 char *endptr;
146 char first;
147
148 if (!endp) endp = &endptr;
149 *endp = (char*) arg;
129 150
130 char first = (arg[0] != '-' ? arg[0] : arg[1]); 151 first = (arg[0] != '-' ? arg[0] : arg[1]);
131 if (!isalnum(first)) return ret_ERANGE(); 152 if (!isalnum(first)) return ret_ERANGE();
132 153
133 errno = 0; 154 errno = 0;
134 v = strtol(arg, &endptr, base); 155 v = strtol(arg, endp, base);
135 if (v > INT_MAX) return ret_ERANGE(); 156 if (v > INT_MAX) return ret_ERANGE();
136 if (v < INT_MIN) return ret_ERANGE(); 157 if (v < INT_MIN) return ret_ERANGE();
137 return handle_errors(v, endp, endptr); 158 return handle_errors(v, endp);
138} 159}
139#endif 160#endif
diff --git a/libbb/dump.c b/libbb/dump.c
index 919fe135c..7e435643b 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -71,7 +71,8 @@ static NOINLINE int bb_dump_size(FS *fs)
71 * skip any special chars -- save precision in 71 * skip any special chars -- save precision in
72 * case it's a %s format. 72 * case it's a %s format.
73 */ 73 */
74 while (strchr(index_str + 1, *++fmt)); 74 while (strchr(index_str + 1, *++fmt))
75 continue;
75 if (*fmt == '.' && isdigit(*++fmt)) { 76 if (*fmt == '.' && isdigit(*++fmt)) {
76 prec = atoi(fmt); 77 prec = atoi(fmt);
77 while (isdigit(*++fmt)) 78 while (isdigit(*++fmt))
@@ -99,8 +100,8 @@ static NOINLINE int bb_dump_size(FS *fs)
99static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) 100static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
100{ 101{
101 enum { NOTOKAY, USEBCNT, USEPREC } sokay; 102 enum { NOTOKAY, USEBCNT, USEPREC } sokay;
102 PR *pr;
103 FU *fu; 103 FU *fu;
104 PR *pr;
104 char *p1, *p2, *p3; 105 char *p1, *p2, *p3;
105 char savech, *fmtp; 106 char savech, *fmtp;
106 const char *byte_count_str; 107 const char *byte_count_str;
@@ -292,16 +293,18 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
292 * interprets any data at all, and has no iteration count, 293 * interprets any data at all, and has no iteration count,
293 * repeat it as necessary. 294 * repeat it as necessary.
294 * 295 *
295 * if, rep count is greater than 1, no trailing whitespace 296 * if rep count is greater than 1, no trailing whitespace
296 * gets output from the last iteration of the format unit. 297 * gets output from the last iteration of the format unit.
297 */ 298 */
298 for (fu = fs->nextfu; fu; fu = fu->nextfu) { 299 for (fu = fs->nextfu; fu; fu = fu->nextfu) {
299 if (!fu->nextfu && fs->bcnt < dumper->blocksize 300 if (!fu->nextfu
300 && !(fu->flags & F_SETREP) && fu->bcnt 301 && fs->bcnt < dumper->blocksize
302 && !(fu->flags & F_SETREP)
303 && fu->bcnt
301 ) { 304 ) {
302 fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt; 305 fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt;
303 } 306 }
304 if (fu->reps > 1) { 307 if (fu->reps > 1 && fu->nextpr) {
305 for (pr = fu->nextpr;; pr = pr->nextpr) 308 for (pr = fu->nextpr;; pr = pr->nextpr)
306 if (!pr->nextpr) 309 if (!pr->nextpr)
307 break; 310 break;
@@ -721,7 +724,7 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt)
721 p = fmt; 724 p = fmt;
722 for (;;) { 725 for (;;) {
723 p = skip_whitespace(p); 726 p = skip_whitespace(p);
724 if (!*p) { 727 if (*p == '\0') {
725 break; 728 break;
726 } 729 }
727 730
@@ -749,7 +752,7 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt)
749 752
750 /* skip slash and trailing white space */ 753 /* skip slash and trailing white space */
751 if (*p == '/') { 754 if (*p == '/') {
752 p = skip_whitespace(++p); 755 p = skip_whitespace(p + 1);
753 } 756 }
754 757
755 /* byte count */ 758 /* byte count */
@@ -763,7 +766,7 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt)
763 } 766 }
764 tfu->bcnt = atoi(savep); 767 tfu->bcnt = atoi(savep);
765 /* skip trailing white space */ 768 /* skip trailing white space */
766 p = skip_whitespace(++p); 769 p = skip_whitespace(p + 1);
767 } 770 }
768 771
769 /* format */ 772 /* format */
@@ -771,7 +774,7 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt)
771 bb_error_msg_and_die("bad format {%s}", fmt); 774 bb_error_msg_and_die("bad format {%s}", fmt);
772 } 775 }
773 for (savep = ++p; *p != '"';) { 776 for (savep = ++p; *p != '"';) {
774 if (*p++ == 0) { 777 if (*p++ == '\0') {
775 bb_error_msg_and_die("bad format {%s}", fmt); 778 bb_error_msg_and_die("bad format {%s}", fmt);
776 } 779 }
777 } 780 }
@@ -782,7 +785,7 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt)
782 785
783 /* alphabetic escape sequences have to be done in place */ 786 /* alphabetic escape sequences have to be done in place */
784 for (p2 = p1;; ++p1, ++p2) { 787 for (p2 = p1;; ++p1, ++p2) {
785 if (!*p1) { 788 if (*p1 == '\0') {
786 *p2 = *p1; 789 *p2 = *p1;
787 break; 790 break;
788 } 791 }
diff --git a/libbb/find_mount_point.c b/libbb/find_mount_point.c
index 56637ad92..9676b5f52 100644
--- a/libbb/find_mount_point.c
+++ b/libbb/find_mount_point.c
@@ -30,7 +30,8 @@ struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too)
30 30
31 devno_of_name = s.st_dev; 31 devno_of_name = s.st_dev;
32 block_dev = 0; 32 block_dev = 0;
33 if (S_ISBLK(s.st_mode)) { 33 /* Why S_ISCHR? - UBI volumes use char devices, not block */
34 if (S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode)) {
34 devno_of_name = s.st_rdev; 35 devno_of_name = s.st_rdev;
35 block_dev = 1; 36 block_dev = 1;
36 } 37 }
diff --git a/libbb/isdirectory.c b/libbb/isdirectory.c
index 9861be6f8..ba6c52ce8 100644
--- a/libbb/isdirectory.c
+++ b/libbb/isdirectory.c
@@ -15,22 +15,17 @@
15 * Return TRUE if fileName is a directory. 15 * Return TRUE if fileName is a directory.
16 * Nonexistent files return FALSE. 16 * Nonexistent files return FALSE.
17 */ 17 */
18int FAST_FUNC is_directory(const char *fileName, int followLinks, struct stat *statBuf) 18int FAST_FUNC is_directory(const char *fileName, int followLinks)
19{ 19{
20 int status; 20 int status;
21 struct stat astatBuf; 21 struct stat statBuf;
22
23 if (statBuf == NULL) {
24 /* use auto stack buffer */
25 statBuf = &astatBuf;
26 }
27 22
28 if (followLinks) 23 if (followLinks)
29 status = stat(fileName, statBuf); 24 status = stat(fileName, &statBuf);
30 else 25 else
31 status = lstat(fileName, statBuf); 26 status = lstat(fileName, &statBuf);
32 27
33 status = (status == 0 && S_ISDIR(statBuf->st_mode)); 28 status = (status == 0 && S_ISDIR(statBuf.st_mode));
34 29
35 return status; 30 return status;
36} 31}
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index c89c829ed..78244c395 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -2221,14 +2221,17 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2221#define command command_must_not_be_used 2221#define command command_must_not_be_used
2222 2222
2223 new_settings = initial_settings; 2223 new_settings = initial_settings;
2224 new_settings.c_lflag &= ~ICANON; /* unbuffered input */ 2224 /* ~ICANON: unbuffered input (most c_cc[] are disabled, VMIN/VTIME are enabled) */
2225 /* Turn off echoing and CTRL-C, so we can trap it */ 2225 /* ~ECHO, ~ECHONL: turn off echoing, including newline echoing */
2226 new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG); 2226 /* ~ISIG: turn off INTR (ctrl-C), QUIT, SUSP */
2227 /* Hmm, in linux c_cc[] is not parsed if ICANON is off */ 2227 new_settings.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG);
2228 /* reads would block only if < 1 char is available */
2228 new_settings.c_cc[VMIN] = 1; 2229 new_settings.c_cc[VMIN] = 1;
2230 /* no timeout (reads block forever) */
2229 new_settings.c_cc[VTIME] = 0; 2231 new_settings.c_cc[VTIME] = 0;
2230 /* Turn off CTRL-C, so we can trap it */ 2232 /* Should be not needed if ISIG is off: */
2231 new_settings.c_cc[VINTR] = _POSIX_VDISABLE; 2233 /* Turn off CTRL-C */
2234 /* new_settings.c_cc[VINTR] = _POSIX_VDISABLE; */
2232 tcsetattr_stdin_TCSANOW(&new_settings); 2235 tcsetattr_stdin_TCSANOW(&new_settings);
2233 2236
2234#if ENABLE_USERNAME_OR_HOMEDIR 2237#if ENABLE_USERNAME_OR_HOMEDIR
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index cf5ba4deb..1590d9a4c 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -204,7 +204,7 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
204 line += strcspn(line, delims[0] ? delims : delims + 1); 204 line += strcspn(line, delims[0] ? delims : delims + 1);
205 } else { 205 } else {
206 /* Combining, find comment char if any */ 206 /* Combining, find comment char if any */
207 line = strchrnul(line, delims[0]); 207 line = strchrnul(line, PARSE_EOL_COMMENTS ? delims[0] : '\0');
208 208
209 /* Trim any extra delimiters from the end */ 209 /* Trim any extra delimiters from the end */
210 if (flags & PARSE_TRIM) { 210 if (flags & PARSE_TRIM) {
diff --git a/libbb/procps.c b/libbb/procps.c
index 39ddd2c12..dbae46e33 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -128,10 +128,11 @@ static unsigned long fast_strtoul_16(char **endptr)
128 char *str = *endptr; 128 char *str = *endptr;
129 unsigned long n = 0; 129 unsigned long n = 0;
130 130
131 while ((c = *str++) != ' ') { 131 /* Need to stop on both ' ' and '\n' */
132 while ((c = *str++) > ' ') {
132 c = ((c|0x20) - '0'); 133 c = ((c|0x20) - '0');
133 if (c > 9) 134 if (c > 9)
134 // c = c + '0' - 'a' + 10: 135 /* c = c + '0' - 'a' + 10: */
135 c = c - ('a' - '0' - 10); 136 c = c - ('a' - '0' - 10);
136 n = n*16 + c; 137 n = n*16 + c;
137 } 138 }
@@ -144,11 +145,12 @@ static unsigned long fast_strtoul_16(char **endptr)
144/* We cut a lot of corners here for speed */ 145/* We cut a lot of corners here for speed */
145static unsigned long fast_strtoul_10(char **endptr) 146static unsigned long fast_strtoul_10(char **endptr)
146{ 147{
147 char c; 148 unsigned char c;
148 char *str = *endptr; 149 char *str = *endptr;
149 unsigned long n = *str - '0'; 150 unsigned long n = *str - '0';
150 151
151 while ((c = *++str) != ' ') 152 /* Need to stop on both ' ' and '\n' */
153 while ((c = *++str) > ' ')
152 n = n*10 + (c - '0'); 154 n = n*10 + (c - '0');
153 155
154 *endptr = str + 1; /* We skip trailing space! */ 156 *endptr = str + 1; /* We skip trailing space! */
@@ -199,7 +201,7 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
199 memset(&currec, 0, sizeof(currec)); 201 memset(&currec, 0, sizeof(currec));
200 while (fgets(buf, PROCPS_BUFSIZE, file)) { 202 while (fgets(buf, PROCPS_BUFSIZE, file)) {
201 // Each mapping datum has this form: 203 // Each mapping datum has this form:
202 // f7d29000-f7d39000 rw-s ADR M:m OFS FILE 204 // f7d29000-f7d39000 rw-s FILEOFS M:m INODE FILENAME
203 // Size: nnn kB 205 // Size: nnn kB
204 // Rss: nnn kB 206 // Rss: nnn kB
205 // ..... 207 // .....
@@ -224,7 +226,7 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
224 tp = strchr(buf, '-'); 226 tp = strchr(buf, '-');
225 if (tp) { 227 if (tp) {
226 // We reached next mapping - the line of this form: 228 // We reached next mapping - the line of this form:
227 // f7d29000-f7d39000 rw-s ADR M:m OFS FILE 229 // f7d29000-f7d39000 rw-s FILEOFS M:m INODE FILENAME
228 230
229 if (cb) { 231 if (cb) {
230 /* If we have a previous record, there's nothing more 232 /* If we have a previous record, there's nothing more
@@ -243,7 +245,7 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
243 245
244 strncpy(currec.smap_mode, tp, sizeof(currec.smap_mode)-1); 246 strncpy(currec.smap_mode, tp, sizeof(currec.smap_mode)-1);
245 247
246 // skipping "rw-s ADR M:m OFS " 248 // skipping "rw-s FILEOFS M:m INODE "
247 tp = skip_whitespace(skip_fields(tp, 4)); 249 tp = skip_whitespace(skip_fields(tp, 4));
248 // filter out /dev/something (something != zero) 250 // filter out /dev/something (something != zero)
249 if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) { 251 if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) {
diff --git a/libbb/read_printf.c b/libbb/read_printf.c
index 0bbf7802a..5ed6e3632 100644
--- a/libbb/read_printf.c
+++ b/libbb/read_printf.c
@@ -8,16 +8,6 @@
8 */ 8 */
9#include "libbb.h" 9#include "libbb.h"
10 10
11#define ZIPPED (ENABLE_FEATURE_SEAMLESS_LZMA \
12 || ENABLE_FEATURE_SEAMLESS_BZ2 \
13 || ENABLE_FEATURE_SEAMLESS_GZ \
14 /* || ENABLE_FEATURE_SEAMLESS_Z */ \
15)
16
17#if ZIPPED
18# include "bb_archive.h"
19#endif
20
21 11
22/* Suppose that you are a shell. You start child processes. 12/* Suppose that you are a shell. You start child processes.
23 * They work and eventually exit. You want to get user input. 13 * They work and eventually exit. You want to get user input.
@@ -244,132 +234,3 @@ void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p)
244 bb_perror_msg_and_die("can't read '%s'", filename); 234 bb_perror_msg_and_die("can't read '%s'", filename);
245 return buf; 235 return buf;
246} 236}
247
248/* Used by e.g. rpm which gives us a fd without filename,
249 * thus we can't guess the format from filename's extension.
250 */
251#if ZIPPED
252void FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/)
253{
254 const int fail_if_not_detected = 1;
255 union {
256 uint8_t b[4];
257 uint16_t b16[2];
258 uint32_t b32[1];
259 } magic;
260 int offset = -2;
261# if BB_MMU
262 IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd);
263 enum { xformer_prog = 0 };
264# else
265 enum { xformer = 0 };
266 const char *xformer_prog;
267# endif
268
269 /* .gz and .bz2 both have 2-byte signature, and their
270 * unpack_XXX_stream wants this header skipped. */
271 xread(fd, magic.b16, sizeof(magic.b16[0]));
272 if (ENABLE_FEATURE_SEAMLESS_GZ
273 && magic.b16[0] == GZIP_MAGIC
274 ) {
275# if BB_MMU
276 xformer = unpack_gz_stream;
277# else
278 xformer_prog = "gunzip";
279# endif
280 goto found_magic;
281 }
282 if (ENABLE_FEATURE_SEAMLESS_BZ2
283 && magic.b16[0] == BZIP2_MAGIC
284 ) {
285# if BB_MMU
286 xformer = unpack_bz2_stream;
287# else
288 xformer_prog = "bunzip2";
289# endif
290 goto found_magic;
291 }
292 if (ENABLE_FEATURE_SEAMLESS_XZ
293 && magic.b16[0] == XZ_MAGIC1
294 ) {
295 offset = -6;
296 xread(fd, magic.b32, sizeof(magic.b32[0]));
297 if (magic.b32[0] == XZ_MAGIC2) {
298# if BB_MMU
299 xformer = unpack_xz_stream;
300 /* unpack_xz_stream wants fd at position 6, no need to seek */
301 //xlseek(fd, offset, SEEK_CUR);
302# else
303 xformer_prog = "unxz";
304# endif
305 goto found_magic;
306 }
307 }
308
309 /* No known magic seen */
310 if (fail_if_not_detected)
311 bb_error_msg_and_die("no gzip"
312 IF_FEATURE_SEAMLESS_BZ2("/bzip2")
313 IF_FEATURE_SEAMLESS_XZ("/xz")
314 " magic");
315 xlseek(fd, offset, SEEK_CUR);
316 return;
317
318 found_magic:
319# if !BB_MMU
320 /* NOMMU version of open_transformer execs
321 * an external unzipper that wants
322 * file position at the start of the file */
323 xlseek(fd, offset, SEEK_CUR);
324# endif
325 open_transformer(fd, xformer, xformer_prog);
326}
327#endif /* ZIPPED */
328
329int FAST_FUNC open_zipped(const char *fname)
330{
331#if !ZIPPED
332 return open(fname, O_RDONLY);
333#else
334 char *sfx;
335 int fd;
336
337 fd = open(fname, O_RDONLY);
338 if (fd < 0)
339 return fd;
340
341 sfx = strrchr(fname, '.');
342 if (sfx) {
343 sfx++;
344 if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0)
345 /* .lzma has no header/signature, just trust it */
346 open_transformer(fd, unpack_lzma_stream, "unlzma");
347 else
348 if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0)
349 || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0)
350 || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0)
351 ) {
352 setup_unzip_on_fd(fd /*, fail_if_not_detected: 1*/);
353 }
354 }
355
356 return fd;
357#endif
358}
359
360void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p)
361{
362 int fd;
363 char *image;
364
365 fd = open_zipped(fname);
366 if (fd < 0)
367 return NULL;
368
369 image = xmalloc_read(fd, maxsz_p);
370 if (!image)
371 bb_perror_msg("read error from '%s'", fname);
372 close(fd);
373
374 return image;
375}
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 5d8056bd6..6611dabfa 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -256,11 +256,19 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv)
256 if (!(flags & DAEMON_ONLY_SANITIZE)) { 256 if (!(flags & DAEMON_ONLY_SANITIZE)) {
257 if (fork_or_rexec(argv)) 257 if (fork_or_rexec(argv))
258 exit(EXIT_SUCCESS); /* parent */ 258 exit(EXIT_SUCCESS); /* parent */
259 /* if daemonizing, make sure we detach from stdio & ctty */ 259 /* if daemonizing, detach from stdio & ctty */
260 setsid(); 260 setsid();
261 dup2(fd, 0); 261 dup2(fd, 0);
262 dup2(fd, 1); 262 dup2(fd, 1);
263 dup2(fd, 2); 263 dup2(fd, 2);
264 if (flags & DAEMON_DOUBLE_FORK) {
265 /* On Linux, session leader can acquire ctty
266 * unknowingly, by opening a tty.
267 * Prevent this: stop being a session leader.
268 */
269 if (fork_or_rexec(argv))
270 exit(EXIT_SUCCESS); /* parent */
271 }
264 } 272 }
265 while (fd > 2) { 273 while (fd > 2) {
266 close(fd--); 274 close(fd--);
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
index 4b7c110d3..1c8bb2b73 100644
--- a/libbb/xconnect.c
+++ b/libbb/xconnect.c
@@ -322,26 +322,28 @@ len_and_sockaddr* FAST_FUNC xdotted2sockaddr(const char *host, int port)
322 return str2sockaddr(host, port, AF_UNSPEC, AI_NUMERICHOST | DIE_ON_ERROR); 322 return str2sockaddr(host, port, AF_UNSPEC, AI_NUMERICHOST | DIE_ON_ERROR);
323} 323}
324 324
325#undef xsocket_type 325int FAST_FUNC xsocket_type(len_and_sockaddr **lsap, int family, int sock_type)
326int FAST_FUNC xsocket_type(len_and_sockaddr **lsap, IF_FEATURE_IPV6(int family,) int sock_type)
327{ 326{
328 IF_NOT_FEATURE_IPV6(enum { family = AF_INET };)
329 len_and_sockaddr *lsa; 327 len_and_sockaddr *lsa;
330 int fd; 328 int fd;
331 int len; 329 int len;
332 330
333#if ENABLE_FEATURE_IPV6
334 if (family == AF_UNSPEC) { 331 if (family == AF_UNSPEC) {
332#if ENABLE_FEATURE_IPV6
335 fd = socket(AF_INET6, sock_type, 0); 333 fd = socket(AF_INET6, sock_type, 0);
336 if (fd >= 0) { 334 if (fd >= 0) {
337 family = AF_INET6; 335 family = AF_INET6;
338 goto done; 336 goto done;
339 } 337 }
338#endif
340 family = AF_INET; 339 family = AF_INET;
341 } 340 }
342#endif 341
343 fd = xsocket(family, sock_type, 0); 342 fd = xsocket(family, sock_type, 0);
343
344 len = sizeof(struct sockaddr_in); 344 len = sizeof(struct sockaddr_in);
345 if (family == AF_UNIX)
346 len = sizeof(struct sockaddr_un);
345#if ENABLE_FEATURE_IPV6 347#if ENABLE_FEATURE_IPV6
346 if (family == AF_INET6) { 348 if (family == AF_INET6) {
347 done: 349 done:
@@ -357,7 +359,7 @@ int FAST_FUNC xsocket_type(len_and_sockaddr **lsap, IF_FEATURE_IPV6(int family,)
357 359
358int FAST_FUNC xsocket_stream(len_and_sockaddr **lsap) 360int FAST_FUNC xsocket_stream(len_and_sockaddr **lsap)
359{ 361{
360 return xsocket_type(lsap, IF_FEATURE_IPV6(AF_UNSPEC,) SOCK_STREAM); 362 return xsocket_type(lsap, AF_UNSPEC, SOCK_STREAM);
361} 363}
362 364
363static int create_and_bind_or_die(const char *bindaddr, int port, int sock_type) 365static int create_and_bind_or_die(const char *bindaddr, int port, int sock_type)
@@ -370,7 +372,7 @@ static int create_and_bind_or_die(const char *bindaddr, int port, int sock_type)
370 /* user specified bind addr dictates family */ 372 /* user specified bind addr dictates family */
371 fd = xsocket(lsa->u.sa.sa_family, sock_type, 0); 373 fd = xsocket(lsa->u.sa.sa_family, sock_type, 0);
372 } else { 374 } else {
373 fd = xsocket_type(&lsa, IF_FEATURE_IPV6(AF_UNSPEC,) sock_type); 375 fd = xsocket_type(&lsa, AF_UNSPEC, sock_type);
374 set_nport(&lsa->u.sa, htons(port)); 376 set_nport(&lsa->u.sa, htons(port));
375 } 377 }
376 setsockopt_reuseaddr(fd); 378 setsockopt_reuseaddr(fd);
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index 8a6d7e1d1..70d3fc96c 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -376,6 +376,7 @@ void FAST_FUNC xchroot(const char *path)
376{ 376{
377 if (chroot(path)) 377 if (chroot(path))
378 bb_perror_msg_and_die("can't change root directory to %s", path); 378 bb_perror_msg_and_die("can't change root directory to %s", path);
379 xchdir("/");
379} 380}
380 381
381// Print a warning message if opendir() fails, but don't die. 382// Print a warning message if opendir() fails, but don't die.