diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | coreutils/readlink.c | 33 | ||||
-rw-r--r-- | include/libbb.h | 2 | ||||
-rw-r--r-- | include/usage.h | 7 | ||||
-rw-r--r-- | libbb/simplify_path.c | 32 | ||||
-rw-r--r-- | modutils/modprobe-small.c | 2 | ||||
-rw-r--r-- | modutils/modprobe.c | 39 | ||||
-rw-r--r-- | modutils/modutils.c | 2 | ||||
-rw-r--r-- | networking/ftpd.c | 5 | ||||
-rw-r--r-- | networking/httpd.c | 380 | ||||
-rw-r--r-- | networking/telnetd.c | 42 | ||||
-rw-r--r-- | shell/ash.c | 3 |
12 files changed, 321 insertions, 228 deletions
@@ -1,6 +1,6 @@ | |||
1 | VERSION = 1 | 1 | VERSION = 1 |
2 | PATCHLEVEL = 14 | 2 | PATCHLEVEL = 14 |
3 | SUBLEVEL = 1 | 3 | SUBLEVEL = 2 |
4 | EXTRAVERSION = | 4 | EXTRAVERSION = |
5 | NAME = Unnamed | 5 | NAME = Unnamed |
6 | 6 | ||
diff --git a/coreutils/readlink.c b/coreutils/readlink.c index 721fd8597..bcf352e74 100644 --- a/coreutils/readlink.c +++ b/coreutils/readlink.c | |||
@@ -6,9 +6,31 @@ | |||
6 | * | 6 | * |
7 | * Licensed under GPL v2 or later, see file LICENSE in this tarball for details. | 7 | * Licensed under GPL v2 or later, see file LICENSE in this tarball for details. |
8 | */ | 8 | */ |
9 | |||
10 | #include "libbb.h" | 9 | #include "libbb.h" |
11 | 10 | ||
11 | /* | ||
12 | * # readlink --version | ||
13 | * readlink (GNU coreutils) 6.10 | ||
14 | * # readlink --help | ||
15 | * -f, --canonicalize | ||
16 | * canonicalize by following every symlink in | ||
17 | * every component of the given name recursively; | ||
18 | * all but the last component must exist | ||
19 | * -e, --canonicalize-existing | ||
20 | * canonicalize by following every symlink in | ||
21 | * every component of the given name recursively, | ||
22 | * all components must exist | ||
23 | * -m, --canonicalize-missing | ||
24 | * canonicalize by following every symlink in | ||
25 | * every component of the given name recursively, | ||
26 | * without requirements on components existence | ||
27 | * -n, --no-newline do not output the trailing newline | ||
28 | * -q, --quiet, -s, --silent suppress most error messages | ||
29 | * -v, --verbose report error messages | ||
30 | * | ||
31 | * bbox supports: -f -n -v (fully), -q -s (accepts but ignores) | ||
32 | */ | ||
33 | |||
12 | int readlink_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 34 | int readlink_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
13 | int readlink_main(int argc UNUSED_PARAM, char **argv) | 35 | int readlink_main(int argc UNUSED_PARAM, char **argv) |
14 | { | 36 | { |
@@ -20,7 +42,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) | |||
20 | unsigned opt; | 42 | unsigned opt; |
21 | /* We need exactly one non-option argument. */ | 43 | /* We need exactly one non-option argument. */ |
22 | opt_complementary = "=1"; | 44 | opt_complementary = "=1"; |
23 | opt = getopt32(argv, "f"); | 45 | opt = getopt32(argv, "fnvsq"); |
24 | fname = argv[optind]; | 46 | fname = argv[optind]; |
25 | ) | 47 | ) |
26 | SKIP_FEATURE_READLINK_FOLLOW( | 48 | SKIP_FEATURE_READLINK_FOLLOW( |
@@ -30,9 +52,10 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) | |||
30 | ) | 52 | ) |
31 | 53 | ||
32 | /* compat: coreutils readlink reports errors silently via exit code */ | 54 | /* compat: coreutils readlink reports errors silently via exit code */ |
33 | logmode = LOGMODE_NONE; | 55 | if (!(opt & 4)) /* not -v */ |
56 | logmode = LOGMODE_NONE; | ||
34 | 57 | ||
35 | if (opt) { | 58 | if (opt & 1) { /* -f */ |
36 | buf = realpath(fname, pathbuf); | 59 | buf = realpath(fname, pathbuf); |
37 | } else { | 60 | } else { |
38 | buf = xmalloc_readlink_or_warn(fname); | 61 | buf = xmalloc_readlink_or_warn(fname); |
@@ -40,7 +63,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) | |||
40 | 63 | ||
41 | if (!buf) | 64 | if (!buf) |
42 | return EXIT_FAILURE; | 65 | return EXIT_FAILURE; |
43 | puts(buf); | 66 | printf((opt & 2) ? "%s" : "%s\n", buf); |
44 | 67 | ||
45 | if (ENABLE_FEATURE_CLEAN_UP && !opt) | 68 | if (ENABLE_FEATURE_CLEAN_UP && !opt) |
46 | free(buf); | 69 | free(buf); |
diff --git a/include/libbb.h b/include/libbb.h index 2868eba03..bedf659b7 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1099,6 +1099,8 @@ const char *get_signame(int number) FAST_FUNC; | |||
1099 | void print_signames(void) FAST_FUNC; | 1099 | void print_signames(void) FAST_FUNC; |
1100 | 1100 | ||
1101 | char *bb_simplify_path(const char *path) FAST_FUNC; | 1101 | char *bb_simplify_path(const char *path) FAST_FUNC; |
1102 | /* Returns ptr to NUL */ | ||
1103 | char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC; | ||
1102 | 1104 | ||
1103 | #define FAIL_DELAY 3 | 1105 | #define FAIL_DELAY 3 |
1104 | extern void bb_do_delay(int seconds) FAST_FUNC; | 1106 | extern void bb_do_delay(int seconds) FAST_FUNC; |
diff --git a/include/usage.h b/include/usage.h index d3bf7849e..bfacc5611 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -3404,12 +3404,15 @@ | |||
3404 | "files do not block on disk I/O" | 3404 | "files do not block on disk I/O" |
3405 | 3405 | ||
3406 | #define readlink_trivial_usage \ | 3406 | #define readlink_trivial_usage \ |
3407 | USE_FEATURE_READLINK_FOLLOW("[-f] ") "FILE" | 3407 | USE_FEATURE_READLINK_FOLLOW("[-fnv] ") "FILE" |
3408 | #define readlink_full_usage "\n\n" \ | 3408 | #define readlink_full_usage "\n\n" \ |
3409 | "Display the value of a symlink" \ | 3409 | "Display the value of a symlink" \ |
3410 | USE_FEATURE_READLINK_FOLLOW( "\n" \ | 3410 | USE_FEATURE_READLINK_FOLLOW( "\n" \ |
3411 | "\nOptions:" \ | 3411 | "\nOptions:" \ |
3412 | "\n -f Canonicalize by following all symlinks") \ | 3412 | "\n -f Canonicalize by following all symlinks" \ |
3413 | "\n -n Don't add newline" \ | ||
3414 | "\n -v Verbose" \ | ||
3415 | ) \ | ||
3413 | 3416 | ||
3414 | #define readprofile_trivial_usage \ | 3417 | #define readprofile_trivial_usage \ |
3415 | "[OPTIONS]..." | 3418 | "[OPTIONS]..." |
diff --git a/libbb/simplify_path.c b/libbb/simplify_path.c index 367f1f04d..f80e3e8a5 100644 --- a/libbb/simplify_path.c +++ b/libbb/simplify_path.c | |||
@@ -6,22 +6,13 @@ | |||
6 | * | 6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
8 | */ | 8 | */ |
9 | |||
10 | #include "libbb.h" | 9 | #include "libbb.h" |
11 | 10 | ||
12 | char* FAST_FUNC bb_simplify_path(const char *path) | 11 | char* FAST_FUNC bb_simplify_abs_path_inplace(char *start) |
13 | { | 12 | { |
14 | char *s, *start, *p; | 13 | char *s, *p; |
15 | 14 | ||
16 | if (path[0] == '/') | ||
17 | start = xstrdup(path); | ||
18 | else { | ||
19 | s = xrealloc_getcwd_or_warn(NULL); | ||
20 | start = concat_path_file(s, path); | ||
21 | free(s); | ||
22 | } | ||
23 | p = s = start; | 15 | p = s = start; |
24 | |||
25 | do { | 16 | do { |
26 | if (*p == '/') { | 17 | if (*p == '/') { |
27 | if (*s == '/') { /* skip duplicate (or initial) slash */ | 18 | if (*s == '/') { /* skip duplicate (or initial) slash */ |
@@ -47,7 +38,22 @@ char* FAST_FUNC bb_simplify_path(const char *path) | |||
47 | if ((p == start) || (*p != '/')) { /* not a trailing slash */ | 38 | if ((p == start) || (*p != '/')) { /* not a trailing slash */ |
48 | ++p; /* so keep last character */ | 39 | ++p; /* so keep last character */ |
49 | } | 40 | } |
50 | *p = 0; | 41 | *p = '\0'; |
42 | return p; | ||
43 | } | ||
44 | |||
45 | char* FAST_FUNC bb_simplify_path(const char *path) | ||
46 | { | ||
47 | char *s, *p; | ||
48 | |||
49 | if (path[0] == '/') | ||
50 | s = xstrdup(path); | ||
51 | else { | ||
52 | p = xrealloc_getcwd_or_warn(NULL); | ||
53 | s = concat_path_file(p, path); | ||
54 | free(p); | ||
55 | } | ||
51 | 56 | ||
52 | return start; | 57 | bb_simplify_abs_path_inplace(s); |
58 | return s; | ||
53 | } | 59 | } |
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 6eb950f32..6ee0164c2 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c | |||
@@ -656,7 +656,7 @@ depmod -[aA] [-n -e -v -q -V -r -u] | |||
656 | [-b basedirectory] [forced_version] | 656 | [-b basedirectory] [forced_version] |
657 | depmod [-n -e -v -q -r -u] [-F kernelsyms] module1.ko module2.ko ... | 657 | depmod [-n -e -v -q -r -u] [-F kernelsyms] module1.ko module2.ko ... |
658 | If no arguments (except options) are given, "depmod -a" is assumed. | 658 | If no arguments (except options) are given, "depmod -a" is assumed. |
659 | depmod will output a dependancy list suitable for the modprobe utility. | 659 | depmod will output a dependency list suitable for the modprobe utility. |
660 | Options: | 660 | Options: |
661 | -a, --all Probe all modules | 661 | -a, --all Probe all modules |
662 | -A, --quick Only does the work if there's a new module | 662 | -A, --quick Only does the work if there's a new module |
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 0339ebb40..310eebc5f 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -8,12 +8,17 @@ | |||
8 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 8 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), | ||
12 | * we expect the full dependency list to be specified in modules.dep. Older | ||
13 | * versions would only export the direct dependency list. | ||
14 | */ | ||
15 | |||
11 | #include "libbb.h" | 16 | #include "libbb.h" |
12 | #include "modutils.h" | 17 | #include "modutils.h" |
13 | #include <sys/utsname.h> | 18 | #include <sys/utsname.h> |
14 | #include <fnmatch.h> | 19 | #include <fnmatch.h> |
15 | 20 | ||
16 | //#define DBG(...) bb_error_msg(__VA_ARGS__) | 21 | //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) |
17 | #define DBG(...) ((void)0) | 22 | #define DBG(...) ((void)0) |
18 | 23 | ||
19 | #define MODULE_FLAG_LOADED 0x0001 | 24 | #define MODULE_FLAG_LOADED 0x0001 |
@@ -116,6 +121,7 @@ static void add_probe(const char *name) | |||
116 | return; | 121 | return; |
117 | } | 122 | } |
118 | 123 | ||
124 | DBG("queuing %s", name); | ||
119 | m->probed_name = name; | 125 | m->probed_name = name; |
120 | m->flags |= MODULE_FLAG_NEED_DEPS; | 126 | m->flags |= MODULE_FLAG_NEED_DEPS; |
121 | llist_add_to_end(&G.probes, m); | 127 | llist_add_to_end(&G.probes, m); |
@@ -205,9 +211,10 @@ static int read_config(const char *path) | |||
205 | 211 | ||
206 | static int do_modprobe(struct module_entry *m) | 212 | static int do_modprobe(struct module_entry *m) |
207 | { | 213 | { |
208 | struct module_entry *m2; | 214 | struct module_entry *m2 = m2; /* for compiler */ |
209 | char *fn, *options; | 215 | char *fn, *options; |
210 | int rc = -1; | 216 | int rc, first; |
217 | llist_t *l; | ||
211 | 218 | ||
212 | if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { | 219 | if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { |
213 | DBG("skipping %s, not found in modules.dep", m->modname); | 220 | DBG("skipping %s, not found in modules.dep", m->modname); |
@@ -218,13 +225,25 @@ static int do_modprobe(struct module_entry *m) | |||
218 | if (!(option_mask32 & MODPROBE_OPT_REMOVE)) | 225 | if (!(option_mask32 & MODPROBE_OPT_REMOVE)) |
219 | m->deps = llist_rev(m->deps); | 226 | m->deps = llist_rev(m->deps); |
220 | 227 | ||
228 | for (l = m->deps; l != NULL; l = l->link) | ||
229 | DBG("dep: %s", l->data); | ||
230 | |||
231 | first = 1; | ||
221 | rc = 0; | 232 | rc = 0; |
222 | while (m->deps && rc == 0) { | 233 | while (m->deps && rc == 0) { |
223 | fn = llist_pop(&m->deps); | 234 | fn = llist_pop(&m->deps); |
224 | m2 = get_or_add_modentry(fn); | 235 | m2 = get_or_add_modentry(fn); |
225 | if (option_mask32 & MODPROBE_OPT_REMOVE) { | 236 | if (option_mask32 & MODPROBE_OPT_REMOVE) { |
226 | if (bb_delete_module(m->modname, O_EXCL) != 0) | 237 | if (m2->flags & MODULE_FLAG_LOADED) { |
227 | rc = errno; | 238 | if (bb_delete_module(m2->modname, O_EXCL) != 0) { |
239 | if (first) | ||
240 | rc = errno; | ||
241 | } else { | ||
242 | m2->flags &= ~MODULE_FLAG_LOADED; | ||
243 | } | ||
244 | } | ||
245 | /* do not error out if *deps* fail to unload */ | ||
246 | first = 0; | ||
228 | } else if (!(m2->flags & MODULE_FLAG_LOADED)) { | 247 | } else if (!(m2->flags & MODULE_FLAG_LOADED)) { |
229 | options = m2->options; | 248 | options = m2->options; |
230 | m2->options = NULL; | 249 | m2->options = NULL; |
@@ -242,11 +261,10 @@ static int do_modprobe(struct module_entry *m) | |||
242 | free(fn); | 261 | free(fn); |
243 | } | 262 | } |
244 | 263 | ||
245 | //FIXME: what if rc < 0? | 264 | if (rc && !(option_mask32 & INSMOD_OPT_SILENT)) { |
246 | if (rc > 0 && !(option_mask32 & INSMOD_OPT_SILENT)) { | ||
247 | bb_error_msg("failed to %sload module %s: %s", | 265 | bb_error_msg("failed to %sload module %s: %s", |
248 | (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "", | 266 | (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "", |
249 | m->probed_name ? m->probed_name : m->modname, | 267 | m2->probed_name ? m2->probed_name : m2->modname, |
250 | moderror(rc) | 268 | moderror(rc) |
251 | ); | 269 | ); |
252 | } | 270 | } |
@@ -294,7 +312,8 @@ static void load_modules_dep(void) | |||
294 | llist_add_to(&m->deps, xstrdup(tokens[0])); | 312 | llist_add_to(&m->deps, xstrdup(tokens[0])); |
295 | if (tokens[1]) | 313 | if (tokens[1]) |
296 | string_to_llist(tokens[1], &m->deps, " "); | 314 | string_to_llist(tokens[1], &m->deps, " "); |
297 | } | 315 | } else |
316 | DBG("skipping dep line"); | ||
298 | } | 317 | } |
299 | config_close(p); | 318 | config_close(p); |
300 | } | 319 | } |
@@ -344,10 +363,12 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
344 | if (opt & (MODPROBE_OPT_INSERT_ALL | MODPROBE_OPT_REMOVE)) { | 363 | if (opt & (MODPROBE_OPT_INSERT_ALL | MODPROBE_OPT_REMOVE)) { |
345 | /* Each argument is a module name */ | 364 | /* Each argument is a module name */ |
346 | do { | 365 | do { |
366 | DBG("adding module %s", *argv); | ||
347 | add_probe(*argv++); | 367 | add_probe(*argv++); |
348 | } while (*argv); | 368 | } while (*argv); |
349 | } else { | 369 | } else { |
350 | /* First argument is module name, rest are parameters */ | 370 | /* First argument is module name, rest are parameters */ |
371 | DBG("probing just module %s", *argv); | ||
351 | add_probe(argv[0]); | 372 | add_probe(argv[0]); |
352 | G.cmdline_mopts = parse_cmdline_module_options(argv); | 373 | G.cmdline_mopts = parse_cmdline_module_options(argv); |
353 | } | 374 | } |
diff --git a/modutils/modutils.c b/modutils/modutils.c index 0f6cb0f2d..f437a9829 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c | |||
@@ -57,7 +57,7 @@ char * FAST_FUNC filename2modname(const char *filename, char *modname) | |||
57 | from = bb_get_last_path_component_nostrip(filename); | 57 | from = bb_get_last_path_component_nostrip(filename); |
58 | for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) | 58 | for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) |
59 | modname[i] = (from[i] == '-') ? '_' : from[i]; | 59 | modname[i] = (from[i] == '-') ? '_' : from[i]; |
60 | modname[i] = 0; | 60 | modname[i] = '\0'; |
61 | 61 | ||
62 | return modname; | 62 | return modname; |
63 | } | 63 | } |
diff --git a/networking/ftpd.c b/networking/ftpd.c index ac6896117..e85e4f8ea 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c | |||
@@ -1320,6 +1320,8 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) | |||
1320 | handle_appe(); | 1320 | handle_appe(); |
1321 | else if (cmdval == const_STOU) /* "store unique" */ | 1321 | else if (cmdval == const_STOU) /* "store unique" */ |
1322 | handle_stou(); | 1322 | handle_stou(); |
1323 | else | ||
1324 | goto bad_cmd; | ||
1323 | } | 1325 | } |
1324 | #endif | 1326 | #endif |
1325 | #if 0 | 1327 | #if 0 |
@@ -1340,6 +1342,9 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) | |||
1340 | * (doesn't necessarily mean "we must support them") | 1342 | * (doesn't necessarily mean "we must support them") |
1341 | * foo 1.2.3: XXXX - comment | 1343 | * foo 1.2.3: XXXX - comment |
1342 | */ | 1344 | */ |
1345 | #if ENABLE_FEATURE_FTP_WRITE | ||
1346 | bad_cmd: | ||
1347 | #endif | ||
1343 | cmdio_write_raw(STR(FTP_BADCMD)" Unknown command\r\n"); | 1348 | cmdio_write_raw(STR(FTP_BADCMD)" Unknown command\r\n"); |
1344 | } | 1349 | } |
1345 | } | 1350 | } |
diff --git a/networking/httpd.c b/networking/httpd.c index 6bf103c56..de4fb9b39 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -32,7 +32,7 @@ | |||
32 | * foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World" | 32 | * foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World" |
33 | * bar=`httpd -e "<Hello World>"` # encode as "<Hello World>" | 33 | * bar=`httpd -e "<Hello World>"` # encode as "<Hello World>" |
34 | * Note that url encoding for arguments is not the same as html encoding for | 34 | * Note that url encoding for arguments is not the same as html encoding for |
35 | * presentation. -d decodes a url-encoded argument while -e encodes in html | 35 | * presentation. -d decodes an url-encoded argument while -e encodes in html |
36 | * for page display. | 36 | * for page display. |
37 | * | 37 | * |
38 | * httpd.conf has the following format: | 38 | * httpd.conf has the following format: |
@@ -54,7 +54,7 @@ | |||
54 | * /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/ | 54 | * /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/ |
55 | * /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/ | 55 | * /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/ |
56 | * .au:audio/basic # additional mime type for audio.au files | 56 | * .au:audio/basic # additional mime type for audio.au files |
57 | * *.php:/path/php # running cgi.php scripts through an interpreter | 57 | * *.php:/path/php # run xxx.php through an interpreter |
58 | * | 58 | * |
59 | * A/D may be as a/d or allow/deny - only first char matters. | 59 | * A/D may be as a/d or allow/deny - only first char matters. |
60 | * Deny/Allow IP logic: | 60 | * Deny/Allow IP logic: |
@@ -94,13 +94,13 @@ | |||
94 | * server exits with an error. | 94 | * server exits with an error. |
95 | * | 95 | * |
96 | */ | 96 | */ |
97 | /* TODO: use TCP_CORK, parse_config() */ | ||
97 | 98 | ||
98 | #include "libbb.h" | 99 | #include "libbb.h" |
99 | #if ENABLE_FEATURE_HTTPD_USE_SENDFILE | 100 | #if ENABLE_FEATURE_HTTPD_USE_SENDFILE |
100 | # include <sys/sendfile.h> | 101 | # include <sys/sendfile.h> |
101 | #endif | 102 | #endif |
102 | 103 | ||
103 | //#define DEBUG 1 | ||
104 | #define DEBUG 0 | 104 | #define DEBUG 0 |
105 | 105 | ||
106 | #define IOBUF_SIZE 8192 /* IO buffer */ | 106 | #define IOBUF_SIZE 8192 /* IO buffer */ |
@@ -115,8 +115,8 @@ | |||
115 | 115 | ||
116 | #define HEADER_READ_TIMEOUT 60 | 116 | #define HEADER_READ_TIMEOUT 60 |
117 | 117 | ||
118 | static const char default_path_httpd_conf[] ALIGN1 = "/etc"; | 118 | static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc"; |
119 | static const char httpd_conf[] ALIGN1 = "httpd.conf"; | 119 | static const char HTTPD_CONF[] ALIGN1 = "httpd.conf"; |
120 | static const char HTTP_200[] ALIGN1 = "HTTP/1.0 200 OK\r\n"; | 120 | static const char HTTP_200[] ALIGN1 = "HTTP/1.0 200 OK\r\n"; |
121 | 121 | ||
122 | typedef struct has_next_ptr { | 122 | typedef struct has_next_ptr { |
@@ -242,7 +242,7 @@ struct globals { | |||
242 | const char *bind_addr_or_port; | 242 | const char *bind_addr_or_port; |
243 | 243 | ||
244 | const char *g_query; | 244 | const char *g_query; |
245 | const char *configFile; | 245 | const char *opt_c_configFile; |
246 | const char *home_httpd; | 246 | const char *home_httpd; |
247 | const char *index_page; | 247 | const char *index_page; |
248 | 248 | ||
@@ -289,7 +289,7 @@ struct globals { | |||
289 | #define rmt_ip (G.rmt_ip ) | 289 | #define rmt_ip (G.rmt_ip ) |
290 | #define bind_addr_or_port (G.bind_addr_or_port) | 290 | #define bind_addr_or_port (G.bind_addr_or_port) |
291 | #define g_query (G.g_query ) | 291 | #define g_query (G.g_query ) |
292 | #define configFile (G.configFile ) | 292 | #define opt_c_configFile (G.opt_c_configFile ) |
293 | #define home_httpd (G.home_httpd ) | 293 | #define home_httpd (G.home_httpd ) |
294 | #define index_page (G.index_page ) | 294 | #define index_page (G.index_page ) |
295 | #define found_mime_type (G.found_mime_type ) | 295 | #define found_mime_type (G.found_mime_type ) |
@@ -452,14 +452,6 @@ static int scan_ip_mask(const char *str, unsigned *ipp, unsigned *maskp) | |||
452 | /* | 452 | /* |
453 | * Parse configuration file into in-memory linked list. | 453 | * Parse configuration file into in-memory linked list. |
454 | * | 454 | * |
455 | * The first non-white character is examined to determine if the config line | ||
456 | * is one of the following: | ||
457 | * .ext:mime/type # new mime type not compiled into httpd | ||
458 | * [adAD]:from # ip address allow/deny, * for wildcard | ||
459 | * /path:user:pass # username/password | ||
460 | * Ennn:error.html # error page for status nnn | ||
461 | * P:/url:[http://]hostname[:port]/new/path # reverse proxy | ||
462 | * | ||
463 | * Any previous IP rules are discarded. | 455 | * Any previous IP rules are discarded. |
464 | * If the flag argument is not SUBDIR_PARSE then all /path and mime rules | 456 | * If the flag argument is not SUBDIR_PARSE then all /path and mime rules |
465 | * are also discarded. That is, previous settings are retained if flag is | 457 | * are also discarded. That is, previous settings are retained if flag is |
@@ -469,99 +461,150 @@ static int scan_ip_mask(const char *str, unsigned *ipp, unsigned *maskp) | |||
469 | * path Path where to look for httpd.conf (without filename). | 461 | * path Path where to look for httpd.conf (without filename). |
470 | * flag Type of the parse request. | 462 | * flag Type of the parse request. |
471 | */ | 463 | */ |
472 | /* flag */ | 464 | /* flag param: */ |
473 | #define FIRST_PARSE 0 | 465 | enum { |
474 | #define SUBDIR_PARSE 1 | 466 | FIRST_PARSE = 0, /* path will be "/etc" */ |
475 | #define SIGNALED_PARSE 2 | 467 | SIGNALED_PARSE = 1, /* path will be "/etc" */ |
476 | #define FIND_FROM_HTTPD_ROOT 3 | 468 | SUBDIR_PARSE = 2, /* path will be derived from URL */ |
469 | }; | ||
477 | static void parse_conf(const char *path, int flag) | 470 | static void parse_conf(const char *path, int flag) |
478 | { | 471 | { |
472 | /* internally used extra flag state */ | ||
473 | enum { TRY_CURDIR_PARSE = 3 }; | ||
474 | |||
479 | FILE *f; | 475 | FILE *f; |
480 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 476 | const char *filename; |
481 | Htaccess *prev; | ||
482 | #endif | ||
483 | Htaccess *cur; | ||
484 | const char *filename = configFile; | ||
485 | char buf[160]; | 477 | char buf[160]; |
486 | char *p, *p0; | ||
487 | char *after_colon; | ||
488 | Htaccess_IP *pip; | ||
489 | 478 | ||
490 | /* discard old rules */ | 479 | /* discard old rules */ |
491 | free_Htaccess_IP_list(&ip_a_d); | 480 | free_Htaccess_IP_list(&ip_a_d); |
492 | flg_deny_all = 0; | 481 | flg_deny_all = 0; |
493 | /* retain previous auth and mime config only for subdir parse */ | 482 | /* retain previous auth and mime config only for subdir parse */ |
494 | if (flag != SUBDIR_PARSE) { | 483 | if (flag != SUBDIR_PARSE) { |
484 | free_Htaccess_list(&mime_a); | ||
495 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 485 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
496 | free_Htaccess_list(&g_auth); | 486 | free_Htaccess_list(&g_auth); |
497 | #endif | 487 | #endif |
498 | free_Htaccess_list(&mime_a); | ||
499 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 488 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
500 | free_Htaccess_list(&script_i); | 489 | free_Htaccess_list(&script_i); |
501 | #endif | 490 | #endif |
502 | } | 491 | } |
503 | 492 | ||
493 | filename = opt_c_configFile; | ||
504 | if (flag == SUBDIR_PARSE || filename == NULL) { | 494 | if (flag == SUBDIR_PARSE || filename == NULL) { |
505 | filename = alloca(strlen(path) + sizeof(httpd_conf) + 2); | 495 | filename = alloca(strlen(path) + sizeof(HTTPD_CONF) + 2); |
506 | sprintf((char *)filename, "%s/%s", path, httpd_conf); | 496 | sprintf((char *)filename, "%s/%s", path, HTTPD_CONF); |
507 | } | 497 | } |
508 | 498 | ||
509 | while ((f = fopen_for_read(filename)) == NULL) { | 499 | while ((f = fopen_for_read(filename)) == NULL) { |
510 | if (flag == SUBDIR_PARSE || flag == FIND_FROM_HTTPD_ROOT) { | 500 | if (flag >= SUBDIR_PARSE) { /* SUBDIR or TRY_CURDIR */ |
511 | /* config file not found, no changes to config */ | 501 | /* config file not found, no changes to config */ |
512 | return; | 502 | return; |
513 | } | 503 | } |
514 | if (configFile && flag == FIRST_PARSE) /* if -c option given */ | 504 | if (flag == FIRST_PARSE) { |
515 | bb_simple_perror_msg_and_die(filename); | 505 | /* -c CONFFILE given, but CONFFILE doesn't exist? */ |
516 | flag = FIND_FROM_HTTPD_ROOT; | 506 | if (opt_c_configFile) |
517 | filename = httpd_conf; | 507 | bb_simple_perror_msg_and_die(opt_c_configFile); |
508 | /* else: no -c, thus we looked at /etc/httpd.conf, | ||
509 | * and it's not there. try ./httpd.conf: */ | ||
510 | } | ||
511 | flag = TRY_CURDIR_PARSE; | ||
512 | filename = HTTPD_CONF; | ||
518 | } | 513 | } |
519 | 514 | ||
520 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 515 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
521 | prev = g_auth; | 516 | /* in "/file:user:pass" lines, we prepend path in subdirs */ |
522 | #endif | 517 | if (flag != SUBDIR_PARSE) |
523 | /* This could stand some work */ | 518 | path = ""; |
524 | while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) { | 519 | #endif |
525 | after_colon = NULL; | 520 | /* The lines can be: |
526 | for (p = p0; *p0 != '\0' && *p0 != '#'; p0++) { | 521 | * |
527 | if (!isspace(*p0)) { | 522 | * I:default_index_file |
528 | *p++ = *p0; | 523 | * H:http_home |
529 | if (*p0 == ':' && after_colon == NULL) | 524 | * [AD]:IP[/mask] # allow/deny, * for wildcard |
530 | after_colon = p; | 525 | * Ennn:error.html # error page for status nnn |
526 | * P:/url:[http://]hostname[:port]/new/path # reverse proxy | ||
527 | * .ext:mime/type # mime type | ||
528 | * *.php:/path/php # run xxx.php through an interpreter | ||
529 | * /file:user:pass # username and password | ||
530 | */ | ||
531 | while (fgets(buf, sizeof(buf), f) != NULL) { | ||
532 | unsigned strlen_buf; | ||
533 | unsigned char ch; | ||
534 | char *after_colon; | ||
535 | |||
536 | { /* remove all whitespace, and # comments */ | ||
537 | char *p, *p0; | ||
538 | |||
539 | p0 = buf; | ||
540 | /* skip non-whitespace beginning. Often the whole line | ||
541 | * is non-whitespace. We want this case to work fast, | ||
542 | * without needless copying, therefore we don't merge | ||
543 | * this operation into next while loop. */ | ||
544 | while ((ch = *p0) != '\0' && ch != '\n' && ch != '#' | ||
545 | && ch != ' ' && ch != '\t' | ||
546 | ) { | ||
547 | p0++; | ||
548 | } | ||
549 | p = p0; | ||
550 | /* if we enter this loop, we have some whitespace. | ||
551 | * discard it */ | ||
552 | while (ch != '\0' && ch != '\n' && ch != '#') { | ||
553 | if (ch != ' ' && ch != '\t') { | ||
554 | *p++ = ch; | ||
555 | } | ||
556 | ch = *++p0; | ||
531 | } | 557 | } |
558 | *p = '\0'; | ||
559 | strlen_buf = p - buf; | ||
560 | if (strlen_buf == 0) | ||
561 | continue; /* empty line */ | ||
532 | } | 562 | } |
533 | *p = '\0'; | ||
534 | 563 | ||
535 | /* test for empty or strange line */ | 564 | after_colon = strchr(buf, ':'); |
536 | if (after_colon == NULL || *after_colon == '\0') | 565 | /* strange line? */ |
566 | if (after_colon == NULL || *++after_colon == '\0') | ||
567 | goto config_error; | ||
568 | |||
569 | ch = (buf[0] & ~0x20); /* toupper if it's a letter */ | ||
570 | |||
571 | if (ch == 'I') { | ||
572 | index_page = xstrdup(after_colon); | ||
537 | continue; | 573 | continue; |
538 | p0 = buf; | 574 | } |
539 | if (*p0 == 'd' || *p0 == 'a') | 575 | |
540 | *p0 -= 0x20; /* a/d -> A/D */ | 576 | /* do not allow jumping around using H in subdir's configs */ |
541 | if (*after_colon == '*') { | 577 | if (flag == FIRST_PARSE && ch == 'H') { |
542 | if (*p0 == 'D') { | 578 | home_httpd = xstrdup(after_colon); |
543 | /* memorize "deny all" */ | 579 | xchdir(home_httpd); |
544 | flg_deny_all = 1; | ||
545 | } | ||
546 | /* skip assumed "A:*", it is a default anyway */ | ||
547 | continue; | 580 | continue; |
548 | } | 581 | } |
549 | 582 | ||
550 | if (*p0 == 'A' || *p0 == 'D') { | 583 | if (ch == 'A' || ch == 'D') { |
551 | /* storing current config IP line */ | 584 | Htaccess_IP *pip; |
552 | pip = xzalloc(sizeof(Htaccess_IP)); | 585 | |
553 | if (scan_ip_mask(after_colon, &(pip->ip), &(pip->mask))) { | 586 | if (*after_colon == '*') { |
587 | if (ch == 'D') { | ||
588 | /* memorize "deny all" */ | ||
589 | flg_deny_all = 1; | ||
590 | } | ||
591 | /* skip assumed "A:*", it is a default anyway */ | ||
592 | continue; | ||
593 | } | ||
594 | /* store "allow/deny IP/mask" line */ | ||
595 | pip = xzalloc(sizeof(*pip)); | ||
596 | if (scan_ip_mask(after_colon, &pip->ip, &pip->mask)) { | ||
554 | /* IP{/mask} syntax error detected, protect all */ | 597 | /* IP{/mask} syntax error detected, protect all */ |
555 | *p0 = 'D'; | 598 | ch = 'D'; |
556 | pip->mask = 0; | 599 | pip->mask = 0; |
557 | } | 600 | } |
558 | pip->allow_deny = *p0; | 601 | pip->allow_deny = ch; |
559 | if (*p0 == 'D') { | 602 | if (ch == 'D') { |
560 | /* Deny:from_IP - prepend */ | 603 | /* Deny:from_IP - prepend */ |
561 | pip->next = ip_a_d; | 604 | pip->next = ip_a_d; |
562 | ip_a_d = pip; | 605 | ip_a_d = pip; |
563 | } else { | 606 | } else { |
564 | /* A:from_IP - append (thus D precedes A) */ | 607 | /* A:from_IP - append (thus all D's precedes A's) */ |
565 | Htaccess_IP *prev_IP = ip_a_d; | 608 | Htaccess_IP *prev_IP = ip_a_d; |
566 | if (prev_IP == NULL) { | 609 | if (prev_IP == NULL) { |
567 | ip_a_d = pip; | 610 | ip_a_d = pip; |
@@ -575,12 +618,12 @@ static void parse_conf(const char *path, int flag) | |||
575 | } | 618 | } |
576 | 619 | ||
577 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES | 620 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES |
578 | if (flag == FIRST_PARSE && *p0 == 'E') { | 621 | if (flag == FIRST_PARSE && ch == 'E') { |
579 | unsigned i; | 622 | unsigned i; |
580 | int status = atoi(++p0); /* error status code */ | 623 | int status = atoi(buf + 1); /* error status code */ |
624 | |||
581 | if (status < HTTP_CONTINUE) { | 625 | if (status < HTTP_CONTINUE) { |
582 | bb_error_msg("config error '%s' in '%s'", buf, filename); | 626 | goto config_error; |
583 | continue; | ||
584 | } | 627 | } |
585 | /* then error page; find matching status */ | 628 | /* then error page; find matching status */ |
586 | for (i = 0; i < ARRAY_SIZE(http_response_type); i++) { | 629 | for (i = 0; i < ARRAY_SIZE(http_response_type); i++) { |
@@ -597,7 +640,7 @@ static void parse_conf(const char *path, int flag) | |||
597 | #endif | 640 | #endif |
598 | 641 | ||
599 | #if ENABLE_FEATURE_HTTPD_PROXY | 642 | #if ENABLE_FEATURE_HTTPD_PROXY |
600 | if (flag == FIRST_PARSE && *p0 == 'P') { | 643 | if (flag == FIRST_PARSE && ch == 'P') { |
601 | /* P:/url:[http://]hostname[:port]/new/path */ | 644 | /* P:/url:[http://]hostname[:port]/new/path */ |
602 | char *url_from, *host_port, *url_to; | 645 | char *url_from, *host_port, *url_to; |
603 | Htaccess_Proxy *proxy_entry; | 646 | Htaccess_Proxy *proxy_entry; |
@@ -605,23 +648,20 @@ static void parse_conf(const char *path, int flag) | |||
605 | url_from = after_colon; | 648 | url_from = after_colon; |
606 | host_port = strchr(after_colon, ':'); | 649 | host_port = strchr(after_colon, ':'); |
607 | if (host_port == NULL) { | 650 | if (host_port == NULL) { |
608 | bb_error_msg("config error '%s' in '%s'", buf, filename); | 651 | goto config_error; |
609 | continue; | ||
610 | } | 652 | } |
611 | *host_port++ = '\0'; | 653 | *host_port++ = '\0'; |
612 | if (strncmp(host_port, "http://", 7) == 0) | 654 | if (strncmp(host_port, "http://", 7) == 0) |
613 | host_port += 7; | 655 | host_port += 7; |
614 | if (*host_port == '\0') { | 656 | if (*host_port == '\0') { |
615 | bb_error_msg("config error '%s' in '%s'", buf, filename); | 657 | goto config_error; |
616 | continue; | ||
617 | } | 658 | } |
618 | url_to = strchr(host_port, '/'); | 659 | url_to = strchr(host_port, '/'); |
619 | if (url_to == NULL) { | 660 | if (url_to == NULL) { |
620 | bb_error_msg("config error '%s' in '%s'", buf, filename); | 661 | goto config_error; |
621 | continue; | ||
622 | } | 662 | } |
623 | *url_to = '\0'; | 663 | *url_to = '\0'; |
624 | proxy_entry = xzalloc(sizeof(Htaccess_Proxy)); | 664 | proxy_entry = xzalloc(sizeof(*proxy_entry)); |
625 | proxy_entry->url_from = xstrdup(url_from); | 665 | proxy_entry->url_from = xstrdup(url_from); |
626 | proxy_entry->host_port = xstrdup(host_port); | 666 | proxy_entry->host_port = xstrdup(host_port); |
627 | *url_to = '/'; | 667 | *url_to = '/'; |
@@ -631,115 +671,87 @@ static void parse_conf(const char *path, int flag) | |||
631 | continue; | 671 | continue; |
632 | } | 672 | } |
633 | #endif | 673 | #endif |
674 | /* the rest of directives are non-alphabetic, | ||
675 | * must avoid using "toupper'ed" ch */ | ||
676 | ch = buf[0]; | ||
634 | 677 | ||
635 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 678 | if (ch == '.' /* ".ext:mime/type" */ |
636 | if (*p0 == '/') { | 679 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
637 | /* make full path from httpd root / current_path / config_line_path */ | 680 | || (ch == '*' && buf[1] == '.') /* "*.php:/path/php" */ |
638 | const char *tp = (flag == SUBDIR_PARSE ? path : ""); | 681 | #endif |
639 | p0 = xmalloc(strlen(tp) + (after_colon - buf) + 2 + strlen(after_colon)); | 682 | ) { |
640 | after_colon[-1] = '\0'; | 683 | char *p; |
641 | sprintf(p0, "/%s%s", tp, buf); | 684 | Htaccess *cur; |
642 | |||
643 | /* looks like bb_simplify_path... */ | ||
644 | tp = p = p0; | ||
645 | do { | ||
646 | if (*p == '/') { | ||
647 | if (*tp == '/') { /* skip duplicate (or initial) slash */ | ||
648 | continue; | ||
649 | } | ||
650 | if (*tp == '.') { | ||
651 | if (tp[1] == '/' || tp[1] == '\0') { /* remove extra '.' */ | ||
652 | continue; | ||
653 | } | ||
654 | if ((tp[1] == '.') && (tp[2] == '/' || tp[2] == '\0')) { | ||
655 | ++tp; | ||
656 | if (p > p0) { | ||
657 | while (*--p != '/') /* omit previous dir */ | ||
658 | continue; | ||
659 | } | ||
660 | continue; | ||
661 | } | ||
662 | } | ||
663 | } | ||
664 | *++p = *tp; | ||
665 | } while (*++tp); | ||
666 | 685 | ||
667 | if ((p == p0) || (*p != '/')) { /* not a trailing slash */ | 686 | cur = xzalloc(sizeof(*cur) /* includes space for NUL */ + strlen_buf); |
668 | ++p; /* so keep last character */ | 687 | strcpy(cur->before_colon, buf); |
688 | p = cur->before_colon + (after_colon - buf); | ||
689 | p[-1] = '\0'; | ||
690 | cur->after_colon = p; | ||
691 | if (ch == '.') { | ||
692 | /* .mime line: prepend to mime_a list */ | ||
693 | cur->next = mime_a; | ||
694 | mime_a = cur; | ||
695 | } | ||
696 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | ||
697 | else { | ||
698 | /* script interpreter line: prepend to script_i list */ | ||
699 | cur->next = script_i; | ||
700 | script_i = cur; | ||
669 | } | 701 | } |
670 | *p = ':'; | ||
671 | strcpy(p + 1, after_colon); | ||
672 | } | ||
673 | #endif | 702 | #endif |
674 | if (*p0 == 'I') { | ||
675 | index_page = xstrdup(after_colon); | ||
676 | continue; | 703 | continue; |
677 | } | 704 | } |
678 | 705 | ||
679 | /* Do not allow jumping around using H in subdir's configs */ | ||
680 | if (flag == FIRST_PARSE && *p0 == 'H') { | ||
681 | home_httpd = xstrdup(after_colon); | ||
682 | xchdir(home_httpd); | ||
683 | continue; | ||
684 | } | ||
685 | |||
686 | /* storing current config line */ | ||
687 | cur = xzalloc(sizeof(Htaccess) + strlen(p0)); | ||
688 | strcpy(cur->before_colon, p0); | ||
689 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | ||
690 | if (*p0 == '/') /* was malloced - see above */ | ||
691 | free(p0); | ||
692 | #endif | ||
693 | cur->after_colon = strchr(cur->before_colon, ':'); | ||
694 | *cur->after_colon++ = '\0'; | ||
695 | if (cur->before_colon[0] == '.') { | ||
696 | /* .mime line: prepend to mime_a list */ | ||
697 | cur->next = mime_a; | ||
698 | mime_a = cur; | ||
699 | continue; | ||
700 | } | ||
701 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | ||
702 | if (cur->before_colon[0] == '*' && cur->before_colon[1] == '.') { | ||
703 | /* script interpreter line: prepend to script_i list */ | ||
704 | cur->next = script_i; | ||
705 | script_i = cur; | ||
706 | continue; | ||
707 | } | ||
708 | #endif | ||
709 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 706 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
710 | //TODO: we do not test for leading "/"?? | 707 | if (ch == '/') { /* "/file:user:pass" */ |
711 | //also, do we leak cur if BASIC_AUTH is off? | 708 | char *p; |
712 | if (prev == NULL) { | 709 | Htaccess *cur; |
713 | /* first line */ | 710 | unsigned file_len; |
714 | g_auth = prev = cur; | 711 | |
715 | } else { | 712 | /* note: path is "" unless we are in SUBDIR parse, |
716 | /* sort path, if current length eq or bigger then move up */ | 713 | * otherwise it does NOT start with "/" */ |
717 | Htaccess *prev_hti = g_auth; | 714 | cur = xzalloc(sizeof(*cur) /* includes space for NUL */ |
718 | size_t l = strlen(cur->before_colon); | 715 | + 1 + strlen(path) |
719 | Htaccess *hti; | 716 | + strlen_buf |
720 | 717 | ); | |
721 | for (hti = prev_hti; hti; hti = hti->next) { | 718 | /* form "/path/file" */ |
722 | if (l >= strlen(hti->before_colon)) { | 719 | sprintf(cur->before_colon, "/%s%.*s", |
723 | /* insert before hti */ | 720 | path, |
724 | cur->next = hti; | 721 | (int) (after_colon - buf - 1), /* includes "/", but not ":" */ |
725 | if (prev_hti != hti) { | 722 | buf); |
726 | prev_hti->next = cur; | 723 | /* canonicalize it */ |
727 | } else { | 724 | p = bb_simplify_abs_path_inplace(cur->before_colon); |
728 | /* insert as top */ | 725 | file_len = p - cur->before_colon; |
729 | g_auth = cur; | 726 | /* add "user:pass" after NUL */ |
727 | strcpy(++p, after_colon); | ||
728 | cur->after_colon = p; | ||
729 | |||
730 | /* insert cur into g_auth */ | ||
731 | /* g_auth is sorted by decreased filename length */ | ||
732 | { | ||
733 | Htaccess *auth, **authp; | ||
734 | |||
735 | authp = &g_auth; | ||
736 | while ((auth = *authp) != NULL) { | ||
737 | if (file_len >= strlen(auth->before_colon)) { | ||
738 | /* insert cur before auth */ | ||
739 | cur->next = auth; | ||
740 | break; | ||
730 | } | 741 | } |
731 | break; | 742 | authp = &auth->next; |
732 | } | 743 | } |
733 | if (prev_hti != hti) | 744 | *authp = cur; |
734 | prev_hti = prev_hti->next; | ||
735 | } | ||
736 | if (!hti) { /* not inserted, add to bottom */ | ||
737 | prev->next = cur; | ||
738 | prev = cur; | ||
739 | } | 745 | } |
746 | continue; | ||
740 | } | 747 | } |
741 | #endif /* BASIC_AUTH */ | 748 | #endif /* BASIC_AUTH */ |
749 | |||
750 | /* the line is not recognized */ | ||
751 | config_error: | ||
752 | bb_error_msg("config error '%s' in '%s'", buf, filename); | ||
742 | } /* while (fgets) */ | 753 | } /* while (fgets) */ |
754 | |||
743 | fclose(f); | 755 | fclose(f); |
744 | } | 756 | } |
745 | 757 | ||
@@ -1527,11 +1539,6 @@ static NOINLINE void send_file_and_exit(const char *url, int what) | |||
1527 | send_headers_and_exit(HTTP_NOT_FOUND); | 1539 | send_headers_and_exit(HTTP_NOT_FOUND); |
1528 | log_and_exit(); | 1540 | log_and_exit(); |
1529 | } | 1541 | } |
1530 | |||
1531 | if (DEBUG) | ||
1532 | bb_error_msg("sending file '%s' content-type: %s", | ||
1533 | url, found_mime_type); | ||
1534 | |||
1535 | /* If you want to know about EPIPE below | 1542 | /* If you want to know about EPIPE below |
1536 | * (happens if you abort downloads from local httpd): */ | 1543 | * (happens if you abort downloads from local httpd): */ |
1537 | signal(SIGPIPE, SIG_IGN); | 1544 | signal(SIGPIPE, SIG_IGN); |
@@ -1559,6 +1566,11 @@ static NOINLINE void send_file_and_exit(const char *url, int what) | |||
1559 | } | 1566 | } |
1560 | } | 1567 | } |
1561 | } | 1568 | } |
1569 | |||
1570 | if (DEBUG) | ||
1571 | bb_error_msg("sending file '%s' content-type: %s", | ||
1572 | url, found_mime_type); | ||
1573 | |||
1562 | #if ENABLE_FEATURE_HTTPD_RANGES | 1574 | #if ENABLE_FEATURE_HTTPD_RANGES |
1563 | if (what == SEND_BODY) | 1575 | if (what == SEND_BODY) |
1564 | range_start = 0; /* err pages and ranges don't mix */ | 1576 | range_start = 0; /* err pages and ranges don't mix */ |
@@ -2031,8 +2043,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2031 | /* We are done reading headers, disable peer timeout */ | 2043 | /* We are done reading headers, disable peer timeout */ |
2032 | alarm(0); | 2044 | alarm(0); |
2033 | 2045 | ||
2034 | if (strcmp(bb_basename(urlcopy), httpd_conf) == 0 || !ip_allowed) { | 2046 | if (strcmp(bb_basename(urlcopy), HTTPD_CONF) == 0 || !ip_allowed) { |
2035 | /* protect listing [/path]/httpd_conf or IP deny */ | 2047 | /* protect listing [/path]/httpd.conf or IP deny */ |
2036 | send_headers_and_exit(HTTP_FORBIDDEN); | 2048 | send_headers_and_exit(HTTP_FORBIDDEN); |
2037 | } | 2049 | } |
2038 | 2050 | ||
@@ -2074,7 +2086,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2074 | header_ptr += 2; | 2086 | header_ptr += 2; |
2075 | write(proxy_fd, header_buf, header_ptr - header_buf); | 2087 | write(proxy_fd, header_buf, header_ptr - header_buf); |
2076 | free(header_buf); /* on the order of 8k, free it */ | 2088 | free(header_buf); /* on the order of 8k, free it */ |
2077 | /* cgi_io_loop_and_exit needs to have two disctinct fds */ | 2089 | /* cgi_io_loop_and_exit needs to have two distinct fds */ |
2078 | cgi_io_loop_and_exit(proxy_fd, dup(proxy_fd), length); | 2090 | cgi_io_loop_and_exit(proxy_fd, dup(proxy_fd), length); |
2079 | } | 2091 | } |
2080 | #endif | 2092 | #endif |
@@ -2245,7 +2257,7 @@ static void mini_httpd_inetd(void) | |||
2245 | 2257 | ||
2246 | static void sighup_handler(int sig UNUSED_PARAM) | 2258 | static void sighup_handler(int sig UNUSED_PARAM) |
2247 | { | 2259 | { |
2248 | parse_conf(default_path_httpd_conf, SIGNALED_PARSE); | 2260 | parse_conf(DEFAULT_PATH_HTTPD_CONF, SIGNALED_PARSE); |
2249 | } | 2261 | } |
2250 | 2262 | ||
2251 | enum { | 2263 | enum { |
@@ -2304,7 +2316,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
2304 | USE_FEATURE_HTTPD_AUTH_MD5("m:") | 2316 | USE_FEATURE_HTTPD_AUTH_MD5("m:") |
2305 | USE_FEATURE_HTTPD_SETUID("u:") | 2317 | USE_FEATURE_HTTPD_SETUID("u:") |
2306 | "p:ifv", | 2318 | "p:ifv", |
2307 | &configFile, &url_for_decode, &home_httpd | 2319 | &opt_c_configFile, &url_for_decode, &home_httpd |
2308 | USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) | 2320 | USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) |
2309 | USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) | 2321 | USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) |
2310 | USE_FEATURE_HTTPD_AUTH_MD5(, &pass) | 2322 | USE_FEATURE_HTTPD_AUTH_MD5(, &pass) |
@@ -2375,7 +2387,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) | |||
2375 | } | 2387 | } |
2376 | #endif | 2388 | #endif |
2377 | 2389 | ||
2378 | parse_conf(default_path_httpd_conf, FIRST_PARSE); | 2390 | parse_conf(DEFAULT_PATH_HTTPD_CONF, FIRST_PARSE); |
2379 | if (!(opt & OPT_INETD)) | 2391 | if (!(opt & OPT_INETD)) |
2380 | signal(SIGHUP, sighup_handler); | 2392 | signal(SIGHUP, sighup_handler); |
2381 | 2393 | ||
diff --git a/networking/telnetd.c b/networking/telnetd.c index ccf328925..4c5ea3ab3 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c | |||
@@ -199,9 +199,17 @@ static size_t iac_safe_write(int fd, const char *buf, size_t count) | |||
199 | return total + rc; | 199 | return total + rc; |
200 | } | 200 | } |
201 | 201 | ||
202 | /* Must match getopt32 string */ | ||
203 | enum { | ||
204 | OPT_WATCHCHILD = (1 << 2), /* -K */ | ||
205 | OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */ | ||
206 | OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p */ | ||
207 | OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */ | ||
208 | }; | ||
209 | |||
202 | static struct tsession * | 210 | static struct tsession * |
203 | make_new_session( | 211 | make_new_session( |
204 | USE_FEATURE_TELNETD_STANDALONE(int sock) | 212 | USE_FEATURE_TELNETD_STANDALONE(int master_fd, int sock) |
205 | SKIP_FEATURE_TELNETD_STANDALONE(void) | 213 | SKIP_FEATURE_TELNETD_STANDALONE(void) |
206 | ) { | 214 | ) { |
207 | const char *login_argv[2]; | 215 | const char *login_argv[2]; |
@@ -288,9 +296,29 @@ make_new_session( | |||
288 | /* Restore default signal handling ASAP */ | 296 | /* Restore default signal handling ASAP */ |
289 | bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL); | 297 | bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL); |
290 | 298 | ||
299 | #if ENABLE_FEATURE_TELNETD_STANDALONE | ||
300 | if (!(option_mask32 & OPT_INETD)) { | ||
301 | struct tsession *tp = sessions; | ||
302 | while (tp) { | ||
303 | close(tp->ptyfd); | ||
304 | close(tp->sockfd_read); | ||
305 | /* sockfd_write == sockfd_read for standalone telnetd */ | ||
306 | /*close(tp->sockfd_write);*/ | ||
307 | tp = tp->next; | ||
308 | } | ||
309 | } | ||
310 | #endif | ||
311 | |||
291 | /* Make new session and process group */ | 312 | /* Make new session and process group */ |
292 | setsid(); | 313 | setsid(); |
293 | 314 | ||
315 | close(fd); | ||
316 | #if ENABLE_FEATURE_TELNETD_STANDALONE | ||
317 | close(sock); | ||
318 | if (master_fd >= 0) | ||
319 | close(master_fd); | ||
320 | #endif | ||
321 | |||
294 | /* Open the child's side of the tty. */ | 322 | /* Open the child's side of the tty. */ |
295 | /* NB: setsid() disconnects from any previous ctty's. Therefore | 323 | /* NB: setsid() disconnects from any previous ctty's. Therefore |
296 | * we must open child's side of the tty AFTER setsid! */ | 324 | * we must open child's side of the tty AFTER setsid! */ |
@@ -329,14 +357,6 @@ make_new_session( | |||
329 | _exit(EXIT_FAILURE); /*bb_perror_msg_and_die("execv %s", loginpath);*/ | 357 | _exit(EXIT_FAILURE); /*bb_perror_msg_and_die("execv %s", loginpath);*/ |
330 | } | 358 | } |
331 | 359 | ||
332 | /* Must match getopt32 string */ | ||
333 | enum { | ||
334 | OPT_WATCHCHILD = (1 << 2), /* -K */ | ||
335 | OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */ | ||
336 | OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p */ | ||
337 | OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */ | ||
338 | }; | ||
339 | |||
340 | #if ENABLE_FEATURE_TELNETD_STANDALONE | 360 | #if ENABLE_FEATURE_TELNETD_STANDALONE |
341 | 361 | ||
342 | static void | 362 | static void |
@@ -465,7 +485,7 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv) | |||
465 | 485 | ||
466 | #if ENABLE_FEATURE_TELNETD_STANDALONE | 486 | #if ENABLE_FEATURE_TELNETD_STANDALONE |
467 | if (IS_INETD) { | 487 | if (IS_INETD) { |
468 | sessions = make_new_session(0); | 488 | sessions = make_new_session(-1, 0); |
469 | if (!sessions) /* pty opening or vfork problem, exit */ | 489 | if (!sessions) /* pty opening or vfork problem, exit */ |
470 | return 1; /* make_new_session prints error message */ | 490 | return 1; /* make_new_session prints error message */ |
471 | } else { | 491 | } else { |
@@ -553,7 +573,7 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv) | |||
553 | if (fd < 0) | 573 | if (fd < 0) |
554 | goto again; | 574 | goto again; |
555 | /* Create a new session and link it into our active list */ | 575 | /* Create a new session and link it into our active list */ |
556 | new_ts = make_new_session(fd); | 576 | new_ts = make_new_session(master_fd, fd); |
557 | if (new_ts) { | 577 | if (new_ts) { |
558 | new_ts->next = sessions; | 578 | new_ts->next = sessions; |
559 | sessions = new_ts; | 579 | sessions = new_ts; |
diff --git a/shell/ash.c b/shell/ash.c index 4acc30110..4981f4ce0 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -11909,7 +11909,8 @@ find_dot_file(char *name) | |||
11909 | */ | 11909 | */ |
11910 | return fullname; | 11910 | return fullname; |
11911 | } | 11911 | } |
11912 | stunalloc(fullname); | 11912 | if (fullname != name) |
11913 | stunalloc(fullname); | ||
11913 | } | 11914 | } |
11914 | 11915 | ||
11915 | /* not found in the PATH */ | 11916 | /* not found in the PATH */ |