diff options
author | Ron Yorston <rmy@pobox.com> | 2019-05-27 11:56:52 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2019-05-27 11:56:52 +0100 |
commit | a61949401890cbb33a9d6c4571b51c53460ad438 (patch) | |
tree | 64dedaddb89896d5b1670a421af123670ca2120b | |
parent | 03a7b173605a890e1db5177ecd5b8dd591081c41 (diff) | |
parent | bcb1fc3e6ca6fe902610f507eaf9b0b58a5c583a (diff) | |
download | busybox-w32-a61949401890cbb33a9d6c4571b51c53460ad438.tar.gz busybox-w32-a61949401890cbb33a9d6c4571b51c53460ad438.tar.bz2 busybox-w32-a61949401890cbb33a9d6c4571b51c53460ad438.zip |
Merge branch 'busybox' into merge
80 files changed, 1153 insertions, 789 deletions
@@ -353,6 +353,15 @@ config FEATURE_CLEAN_UP | |||
353 | Don't enable this unless you have a really good reason to clean | 353 | Don't enable this unless you have a really good reason to clean |
354 | things up manually. | 354 | things up manually. |
355 | 355 | ||
356 | config FEATURE_SYSLOG_INFO | ||
357 | bool "Support LOG_INFO level syslog messages" | ||
358 | default y | ||
359 | depends on FEATURE_SYSLOG | ||
360 | help | ||
361 | Applets which send their output to syslog use either LOG_INFO or | ||
362 | LOG_ERR log levels, but by disabling this option all messages will | ||
363 | be logged at the LOG_ERR level, saving just under 200 bytes. | ||
364 | |||
356 | # These are auto-selected by other options | 365 | # These are auto-selected by other options |
357 | 366 | ||
358 | config FEATURE_SYSLOG | 367 | config FEATURE_SYSLOG |
diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index 78366f26a..1f535b32a 100644 --- a/archival/libarchive/decompress_bunzip2.c +++ b/archival/libarchive/decompress_bunzip2.c | |||
@@ -235,9 +235,9 @@ static int get_next_block(bunzip_data *bd) | |||
235 | /* Get next value */ | 235 | /* Get next value */ |
236 | int n = 0; | 236 | int n = 0; |
237 | while (get_bits(bd, 1)) { | 237 | while (get_bits(bd, 1)) { |
238 | n++; | ||
238 | if (n >= groupCount) | 239 | if (n >= groupCount) |
239 | return RETVAL_DATA_ERROR; | 240 | return RETVAL_DATA_ERROR; |
240 | n++; | ||
241 | } | 241 | } |
242 | /* Decode MTF to get the next selector */ | 242 | /* Decode MTF to get the next selector */ |
243 | tmp_byte = mtfSymbol[n]; | 243 | tmp_byte = mtfSymbol[n]; |
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index 69f3ecc66..3a0fc4712 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c | |||
@@ -180,47 +180,44 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog) | |||
180 | */ | 180 | */ |
181 | static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) | 181 | static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) |
182 | { | 182 | { |
183 | union { | ||
184 | uint8_t b[4]; | ||
185 | uint16_t b16[2]; | ||
186 | uint32_t b32[1]; | ||
187 | } magic; | ||
188 | transformer_state_t *xstate; | 183 | transformer_state_t *xstate; |
189 | 184 | ||
190 | xstate = xzalloc(sizeof(*xstate)); | 185 | xstate = xzalloc(sizeof(*xstate)); |
191 | xstate->src_fd = fd; | 186 | xstate->src_fd = fd; |
192 | xstate->signature_skipped = 2; | ||
193 | 187 | ||
194 | /* .gz and .bz2 both have 2-byte signature, and their | 188 | /* .gz and .bz2 both have 2-byte signature, and their |
195 | * unpack_XXX_stream wants this header skipped. */ | 189 | * unpack_XXX_stream wants this header skipped. */ |
196 | xread(fd, magic.b16, sizeof(magic.b16[0])); | 190 | xstate->signature_skipped = 2; |
191 | xread(fd, xstate->magic.b16, 2); | ||
197 | if (ENABLE_FEATURE_SEAMLESS_GZ | 192 | if (ENABLE_FEATURE_SEAMLESS_GZ |
198 | && magic.b16[0] == GZIP_MAGIC | 193 | && xstate->magic.b16[0] == GZIP_MAGIC |
199 | ) { | 194 | ) { |
200 | xstate->xformer = unpack_gz_stream; | 195 | xstate->xformer = unpack_gz_stream; |
201 | USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) | 196 | USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) |
202 | goto found_magic; | 197 | goto found_magic; |
203 | } | 198 | } |
204 | if (ENABLE_FEATURE_SEAMLESS_Z | 199 | if (ENABLE_FEATURE_SEAMLESS_Z |
205 | && magic.b16[0] == COMPRESS_MAGIC | 200 | && xstate->magic.b16[0] == COMPRESS_MAGIC |
206 | ) { | 201 | ) { |
207 | xstate->xformer = unpack_Z_stream; | 202 | xstate->xformer = unpack_Z_stream; |
208 | USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";) | 203 | USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";) |
209 | goto found_magic; | 204 | goto found_magic; |
210 | } | 205 | } |
211 | if (ENABLE_FEATURE_SEAMLESS_BZ2 | 206 | if (ENABLE_FEATURE_SEAMLESS_BZ2 |
212 | && magic.b16[0] == BZIP2_MAGIC | 207 | && xstate->magic.b16[0] == BZIP2_MAGIC |
213 | ) { | 208 | ) { |
214 | xstate->xformer = unpack_bz2_stream; | 209 | xstate->xformer = unpack_bz2_stream; |
215 | USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) | 210 | USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) |
216 | goto found_magic; | 211 | goto found_magic; |
217 | } | 212 | } |
218 | if (ENABLE_FEATURE_SEAMLESS_XZ | 213 | if (ENABLE_FEATURE_SEAMLESS_XZ |
219 | && magic.b16[0] == XZ_MAGIC1 | 214 | && xstate->magic.b16[0] == XZ_MAGIC1 |
220 | ) { | 215 | ) { |
216 | uint32_t v32; | ||
221 | xstate->signature_skipped = 6; | 217 | xstate->signature_skipped = 6; |
222 | xread(fd, magic.b32, sizeof(magic.b32[0])); | 218 | xread(fd, &xstate->magic.b16[1], 4); |
223 | if (magic.b32[0] == XZ_MAGIC2) { | 219 | move_from_unaligned32(v32, &xstate->magic.b16[1]); |
220 | if (v32 == XZ_MAGIC2) { | ||
224 | xstate->xformer = unpack_xz_stream; | 221 | xstate->xformer = unpack_xz_stream; |
225 | USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) | 222 | USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) |
226 | goto found_magic; | 223 | goto found_magic; |
@@ -365,11 +362,24 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_ | |||
365 | *maxsz_p = xstate->mem_output_size; | 362 | *maxsz_p = xstate->mem_output_size; |
366 | } | 363 | } |
367 | } else { | 364 | } else { |
368 | /* File is not compressed */ | 365 | /* File is not compressed. |
369 | //FIXME: avoid seek | 366 | * We already read first few bytes, account for that. |
370 | xlseek(xstate->src_fd, - xstate->signature_skipped, SEEK_CUR); | 367 | * Example where it happens: |
368 | * "modinfo MODULE.ko" (not compressed) | ||
369 | * open("MODULE.ko", O_RDONLY|O_LARGEFILE) = 4 | ||
370 | * read(4, "\177E", 2) = 2 | ||
371 | * fstat64(4, ...) | ||
372 | * mmap(...) | ||
373 | * read(4, "LF\2\1\1\0\0\0\0"... | ||
374 | * ...and we avoided seeking on the fd! :) | ||
375 | */ | ||
376 | image = xmalloc_read_with_initial_buf( | ||
377 | xstate->src_fd, | ||
378 | maxsz_p, | ||
379 | xmemdup(&xstate->magic, xstate->signature_skipped), | ||
380 | xstate->signature_skipped | ||
381 | ); | ||
371 | xstate->signature_skipped = 0; | 382 | xstate->signature_skipped = 0; |
372 | image = xmalloc_read(xstate->src_fd, maxsz_p); | ||
373 | } | 383 | } |
374 | 384 | ||
375 | if (!image) | 385 | if (!image) |
diff --git a/coreutils/dd.c b/coreutils/dd.c index 2d91f77ef..3054ec6ea 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
@@ -195,23 +195,15 @@ static void dd_output_status(int UNUSED_PARAM cur_signal) | |||
195 | #endif | 195 | #endif |
196 | } | 196 | } |
197 | 197 | ||
198 | static ssize_t full_write_or_warn(const void *buf, size_t len, | ||
199 | const char *const filename) | ||
200 | { | ||
201 | ssize_t n = full_write(ofd, buf, len); | ||
202 | if (n < 0) | ||
203 | bb_perror_msg("writing '%s'", filename); | ||
204 | return n; | ||
205 | } | ||
206 | |||
207 | static bool write_and_stats(const void *buf, size_t len, size_t obs, | 198 | static bool write_and_stats(const void *buf, size_t len, size_t obs, |
208 | const char *filename) | 199 | const char *filename) |
209 | { | 200 | { |
210 | ssize_t n = full_write_or_warn(buf, len, filename); | 201 | ssize_t n; |
211 | if (n < 0) | 202 | |
212 | return 1; | 203 | n = full_write(ofd, buf, len); |
213 | #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE | 204 | #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE |
214 | G.total_bytes += n; | 205 | if (n > 0) |
206 | G.total_bytes += n; | ||
215 | #endif | 207 | #endif |
216 | if ((size_t)n == obs) { | 208 | if ((size_t)n == obs) { |
217 | G.out_full++; | 209 | G.out_full++; |
@@ -221,6 +213,14 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs, | |||
221 | G.out_part++; | 213 | G.out_part++; |
222 | return 0; | 214 | return 0; |
223 | } | 215 | } |
216 | /* n is < len (and possibly is -1). | ||
217 | * Even if n >= 0, errno is usually set correctly. | ||
218 | * For example, if writing to block device and getting ENOSPC, | ||
219 | * full_write() first sees a short write, then tries to write | ||
220 | * the remainder and gets errno set to ENOSPC. | ||
221 | * It returns n > 0 (the amount which it did write). | ||
222 | */ | ||
223 | bb_perror_msg("error writing '%s'", filename); | ||
224 | return 1; | 224 | return 1; |
225 | } | 225 | } |
226 | 226 | ||
diff --git a/coreutils/ln.c b/coreutils/ln.c index 3fe2f3f64..afeb0d72d 100644 --- a/coreutils/ln.c +++ b/coreutils/ln.c | |||
@@ -29,7 +29,7 @@ | |||
29 | //usage: "\n -n Don't dereference symlinks - treat like normal file" | 29 | //usage: "\n -n Don't dereference symlinks - treat like normal file" |
30 | //usage: "\n -b Make a backup of the target (if exists) before link operation" | 30 | //usage: "\n -b Make a backup of the target (if exists) before link operation" |
31 | //usage: "\n -S suf Use suffix instead of ~ when making backup files" | 31 | //usage: "\n -S suf Use suffix instead of ~ when making backup files" |
32 | //usage: "\n -T 2nd arg must be a DIR" | 32 | //usage: "\n -T Treat LINK as a file, not DIR" |
33 | //usage: "\n -v Verbose" | 33 | //usage: "\n -v Verbose" |
34 | //usage: | 34 | //usage: |
35 | //usage:#define ln_example_usage | 35 | //usage:#define ln_example_usage |
diff --git a/coreutils/ls.c b/coreutils/ls.c index 6be3eb291..3eff5a949 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c | |||
@@ -1096,7 +1096,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
1096 | static const char ls_longopts[] ALIGN1 = | 1096 | static const char ls_longopts[] ALIGN1 = |
1097 | "full-time\0" No_argument "\xff" | 1097 | "full-time\0" No_argument "\xff" |
1098 | "group-directories-first\0" No_argument "\xfe" | 1098 | "group-directories-first\0" No_argument "\xfe" |
1099 | "color\0" Optional_argument "\xfd" | 1099 | IF_FEATURE_LS_COLOR("color\0" Optional_argument "\xfd") |
1100 | ; | 1100 | ; |
1101 | #endif | 1101 | #endif |
1102 | 1102 | ||
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 3a4c1044a..72642ae74 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c | |||
@@ -94,7 +94,7 @@ Misc options: | |||
94 | //usage: "\n -n NAME Match processes with NAME" | 94 | //usage: "\n -n NAME Match processes with NAME" |
95 | //usage: "\n in comm field in /proc/PID/stat" | 95 | //usage: "\n in comm field in /proc/PID/stat" |
96 | //usage: "\n -x EXECUTABLE Match processes with this command" | 96 | //usage: "\n -x EXECUTABLE Match processes with this command" |
97 | //usage: "\n command in /proc/PID/cmdline" | 97 | //usage: "\n in /proc/PID/cmdline" |
98 | //usage: "\n -p FILE Match a process with PID from FILE" | 98 | //usage: "\n -p FILE Match a process with PID from FILE" |
99 | //usage: "\n All specified conditions must match" | 99 | //usage: "\n All specified conditions must match" |
100 | //usage: "\n-S only:" | 100 | //usage: "\n-S only:" |
@@ -452,31 +452,34 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | |||
452 | // "start-stop-daemon -S -a sleep -- 5" | 452 | // "start-stop-daemon -S -a sleep -- 5" |
453 | // NB: -n option does _not_ behave in this way: this will try to execute "5": | 453 | // NB: -n option does _not_ behave in this way: this will try to execute "5": |
454 | // "start-stop-daemon -S -n sleep -- 5" | 454 | // "start-stop-daemon -S -n sleep -- 5" |
455 | if (!execname) { /* -x is not given */ | 455 | if (opt & CTX_START) { |
456 | execname = startas; | 456 | if (!execname) { /* -x is not given */ |
457 | if (!execname) { /* neither -x nor -a is given */ | 457 | execname = startas; |
458 | execname = argv[0]; | 458 | if (!execname) { /* neither -x nor -a is given */ |
459 | if (!execname) | 459 | execname = argv[0]; |
460 | bb_show_usage(); | 460 | if (!execname) |
461 | argv++; | 461 | bb_show_usage(); |
462 | argv++; | ||
463 | } | ||
462 | } | 464 | } |
465 | if (!startas) /* -a is not given: use -x EXECUTABLE or argv[0] */ | ||
466 | startas = execname; | ||
467 | *--argv = startas; | ||
468 | } | ||
469 | if (execname) { | ||
470 | G.execname_sizeof = strlen(execname) + 1; | ||
471 | G.execname_cmpbuf = xmalloc(G.execname_sizeof + 1); | ||
463 | } | 472 | } |
464 | if (!startas) /* -a is not given: use -x EXECUTABLE or argv[0] */ | ||
465 | startas = execname; | ||
466 | *--argv = startas; | ||
467 | G.execname_sizeof = strlen(execname) + 1; | ||
468 | G.execname_cmpbuf = xmalloc(G.execname_sizeof + 1); | ||
469 | |||
470 | // IF_FEATURE_START_STOP_DAEMON_FANCY( | 473 | // IF_FEATURE_START_STOP_DAEMON_FANCY( |
471 | // if (retry_arg) | 474 | // if (retry_arg) |
472 | // retries = xatoi_positive(retry_arg); | 475 | // retries = xatoi_positive(retry_arg); |
473 | // ) | 476 | // ) |
474 | |||
475 | if (userspec) { | 477 | if (userspec) { |
476 | user_id = bb_strtou(userspec, NULL, 10); | 478 | user_id = bb_strtou(userspec, NULL, 10); |
477 | if (errno) | 479 | if (errno) |
478 | user_id = xuname2uid(userspec); | 480 | user_id = xuname2uid(userspec); |
479 | } | 481 | } |
482 | |||
480 | /* Both start and stop need to know current processes */ | 483 | /* Both start and stop need to know current processes */ |
481 | do_procinit(); | 484 | do_procinit(); |
482 | 485 | ||
@@ -485,6 +488,8 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | |||
485 | return (opt & OPT_OKNODO) ? 0 : (i <= 0); | 488 | return (opt & OPT_OKNODO) ? 0 : (i <= 0); |
486 | } | 489 | } |
487 | 490 | ||
491 | /* else: CTX_START (-S). execname can't be NULL. */ | ||
492 | |||
488 | if (G.found_procs) { | 493 | if (G.found_procs) { |
489 | if (!QUIET) | 494 | if (!QUIET) |
490 | printf("%s is already running\n", execname); | 495 | printf("%s is already running\n", execname); |
diff --git a/editors/sed.c b/editors/sed.c index a5cedbd8d..a93e5494a 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -1108,6 +1108,8 @@ static void process_files(void) | |||
1108 | int old_matched, matched; | 1108 | int old_matched, matched; |
1109 | 1109 | ||
1110 | old_matched = sed_cmd->in_match; | 1110 | old_matched = sed_cmd->in_match; |
1111 | if (!old_matched) | ||
1112 | sed_cmd->end_line = sed_cmd->end_line_orig; | ||
1111 | 1113 | ||
1112 | /* Determine if this command matches this line: */ | 1114 | /* Determine if this command matches this line: */ |
1113 | 1115 | ||
diff --git a/editors/vi.c b/editors/vi.c index a8b4dc5a4..70c8f3daf 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -3067,11 +3067,14 @@ static void do_cmd(int c); | |||
3067 | static int find_range(char **start, char **stop, char c) | 3067 | static int find_range(char **start, char **stop, char c) |
3068 | { | 3068 | { |
3069 | char *save_dot, *p, *q, *t; | 3069 | char *save_dot, *p, *q, *t; |
3070 | int cnt, multiline = 0; | 3070 | int cnt, multiline = 0, forward; |
3071 | 3071 | ||
3072 | save_dot = dot; | 3072 | save_dot = dot; |
3073 | p = q = dot; | 3073 | p = q = dot; |
3074 | 3074 | ||
3075 | // will a 'G' command move forwards or backwards? | ||
3076 | forward = cmdcnt == 0 || cmdcnt > count_lines(text, dot); | ||
3077 | |||
3075 | if (strchr("cdy><", c)) { | 3078 | if (strchr("cdy><", c)) { |
3076 | // these cmds operate on whole lines | 3079 | // these cmds operate on whole lines |
3077 | p = q = begin_line(p); | 3080 | p = q = begin_line(p); |
@@ -3095,13 +3098,13 @@ static int find_range(char **start, char **stop, char c) | |||
3095 | if (dot > text && *dot == '\n') | 3098 | if (dot > text && *dot == '\n') |
3096 | dot--; // stay off NL | 3099 | dot--; // stay off NL |
3097 | q = dot; | 3100 | q = dot; |
3098 | } else if (strchr("H-k{", c)) { | 3101 | } else if (strchr("H-k{", c) || (c == 'G' && !forward)) { |
3099 | // these operate on multi-lines backwards | 3102 | // these operate on multi-lines backwards |
3100 | q = end_line(dot); // find NL | 3103 | q = end_line(dot); // find NL |
3101 | do_cmd(c); // execute movement cmd | 3104 | do_cmd(c); // execute movement cmd |
3102 | dot_begin(); | 3105 | dot_begin(); |
3103 | p = dot; | 3106 | p = dot; |
3104 | } else if (strchr("L+j}\r\n", c)) { | 3107 | } else if (strchr("L+j}\r\n", c) || (c == 'G' && forward)) { |
3105 | // these operate on multi-lines forwards | 3108 | // these operate on multi-lines forwards |
3106 | p = begin_line(dot); | 3109 | p = begin_line(dot); |
3107 | do_cmd(c); // execute movement cmd | 3110 | do_cmd(c); // execute movement cmd |
@@ -3836,11 +3839,10 @@ static void do_cmd(int c) | |||
3836 | if (c1 == 27) { // ESC- user changed mind and wants out | 3839 | if (c1 == 27) { // ESC- user changed mind and wants out |
3837 | c = c1 = 27; // Escape- do nothing | 3840 | c = c1 = 27; // Escape- do nothing |
3838 | } else if (strchr("wW", c1)) { | 3841 | } else if (strchr("wW", c1)) { |
3842 | ml = 0; // multi-line ranges aren't allowed for words | ||
3839 | if (c == 'c') { | 3843 | if (c == 'c') { |
3840 | // don't include trailing WS as part of word | 3844 | // don't include trailing WS as part of word |
3841 | while (isblank(*q)) { | 3845 | while (isspace(*q) && q > p) { |
3842 | if (q <= text || q[-1] == '\n') | ||
3843 | break; | ||
3844 | q--; | 3846 | q--; |
3845 | } | 3847 | } |
3846 | } | 3848 | } |
@@ -3848,7 +3850,7 @@ static void do_cmd(int c) | |||
3848 | } else if (strchr("^0bBeEft%$ lh\b\177", c1)) { | 3850 | } else if (strchr("^0bBeEft%$ lh\b\177", c1)) { |
3849 | // partial line copy text into a register and delete | 3851 | // partial line copy text into a register and delete |
3850 | dot = yank_delete(p, q, ml, yf, ALLOW_UNDO); // delete word | 3852 | dot = yank_delete(p, q, ml, yf, ALLOW_UNDO); // delete word |
3851 | } else if (strchr("cdykjHL+-{}\r\n", c1)) { | 3853 | } else if (strchr("cdykjGHL+-{}\r\n", c1)) { |
3852 | // whole line copy text into a register and delete | 3854 | // whole line copy text into a register and delete |
3853 | dot = yank_delete(p, q, ml, yf, ALLOW_UNDO); // delete lines | 3855 | dot = yank_delete(p, q, ml, yf, ALLOW_UNDO); // delete lines |
3854 | whole = 1; | 3856 | whole = 1; |
diff --git a/examples/shutdown-1.0/script/stop_storage b/examples/shutdown-1.0/script/stop_storage index 1be5f735b..50f3b4dd2 100755 --- a/examples/shutdown-1.0/script/stop_storage +++ b/examples/shutdown-1.0/script/stop_storage | |||
@@ -4,7 +4,7 @@ | |||
4 | # Repeat. | 4 | # Repeat. |
5 | 5 | ||
6 | umountcnt=2 | 6 | umountcnt=2 |
7 | writeout=0 # increase if your kernel doesn ot guarantee writes to complete | 7 | writeout=0 # increase if your kernel does not guarantee writes to complete |
8 | 8 | ||
9 | # No /usr - we are expecting all binaries to be accessible | 9 | # No /usr - we are expecting all binaries to be accessible |
10 | # from root fs alone | 10 | # from root fs alone |
diff --git a/examples/udhcp/udhcpd.conf b/examples/udhcp/udhcpd.conf index bb8774e08..df1258aaf 100644 --- a/examples/udhcp/udhcpd.conf +++ b/examples/udhcp/udhcpd.conf | |||
@@ -44,7 +44,7 @@ interface eth0 | |||
44 | #notify_file # default: no script | 44 | #notify_file # default: no script |
45 | #notify_file dumpleases # useful for debugging | 45 | #notify_file dumpleases # useful for debugging |
46 | 46 | ||
47 | # The following are bootp specific options | 47 | # The following are BOOTP specific options |
48 | # next server to use in bootstrap | 48 | # next server to use in bootstrap |
49 | #siaddr 192.168.0.22 # default: 0.0.0.0 (none) | 49 | #siaddr 192.168.0.22 # default: 0.0.0.0 (none) |
50 | # tftp server name | 50 | # tftp server name |
@@ -52,9 +52,14 @@ interface eth0 | |||
52 | # tftp file to download (e.g. kernel image) | 52 | # tftp file to download (e.g. kernel image) |
53 | #boot_file /var/nfs_root # default: none | 53 | #boot_file /var/nfs_root # default: none |
54 | 54 | ||
55 | # NOTE: "boot_file FILE" and "opt bootfile FILE" are conceptually the same, | ||
56 | # but "boot_file" goes into BOOTP-defined fixed-size field in the packet, | ||
57 | # whereas "opt bootfile" goes into DHCP option 0x43. | ||
58 | # Same for "sname HOST" and "opt tftp HOST". | ||
59 | |||
55 | # Static leases map | 60 | # Static leases map |
56 | #static_lease 00:60:08:11:CE:4E 192.168.0.54 | 61 | #static_lease 00:60:08:11:CE:4E 192.168.0.54 |
57 | #static_lease 00:60:08:11:CE:3E 192.168.0.44 | 62 | #static_lease 00:60:08:11:CE:3E 192.168.0.44 optional_hostname |
58 | 63 | ||
59 | # The remainder of options are DHCP options and can be specified with the | 64 | # The remainder of options are DHCP options and can be specified with the |
60 | # keyword 'opt' or 'option'. If an option can take multiple items, such | 65 | # keyword 'opt' or 'option'. If an option can take multiple items, such |
diff --git a/examples/var_service/dhcp_if/run b/examples/var_service/dhcp_if/run index d8f343586..882f008d6 100755 --- a/examples/var_service/dhcp_if/run +++ b/examples/var_service/dhcp_if/run | |||
@@ -8,7 +8,7 @@ pwd="$PWD" | |||
8 | if="${PWD##*/dhcp_}" | 8 | if="${PWD##*/dhcp_}" |
9 | 9 | ||
10 | echo "* Upping iface $if" | 10 | echo "* Upping iface $if" |
11 | ip link set dev "$if" up || { sleep 5; exit; } | 11 | ip link set dev "$if" up || exec sleep 5 |
12 | 12 | ||
13 | echo "* Starting udhcpc on $if [$$]" | 13 | echo "* Starting udhcpc on $if [$$]" |
14 | exec \ | 14 | exec \ |
diff --git a/examples/var_service/dhcpd_if/run b/examples/var_service/dhcpd_if/run index e3d1b00f4..82ac08aa4 100755 --- a/examples/var_service/dhcpd_if/run +++ b/examples/var_service/dhcpd_if/run | |||
@@ -8,7 +8,7 @@ pwd="$PWD" | |||
8 | if="${PWD##*/dhcpd_}" | 8 | if="${PWD##*/dhcpd_}" |
9 | 9 | ||
10 | echo "* Upping iface $if" | 10 | echo "* Upping iface $if" |
11 | ip link set dev $if up || { sleep 5; exit; } | 11 | ip link set dev $if up || exec sleep 5 |
12 | 12 | ||
13 | >>udhcpd.leases | 13 | >>udhcpd.leases |
14 | sed 's/^interface.*$/interface '"$if/" -i udhcpd.conf | 14 | sed 's/^interface.*$/interface '"$if/" -i udhcpd.conf |
diff --git a/examples/var_service/ifplugd_if/run b/examples/var_service/ifplugd_if/run index e7816619d..cfddfec06 100755 --- a/examples/var_service/ifplugd_if/run +++ b/examples/var_service/ifplugd_if/run | |||
@@ -9,7 +9,7 @@ pwd="$PWD" | |||
9 | if="${PWD##*/ifplugd_}" | 9 | if="${PWD##*/ifplugd_}" |
10 | 10 | ||
11 | echo "* Upping iface $if" | 11 | echo "* Upping iface $if" |
12 | ip link set dev "$if" up || { sleep 5; exit; } | 12 | ip link set dev "$if" up || exec sleep 5 |
13 | 13 | ||
14 | echo "* Starting ifplugd on $if [$$]" | 14 | echo "* Starting ifplugd on $if [$$]" |
15 | exec \ | 15 | exec \ |
diff --git a/examples/var_service/supplicant_if/run b/examples/var_service/supplicant_if/run index bc16fb606..5c813b07f 100755 --- a/examples/var_service/supplicant_if/run +++ b/examples/var_service/supplicant_if/run | |||
@@ -9,7 +9,7 @@ if="${PWD##*/dhcp_}" | |||
9 | 9 | ||
10 | echo "* Upping iface $if" | 10 | echo "* Upping iface $if" |
11 | # "or sleep" idiom prevents rapid respawning if iface does not exist | 11 | # "or sleep" idiom prevents rapid respawning if iface does not exist |
12 | ip link set dev "$if" up || { sleep 5; exit; } | 12 | ip link set dev "$if" up || exec sleep 5 |
13 | 13 | ||
14 | ##echo "* Powersave disable on $if" | 14 | ##echo "* Powersave disable on $if" |
15 | ##iw dev "$if" set power_save off | 15 | ##iw dev "$if" set power_save off |
diff --git a/examples/var_service/zcip_if/run b/examples/var_service/zcip_if/run index 699823246..69f8b9bae 100755 --- a/examples/var_service/zcip_if/run +++ b/examples/var_service/zcip_if/run | |||
@@ -8,7 +8,7 @@ pwd="$PWD" | |||
8 | if="${PWD##*/zcip_}" | 8 | if="${PWD##*/zcip_}" |
9 | 9 | ||
10 | echo "* Upping iface $if" | 10 | echo "* Upping iface $if" |
11 | ip link set dev "$if" up || { sleep 5; exit; } | 11 | ip link set dev "$if" up || exec sleep 5 |
12 | 12 | ||
13 | echo "* Starting zcip on $if [$$]" | 13 | echo "* Starting zcip on $if [$$]" |
14 | exec \ | 14 | exec \ |
diff --git a/include/bb_archive.h b/include/bb_archive.h index b2cb7b347..58e4c21bb 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h | |||
@@ -252,6 +252,12 @@ typedef struct transformer_state_t { | |||
252 | off_t bytes_in; /* used in unzip code only: needs to know packed size */ | 252 | off_t bytes_in; /* used in unzip code only: needs to know packed size */ |
253 | uint32_t crc32; | 253 | uint32_t crc32; |
254 | time_t mtime; /* gunzip code may set this on exit */ | 254 | time_t mtime; /* gunzip code may set this on exit */ |
255 | |||
256 | union { /* if we read magic, it's saved here */ | ||
257 | uint8_t b[8]; | ||
258 | uint16_t b16[4]; | ||
259 | uint32_t b32[2]; | ||
260 | } magic; | ||
255 | } transformer_state_t; | 261 | } transformer_state_t; |
256 | 262 | ||
257 | void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; | 263 | void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; |
diff --git a/include/libbb.h b/include/libbb.h index 05a0c575c..9da94638b 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -920,6 +920,7 @@ extern ssize_t open_read_close(const char *filename, void *buf, size_t maxsz) FA | |||
920 | extern char *xmalloc_reads(int fd, size_t *maxsz_p) FAST_FUNC; | 920 | extern char *xmalloc_reads(int fd, size_t *maxsz_p) FAST_FUNC; |
921 | /* Reads block up to *maxsz_p (default: INT_MAX - 4095) */ | 921 | /* Reads block up to *maxsz_p (default: INT_MAX - 4095) */ |
922 | extern void *xmalloc_read(int fd, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | 922 | extern void *xmalloc_read(int fd, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; |
923 | extern void *xmalloc_read_with_initial_buf(int fd, size_t *maxsz_p, char *buf, size_t total) FAST_FUNC; | ||
923 | /* Returns NULL if file can't be opened (default max size: INT_MAX - 4095) */ | 924 | /* Returns NULL if file can't be opened (default max size: INT_MAX - 4095) */ |
924 | extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | 925 | extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; |
925 | /* Never returns NULL */ | 926 | /* Never returns NULL */ |
@@ -1359,7 +1360,6 @@ enum { | |||
1359 | LOGMODE_BOTH = LOGMODE_SYSLOG + LOGMODE_STDIO, | 1360 | LOGMODE_BOTH = LOGMODE_SYSLOG + LOGMODE_STDIO, |
1360 | }; | 1361 | }; |
1361 | extern const char *msg_eol; | 1362 | extern const char *msg_eol; |
1362 | extern smallint syslog_level; | ||
1363 | extern smallint logmode; | 1363 | extern smallint logmode; |
1364 | extern uint8_t xfunc_error_retval; | 1364 | extern uint8_t xfunc_error_retval; |
1365 | extern void (*die_func)(void); | 1365 | extern void (*die_func)(void); |
@@ -1379,6 +1379,14 @@ void bb_verror_msg(const char *s, va_list p, const char *strerr) FAST_FUNC; | |||
1379 | void bb_die_memory_exhausted(void) NORETURN FAST_FUNC; | 1379 | void bb_die_memory_exhausted(void) NORETURN FAST_FUNC; |
1380 | void bb_logenv_override(void) FAST_FUNC; | 1380 | void bb_logenv_override(void) FAST_FUNC; |
1381 | 1381 | ||
1382 | #if ENABLE_FEATURE_SYSLOG_INFO | ||
1383 | void bb_info_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; | ||
1384 | void bb_vinfo_msg(const char *s, va_list p) FAST_FUNC; | ||
1385 | #else | ||
1386 | #define bb_info_msg bb_error_msg | ||
1387 | #define bb_vinfo_msg(s,p) bb_verror_msg(s,p,NULL) | ||
1388 | #endif | ||
1389 | |||
1382 | /* We need to export XXX_main from libbusybox | 1390 | /* We need to export XXX_main from libbusybox |
1383 | * only if we build "individual" binaries | 1391 | * only if we build "individual" binaries |
1384 | */ | 1392 | */ |
diff --git a/libbb/find_mount_point.c b/libbb/find_mount_point.c index 341c30102..edf734614 100644 --- a/libbb/find_mount_point.c +++ b/libbb/find_mount_point.c | |||
@@ -70,11 +70,22 @@ struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too) | |||
70 | continue; | 70 | continue; |
71 | 71 | ||
72 | /* Is device's dev_t == name's dev_t? */ | 72 | /* Is device's dev_t == name's dev_t? */ |
73 | if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == devno_of_name) | 73 | if (mountEntry->mnt_fsname[0] == '/' |
74 | /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
75 | * avoid stat'ing "sysfs", "proc", "none" and such, | ||
76 | * useless at best, can stat unrelated files at worst. | ||
77 | */ | ||
78 | && stat(mountEntry->mnt_fsname, &s) == 0 | ||
79 | && s.st_rdev == devno_of_name | ||
80 | ) { | ||
74 | break; | 81 | break; |
82 | } | ||
75 | /* Match the directory's mount point. */ | 83 | /* Match the directory's mount point. */ |
76 | if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == devno_of_name) | 84 | if (stat(mountEntry->mnt_dir, &s) == 0 |
85 | && s.st_dev == devno_of_name | ||
86 | ) { | ||
77 | break; | 87 | break; |
88 | } | ||
78 | } | 89 | } |
79 | endmntent(mtab_fp); | 90 | endmntent(mtab_fp); |
80 | #else | 91 | #else |
diff --git a/libbb/full_write.c b/libbb/full_write.c index 2b7983f4c..15766fc6c 100644 --- a/libbb/full_write.c +++ b/libbb/full_write.c | |||
@@ -11,7 +11,8 @@ | |||
11 | /* | 11 | /* |
12 | * Write all of the supplied buffer out to a file. | 12 | * Write all of the supplied buffer out to a file. |
13 | * This does multiple writes as necessary. | 13 | * This does multiple writes as necessary. |
14 | * Returns the amount written, or -1 on an error. | 14 | * Returns the amount written, or -1 if error was seen |
15 | * on the very first write. | ||
15 | */ | 16 | */ |
16 | ssize_t FAST_FUNC full_write(int fd, const void *buf, size_t len) | 17 | ssize_t FAST_FUNC full_write(int fd, const void *buf, size_t len) |
17 | { | 18 | { |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 191bc0598..9781b4a08 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -70,13 +70,20 @@ | |||
70 | #if ENABLE_UNICODE_SUPPORT | 70 | #if ENABLE_UNICODE_SUPPORT |
71 | # define BB_NUL ((wchar_t)0) | 71 | # define BB_NUL ((wchar_t)0) |
72 | # define CHAR_T wchar_t | 72 | # define CHAR_T wchar_t |
73 | static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); } | 73 | static bool BB_isspace(CHAR_T c) |
74 | { | ||
75 | return ((unsigned)c < 256 && isspace(c)); | ||
76 | } | ||
74 | # if ENABLE_FEATURE_EDITING_VI | 77 | # if ENABLE_FEATURE_EDITING_VI |
75 | static bool BB_isalnum_or_underscore(CHAR_T c) { | 78 | static bool BB_isalnum_or_underscore(CHAR_T c) |
79 | { | ||
76 | return ((unsigned)c < 256 && isalnum(c)) || c == '_'; | 80 | return ((unsigned)c < 256 && isalnum(c)) || c == '_'; |
77 | } | 81 | } |
78 | # endif | 82 | # endif |
79 | static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } | 83 | static bool BB_ispunct(CHAR_T c) |
84 | { | ||
85 | return ((unsigned)c < 256 && ispunct(c)); | ||
86 | } | ||
80 | # undef isspace | 87 | # undef isspace |
81 | # undef isalnum | 88 | # undef isalnum |
82 | # undef ispunct | 89 | # undef ispunct |
diff --git a/libbb/read_printf.c b/libbb/read_printf.c index e47ac7afe..1e67d6542 100644 --- a/libbb/read_printf.c +++ b/libbb/read_printf.c | |||
@@ -107,10 +107,9 @@ char* FAST_FUNC xmalloc_reads(int fd, size_t *maxsz_p) | |||
107 | 107 | ||
108 | // Read (potentially big) files in one go. File size is estimated | 108 | // Read (potentially big) files in one go. File size is estimated |
109 | // by stat. Extra '\0' byte is appended. | 109 | // by stat. Extra '\0' byte is appended. |
110 | void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p) | 110 | void* FAST_FUNC xmalloc_read_with_initial_buf(int fd, size_t *maxsz_p, char *buf, size_t total) |
111 | { | 111 | { |
112 | char *buf; | 112 | size_t size, rd_size; |
113 | size_t size, rd_size, total; | ||
114 | size_t to_read; | 113 | size_t to_read; |
115 | struct stat st; | 114 | struct stat st; |
116 | 115 | ||
@@ -123,8 +122,6 @@ void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p) | |||
123 | /* In order to make such files readable, we add small const */ | 122 | /* In order to make such files readable, we add small const */ |
124 | size = (st.st_size | 0x3ff) + 1; | 123 | size = (st.st_size | 0x3ff) + 1; |
125 | 124 | ||
126 | total = 0; | ||
127 | buf = NULL; | ||
128 | while (1) { | 125 | while (1) { |
129 | if (to_read < size) | 126 | if (to_read < size) |
130 | size = to_read; | 127 | size = to_read; |
@@ -153,6 +150,11 @@ void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p) | |||
153 | return buf; | 150 | return buf; |
154 | } | 151 | } |
155 | 152 | ||
153 | void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p) | ||
154 | { | ||
155 | return xmalloc_read_with_initial_buf(fd, maxsz_p, NULL, 0); | ||
156 | } | ||
157 | |||
156 | #ifdef USING_LSEEK_TO_GET_SIZE | 158 | #ifdef USING_LSEEK_TO_GET_SIZE |
157 | /* Alternatively, file size can be obtained by lseek to the end. | 159 | /* Alternatively, file size can be obtained by lseek to the end. |
158 | * The code is slightly bigger. Retained in case fstat approach | 160 | * The code is slightly bigger. Retained in case fstat approach |
diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index 22c30357b..6d3459905 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | #if ENABLE_FEATURE_SYSLOG | 14 | #if ENABLE_FEATURE_SYSLOG |
15 | smallint syslog_level = LOG_ERR; | 15 | static smallint syslog_level = LOG_ERR; |
16 | #endif | 16 | #endif |
17 | smallint logmode = LOGMODE_STDIO; | 17 | smallint logmode = LOGMODE_STDIO; |
18 | const char *msg_eol = "\n"; | 18 | const char *msg_eol = "\n"; |
@@ -154,7 +154,7 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) | |||
154 | } | 154 | } |
155 | # if ENABLE_FEATURE_SYSLOG | 155 | # if ENABLE_FEATURE_SYSLOG |
156 | if (logmode & LOGMODE_SYSLOG) { | 156 | if (logmode & LOGMODE_SYSLOG) { |
157 | syslog(LOG_ERR, "%s", msgc); | 157 | syslog(syslog_level, "%s", msgc); |
158 | } | 158 | } |
159 | # endif | 159 | # endif |
160 | free(msgc); | 160 | free(msgc); |
@@ -180,3 +180,21 @@ void FAST_FUNC bb_error_msg(const char *s, ...) | |||
180 | bb_verror_msg(s, p, NULL); | 180 | bb_verror_msg(s, p, NULL); |
181 | va_end(p); | 181 | va_end(p); |
182 | } | 182 | } |
183 | |||
184 | #if ENABLE_FEATURE_SYSLOG_INFO | ||
185 | void FAST_FUNC bb_vinfo_msg(const char *s, va_list p) | ||
186 | { | ||
187 | syslog_level = LOG_INFO; | ||
188 | bb_verror_msg(s, p, NULL); | ||
189 | syslog_level = LOG_ERR; | ||
190 | } | ||
191 | |||
192 | void FAST_FUNC bb_info_msg(const char *s, ...) | ||
193 | { | ||
194 | va_list p; | ||
195 | |||
196 | va_start(p, s); | ||
197 | bb_vinfo_msg(s, p); | ||
198 | va_end(p); | ||
199 | } | ||
200 | #endif | ||
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 2d497d754..26e1776a4 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -268,12 +268,6 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv) | |||
268 | if (flags & DAEMON_CHDIR_ROOT) | 268 | if (flags & DAEMON_CHDIR_ROOT) |
269 | xchdir("/"); | 269 | xchdir("/"); |
270 | 270 | ||
271 | if (flags & DAEMON_DEVNULL_STDIO) { | ||
272 | close(0); | ||
273 | close(1); | ||
274 | close(2); | ||
275 | } | ||
276 | |||
277 | fd = open(bb_dev_null, O_RDWR); | 271 | fd = open(bb_dev_null, O_RDWR); |
278 | if (fd < 0) { | 272 | if (fd < 0) { |
279 | /* NB: we can be called as bb_sanitize_stdio() from init | 273 | /* NB: we can be called as bb_sanitize_stdio() from init |
@@ -283,8 +277,15 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv) | |||
283 | fd = xopen("/", O_RDONLY); /* don't believe this can fail */ | 277 | fd = xopen("/", O_RDONLY); /* don't believe this can fail */ |
284 | } | 278 | } |
285 | 279 | ||
286 | while ((unsigned)fd < 2) | 280 | if (flags & DAEMON_DEVNULL_STDIO) { |
287 | fd = dup(fd); /* have 0,1,2 open at least to /dev/null */ | 281 | xdup2(fd, 0); |
282 | xdup2(fd, 1); | ||
283 | xdup2(fd, 2); | ||
284 | } else { | ||
285 | /* have 0,1,2 open at least to /dev/null */ | ||
286 | while ((unsigned)fd < 2) | ||
287 | fd = dup(fd); | ||
288 | } | ||
288 | 289 | ||
289 | if (!(flags & DAEMON_ONLY_SANITIZE)) { | 290 | if (!(flags & DAEMON_ONLY_SANITIZE)) { |
290 | 291 | ||
diff --git a/loginutils/chpasswd.c b/loginutils/chpasswd.c index 4b3602e7a..dd0532c66 100644 --- a/loginutils/chpasswd.c +++ b/loginutils/chpasswd.c | |||
@@ -114,7 +114,7 @@ int chpasswd_main(int argc UNUSED_PARAM, char **argv) | |||
114 | if (rc < 0) | 114 | if (rc < 0) |
115 | bb_error_msg_and_die("an error occurred updating password for %s", name); | 115 | bb_error_msg_and_die("an error occurred updating password for %s", name); |
116 | if (rc) | 116 | if (rc) |
117 | bb_error_msg("password for '%s' changed", name); | 117 | bb_info_msg("password for '%s' changed", name); |
118 | logmode = LOGMODE_STDIO; | 118 | logmode = LOGMODE_STDIO; |
119 | free(name); | 119 | free(name); |
120 | free(free_me); | 120 | free(free_me); |
diff --git a/loginutils/login.c b/loginutils/login.c index 4df651cc6..a08642a34 100644 --- a/loginutils/login.c +++ b/loginutils/login.c | |||
@@ -534,7 +534,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |||
534 | wait_for_exitstatus(child_pid); | 534 | wait_for_exitstatus(child_pid); |
535 | update_utmp_DEAD_PROCESS(child_pid); | 535 | update_utmp_DEAD_PROCESS(child_pid); |
536 | } | 536 | } |
537 | IF_PAM(login_pam_end(pamh);) | 537 | login_pam_end(pamh); |
538 | return 0; | 538 | return 0; |
539 | } | 539 | } |
540 | #endif | 540 | #endif |
diff --git a/loginutils/passwd.c b/loginutils/passwd.c index 30e096460..6c643d3d0 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c | |||
@@ -228,7 +228,7 @@ int passwd_main(int argc UNUSED_PARAM, char **argv) | |||
228 | /* LOGMODE_BOTH */ | 228 | /* LOGMODE_BOTH */ |
229 | if (rc < 0) | 229 | if (rc < 0) |
230 | bb_error_msg_and_die("can't update password file %s", filename); | 230 | bb_error_msg_and_die("can't update password file %s", filename); |
231 | bb_error_msg("password for %s changed by %s", name, myname); | 231 | bb_info_msg("password for %s changed by %s", name, myname); |
232 | 232 | ||
233 | /*if (ENABLE_FEATURE_CLEAN_UP) free(newp); - can't, it may be non-malloced */ | 233 | /*if (ENABLE_FEATURE_CLEAN_UP) free(newp); - can't, it may be non-malloced */ |
234 | skip: | 234 | skip: |
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index 27ea5dff0..9bb4d3613 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c | |||
@@ -68,17 +68,17 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv) | |||
68 | ); | 68 | ); |
69 | if (r < 0) { | 69 | if (r < 0) { |
70 | /* ^D, ^C, timeout, or read error */ | 70 | /* ^D, ^C, timeout, or read error */ |
71 | bb_error_msg("normal startup"); | 71 | bb_info_msg("normal startup"); |
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | if (r > 0) { | 74 | if (r > 0) { |
75 | break; | 75 | break; |
76 | } | 76 | } |
77 | bb_do_delay(LOGIN_FAIL_DELAY); | 77 | bb_do_delay(LOGIN_FAIL_DELAY); |
78 | bb_error_msg("Login incorrect"); | 78 | bb_info_msg("Login incorrect"); |
79 | } | 79 | } |
80 | 80 | ||
81 | bb_error_msg("starting shell for system maintenance"); | 81 | bb_info_msg("starting shell for system maintenance"); |
82 | 82 | ||
83 | IF_SELINUX(renew_current_security_context()); | 83 | IF_SELINUX(renew_current_security_context()); |
84 | 84 | ||
diff --git a/miscutils/crond.c b/miscutils/crond.c index 25e5503c7..b533a3991 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c | |||
@@ -181,9 +181,7 @@ static void crondlog(unsigned level, const char *msg, va_list va) | |||
181 | * need not touch syslog_level | 181 | * need not touch syslog_level |
182 | * (they are ok with LOG_ERR default). | 182 | * (they are ok with LOG_ERR default). |
183 | */ | 183 | */ |
184 | syslog_level = LOG_INFO; | 184 | bb_vinfo_msg(msg, va); |
185 | bb_verror_msg(msg, va, /* strerr: */ NULL); | ||
186 | syslog_level = LOG_ERR; | ||
187 | } | 185 | } |
188 | } | 186 | } |
189 | 187 | ||
@@ -1108,7 +1106,7 @@ int crond_main(int argc UNUSED_PARAM, char **argv) | |||
1108 | process_cron_update_file(); | 1106 | process_cron_update_file(); |
1109 | log5("wakeup dt=%ld", dt); | 1107 | log5("wakeup dt=%ld", dt); |
1110 | if (dt < -60 * 60 || dt > 60 * 60) { | 1108 | if (dt < -60 * 60 || dt > 60 * 60) { |
1111 | bb_error_msg("time disparity of %ld minutes detected", dt / 60); | 1109 | bb_info_msg("time disparity of %ld minutes detected", dt / 60); |
1112 | /* and we do not run any jobs in this case */ | 1110 | /* and we do not run any jobs in this case */ |
1113 | } else if (dt > 0) { | 1111 | } else if (dt > 0) { |
1114 | /* Usual case: time advances forward, as expected */ | 1112 | /* Usual case: time advances forward, as expected */ |
diff --git a/miscutils/dc.c b/miscutils/dc.c index 0d09f5e2b..c7ce2be0b 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c | |||
@@ -35,10 +35,12 @@ enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof( | |||
35 | base = 10; \ | 35 | base = 10; \ |
36 | } while (0) | 36 | } while (0) |
37 | 37 | ||
38 | static void check_under(void) | 38 | static unsigned check_under(void) |
39 | { | 39 | { |
40 | if (pointer == 0) | 40 | unsigned p = pointer; |
41 | if (p == 0) | ||
41 | bb_error_msg_and_die("stack underflow"); | 42 | bb_error_msg_and_die("stack underflow"); |
43 | return p - 1; | ||
42 | } | 44 | } |
43 | 45 | ||
44 | static void push(double a) | 46 | static void push(double a) |
@@ -50,8 +52,9 @@ static void push(double a) | |||
50 | 52 | ||
51 | static double pop(void) | 53 | static double pop(void) |
52 | { | 54 | { |
53 | check_under(); | 55 | unsigned p = check_under(); |
54 | return stack[--pointer]; | 56 | pointer = p; |
57 | return stack[p]; | ||
55 | } | 58 | } |
56 | 59 | ||
57 | static void add(void) | 60 | static void add(void) |
@@ -91,6 +94,19 @@ static void mod(void) | |||
91 | { | 94 | { |
92 | data_t d = pop(); | 95 | data_t d = pop(); |
93 | 96 | ||
97 | /* compat with dc (GNU bc 1.07.1) 1.4.1: | ||
98 | * $ dc -e '4 0 % p' | ||
99 | * dc: remainder by zero | ||
100 | * 0 | ||
101 | */ | ||
102 | if (d == 0) { | ||
103 | bb_error_msg("remainder by zero"); | ||
104 | pop(); | ||
105 | push(0); | ||
106 | return; | ||
107 | } | ||
108 | /* ^^^^ without this, we simply get SIGFPE and die */ | ||
109 | |||
94 | push((data_t) pop() % d); | 110 | push((data_t) pop() % d); |
95 | } | 111 | } |
96 | 112 | ||
@@ -171,8 +187,7 @@ static void print_stack_no_pop(void) | |||
171 | 187 | ||
172 | static void print_no_pop(void) | 188 | static void print_no_pop(void) |
173 | { | 189 | { |
174 | check_under(); | 190 | print_base(stack[check_under()]); |
175 | print_base(stack[pointer-1]); | ||
176 | } | 191 | } |
177 | 192 | ||
178 | struct op { | 193 | struct op { |
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index 3bf06b965..e4d104d0c 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c | |||
@@ -343,7 +343,7 @@ static const char bb_msg_variable_not_found[] ALIGN1 = "variable: %s not found"; | |||
343 | 343 | ||
344 | /* Busybox stuff */ | 344 | /* Busybox stuff */ |
345 | #if ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG | 345 | #if ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG |
346 | #define info_logger(p, fmt, args...) bb_error_msg(fmt, ## args) | 346 | #define info_logger(p, fmt, args...) bb_info_msg(fmt, ## args) |
347 | #define msg_logger(p, fmt, args...) bb_error_msg(fmt, ## args) | 347 | #define msg_logger(p, fmt, args...) bb_error_msg(fmt, ## args) |
348 | #define msg_logger_and_die(p, fmt, args...) bb_error_msg_and_die(fmt, ## args) | 348 | #define msg_logger_and_die(p, fmt, args...) bb_error_msg_and_die(fmt, ## args) |
349 | #define error_logger(p, fmt, args...) bb_perror_msg(fmt, ## args) | 349 | #define error_logger(p, fmt, args...) bb_perror_msg(fmt, ## args) |
diff --git a/modutils/lsmod.c b/modutils/lsmod.c index 694205fda..39dc8e6b7 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c | |||
@@ -66,7 +66,10 @@ static void check_tainted(void) | |||
66 | } | 66 | } |
67 | } | 67 | } |
68 | #else | 68 | #else |
69 | static void check_tainted(void) { putchar('\n'); } | 69 | static ALWAYS_INLINE void check_tainted(void) |
70 | { | ||
71 | putchar('\n'); | ||
72 | } | ||
70 | #endif | 73 | #endif |
71 | 74 | ||
72 | int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 75 | int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
diff --git a/networking/dnsd.c b/networking/dnsd.c index 37a80309d..f2c6bddc6 100644 --- a/networking/dnsd.c +++ b/networking/dnsd.c | |||
@@ -133,7 +133,7 @@ static struct dns_entry *parse_conf_file(const char *fileconf) | |||
133 | } | 133 | } |
134 | 134 | ||
135 | if (OPT_verbose) | 135 | if (OPT_verbose) |
136 | bb_error_msg("name:%s, ip:%s", token[0], token[1]); | 136 | bb_info_msg("name:%s, ip:%s", token[0], token[1]); |
137 | 137 | ||
138 | /* sizeof(*m) includes 1 byte for m->name[0] */ | 138 | /* sizeof(*m) includes 1 byte for m->name[0] */ |
139 | m = xzalloc(sizeof(*m) + strlen(token[0]) + 1); | 139 | m = xzalloc(sizeof(*m) + strlen(token[0]) + 1); |
@@ -438,7 +438,7 @@ static int process_packet(struct dns_entry *conf_data, | |||
438 | answstr = table_lookup(conf_data, type, query_string); | 438 | answstr = table_lookup(conf_data, type, query_string); |
439 | #if DEBUG | 439 | #if DEBUG |
440 | /* Shows lengths instead of dots, unusable for !DEBUG */ | 440 | /* Shows lengths instead of dots, unusable for !DEBUG */ |
441 | bb_error_msg("'%s'->'%s'", query_string, answstr); | 441 | bb_info_msg("'%s'->'%s'", query_string, answstr); |
442 | #endif | 442 | #endif |
443 | outr_rlen = 4; | 443 | outr_rlen = 4; |
444 | if (answstr && type == htons(REQ_PTR)) { | 444 | if (answstr && type == htons(REQ_PTR)) { |
@@ -474,7 +474,7 @@ static int process_packet(struct dns_entry *conf_data, | |||
474 | * RCODE = 0 "success" | 474 | * RCODE = 0 "success" |
475 | */ | 475 | */ |
476 | if (OPT_verbose) | 476 | if (OPT_verbose) |
477 | bb_error_msg("returning positive reply"); | 477 | bb_info_msg("returning positive reply"); |
478 | outr_flags = htons(0x8000 | 0x0400 | 0); | 478 | outr_flags = htons(0x8000 | 0x0400 | 0); |
479 | /* we have one answer */ | 479 | /* we have one answer */ |
480 | head->nansw = htons(1); | 480 | head->nansw = htons(1); |
@@ -539,7 +539,7 @@ int dnsd_main(int argc UNUSED_PARAM, char **argv) | |||
539 | 539 | ||
540 | { | 540 | { |
541 | char *p = xmalloc_sockaddr2dotted(&lsa->u.sa); | 541 | char *p = xmalloc_sockaddr2dotted(&lsa->u.sa); |
542 | bb_error_msg("accepting UDP packets on %s", p); | 542 | bb_info_msg("accepting UDP packets on %s", p); |
543 | free(p); | 543 | free(p); |
544 | } | 544 | } |
545 | 545 | ||
@@ -557,7 +557,7 @@ int dnsd_main(int argc UNUSED_PARAM, char **argv) | |||
557 | continue; | 557 | continue; |
558 | } | 558 | } |
559 | if (OPT_verbose) | 559 | if (OPT_verbose) |
560 | bb_error_msg("got UDP packet"); | 560 | bb_info_msg("got UDP packet"); |
561 | buf[r] = '\0'; /* paranoia */ | 561 | buf[r] = '\0'; /* paranoia */ |
562 | r = process_packet(conf_data, conf_ttl, buf); | 562 | r = process_packet(conf_data, conf_ttl, buf); |
563 | if (r <= 0) | 563 | if (r <= 0) |
diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 026ff1cc8..1426709cb 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c | |||
@@ -326,7 +326,7 @@ static int run_script(const char *action) | |||
326 | char *argv[5]; | 326 | char *argv[5]; |
327 | int r; | 327 | int r; |
328 | 328 | ||
329 | bb_error_msg("executing '%s %s %s'", G.script_name, G.iface, action); | 329 | bb_info_msg("executing '%s %s %s'", G.script_name, G.iface, action); |
330 | 330 | ||
331 | argv[0] = (char*) G.script_name; | 331 | argv[0] = (char*) G.script_name; |
332 | argv[1] = (char*) G.iface; | 332 | argv[1] = (char*) G.iface; |
@@ -345,7 +345,7 @@ static int run_script(const char *action) | |||
345 | bb_unsetenv_and_free(env_PREVIOUS); | 345 | bb_unsetenv_and_free(env_PREVIOUS); |
346 | bb_unsetenv_and_free(env_CURRENT); | 346 | bb_unsetenv_and_free(env_CURRENT); |
347 | 347 | ||
348 | bb_error_msg("exit code: %d", r & 0xff); | 348 | bb_info_msg("exit code: %d", r & 0xff); |
349 | return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r; | 349 | return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r; |
350 | } | 350 | } |
351 | 351 | ||
@@ -365,7 +365,7 @@ static void up_iface(void) | |||
365 | if (!(ifrequest.ifr_flags & IFF_UP)) { | 365 | if (!(ifrequest.ifr_flags & IFF_UP)) { |
366 | ifrequest.ifr_flags |= IFF_UP; | 366 | ifrequest.ifr_flags |= IFF_UP; |
367 | /* Let user know we mess up with interface */ | 367 | /* Let user know we mess up with interface */ |
368 | bb_error_msg("upping interface"); | 368 | bb_info_msg("upping interface"); |
369 | if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "setting interface flags") < 0) { | 369 | if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "setting interface flags") < 0) { |
370 | if (errno != ENODEV && errno != EADDRNOTAVAIL) | 370 | if (errno != ENODEV && errno != EADDRNOTAVAIL) |
371 | xfunc_die(); | 371 | xfunc_die(); |
@@ -414,7 +414,7 @@ static void maybe_up_new_iface(void) | |||
414 | (uint8_t)(ifrequest.ifr_hwaddr.sa_data[5])); | 414 | (uint8_t)(ifrequest.ifr_hwaddr.sa_data[5])); |
415 | } | 415 | } |
416 | 416 | ||
417 | bb_error_msg("using interface %s%s with driver<%s> (version: %s)", | 417 | bb_info_msg("using interface %s%s with driver<%s> (version: %s)", |
418 | G.iface, buf, driver_info.driver, driver_info.version); | 418 | G.iface, buf, driver_info.driver, driver_info.version); |
419 | } | 419 | } |
420 | #endif | 420 | #endif |
@@ -447,7 +447,7 @@ static smallint detect_link(void) | |||
447 | logmode = sv_logmode; | 447 | logmode = sv_logmode; |
448 | if (status != IFSTATUS_ERR) { | 448 | if (status != IFSTATUS_ERR) { |
449 | G.api_method_num = i; | 449 | G.api_method_num = i; |
450 | bb_error_msg("using %s detection mode", method_table[i].name); | 450 | bb_info_msg("using %s detection mode", method_table[i].name); |
451 | break; | 451 | break; |
452 | } | 452 | } |
453 | } | 453 | } |
@@ -632,7 +632,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv) | |||
632 | /* | (1 << SIGCHLD) - run_script does not use it anymore */ | 632 | /* | (1 << SIGCHLD) - run_script does not use it anymore */ |
633 | , record_signo); | 633 | , record_signo); |
634 | 634 | ||
635 | bb_error_msg("started: %s", bb_banner); | 635 | bb_info_msg("started: %s", bb_banner); |
636 | 636 | ||
637 | if (opts & FLAG_MONITOR) { | 637 | if (opts & FLAG_MONITOR) { |
638 | struct ifreq ifrequest; | 638 | struct ifreq ifrequest; |
@@ -649,7 +649,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv) | |||
649 | iface_status_str = strstatus(iface_status); | 649 | iface_status_str = strstatus(iface_status); |
650 | 650 | ||
651 | if (opts & FLAG_MONITOR) { | 651 | if (opts & FLAG_MONITOR) { |
652 | bb_error_msg("interface %s", | 652 | bb_info_msg("interface %s", |
653 | G.iface_exists ? "exists" | 653 | G.iface_exists ? "exists" |
654 | : "doesn't exist, waiting"); | 654 | : "doesn't exist, waiting"); |
655 | } | 655 | } |
@@ -657,7 +657,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv) | |||
657 | * by potentially lying that it really exists */ | 657 | * by potentially lying that it really exists */ |
658 | 658 | ||
659 | if (G.iface_exists) { | 659 | if (G.iface_exists) { |
660 | bb_error_msg("link is %s", iface_status_str); | 660 | bb_info_msg("link is %s", iface_status_str); |
661 | } | 661 | } |
662 | 662 | ||
663 | if ((!(opts & FLAG_NO_STARTUP) | 663 | if ((!(opts & FLAG_NO_STARTUP) |
@@ -712,7 +712,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv) | |||
712 | if (G.iface_exists < 0) /* error */ | 712 | if (G.iface_exists < 0) /* error */ |
713 | goto exiting; | 713 | goto exiting; |
714 | if (iface_exists_old != G.iface_exists) { | 714 | if (iface_exists_old != G.iface_exists) { |
715 | bb_error_msg("interface %sappeared", | 715 | bb_info_msg("interface %sappeared", |
716 | G.iface_exists ? "" : "dis"); | 716 | G.iface_exists ? "" : "dis"); |
717 | if (G.iface_exists) | 717 | if (G.iface_exists) |
718 | maybe_up_new_iface(); | 718 | maybe_up_new_iface(); |
@@ -730,7 +730,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv) | |||
730 | iface_status_str = strstatus(iface_status); | 730 | iface_status_str = strstatus(iface_status); |
731 | 731 | ||
732 | if (iface_status_old != iface_status) { | 732 | if (iface_status_old != iface_status) { |
733 | bb_error_msg("link is %s", iface_status_str); | 733 | bb_info_msg("link is %s", iface_status_str); |
734 | 734 | ||
735 | if (delay_time) { | 735 | if (delay_time) { |
736 | /* link restored its old status before | 736 | /* link restored its old status before |
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 8a6efc976..5327b0979 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
@@ -1177,8 +1177,15 @@ static int doit(char *str) | |||
1177 | 1177 | ||
1178 | static int execute_all(struct interface_defn_t *ifd, const char *opt) | 1178 | static int execute_all(struct interface_defn_t *ifd, const char *opt) |
1179 | { | 1179 | { |
1180 | /* 'opt' is always short, the longest value is "post-down". | ||
1181 | * Can use on-stack buffer instead of xasprintf'ed one. | ||
1182 | */ | ||
1183 | char buf[sizeof("run-parts /etc/network/if-%s.d") | ||
1184 | + sizeof("post-down") | ||
1185 | /*paranoia:*/ + 8 | ||
1186 | ]; | ||
1180 | int i; | 1187 | int i; |
1181 | char *buf; | 1188 | |
1182 | for (i = 0; i < ifd->n_options; i++) { | 1189 | for (i = 0; i < ifd->n_options; i++) { |
1183 | if (strcmp(ifd->option[i].name, opt) == 0) { | 1190 | if (strcmp(ifd->option[i].name, opt) == 0) { |
1184 | if (!doit(ifd->option[i].value)) { | 1191 | if (!doit(ifd->option[i].value)) { |
@@ -1192,8 +1199,7 @@ static int execute_all(struct interface_defn_t *ifd, const char *opt) | |||
1192 | * complains, and this message _is_ annoyingly visible. | 1199 | * complains, and this message _is_ annoyingly visible. |
1193 | * Don't "fix" this (unless newer Debian does). | 1200 | * Don't "fix" this (unless newer Debian does). |
1194 | */ | 1201 | */ |
1195 | buf = xasprintf("run-parts /etc/network/if-%s.d", opt); | 1202 | sprintf(buf, "run-parts /etc/network/if-%s.d", opt); |
1196 | /* heh, we don't bother free'ing it */ | ||
1197 | return doit(buf); | 1203 | return doit(buf); |
1198 | } | 1204 | } |
1199 | 1205 | ||
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index 8364f6a3e..7b7e0154b 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | struct filter_t { | 24 | struct filter_t { |
25 | char *label; | 25 | char *label; |
26 | /* Flush cmd buf. If !NULL, print_addrinfo() constructs flush commands in it */ | ||
26 | char *flushb; | 27 | char *flushb; |
27 | struct rtnl_handle *rth; | 28 | struct rtnl_handle *rth; |
28 | int scope, scopemask; | 29 | int scope, scopemask; |
@@ -34,6 +35,8 @@ struct filter_t { | |||
34 | smallint showqueue; | 35 | smallint showqueue; |
35 | smallint oneline; | 36 | smallint oneline; |
36 | smallint up; | 37 | smallint up; |
38 | /* Misnomer. Does not mean "flushed something" */ | ||
39 | /* More like "flush commands were constructed by print_addrinfo()" */ | ||
37 | smallint flushed; | 40 | smallint flushed; |
38 | inet_prefix pfx; | 41 | inet_prefix pfx; |
39 | } FIX_ALIASING; | 42 | } FIX_ALIASING; |
@@ -201,7 +204,7 @@ static NOINLINE int print_linkinfo(const struct nlmsghdr *n) | |||
201 | 204 | ||
202 | static int flush_update(void) | 205 | static int flush_update(void) |
203 | { | 206 | { |
204 | if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { | 207 | if (rtnl_send_check(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { |
205 | bb_perror_msg("can't send flush request"); | 208 | bb_perror_msg("can't send flush request"); |
206 | return -1; | 209 | return -1; |
207 | } | 210 | } |
@@ -510,7 +513,6 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush) | |||
510 | xrtnl_dump_filter(&rth, store_nlmsg, &ainfo); | 513 | xrtnl_dump_filter(&rth, store_nlmsg, &ainfo); |
511 | } | 514 | } |
512 | 515 | ||
513 | |||
514 | if (G_filter.family && G_filter.family != AF_PACKET) { | 516 | if (G_filter.family && G_filter.family != AF_PACKET) { |
515 | struct nlmsg_list **lp; | 517 | struct nlmsg_list **lp; |
516 | lp = &linfo; | 518 | lp = &linfo; |
@@ -571,8 +573,8 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush) | |||
571 | 573 | ||
572 | for (l = linfo; l; l = l->next) { | 574 | for (l = linfo; l; l = l->next) { |
573 | if ((oneline && G_filter.family != AF_PACKET) | 575 | if ((oneline && G_filter.family != AF_PACKET) |
574 | || (print_linkinfo(&l->h) == 0) | ||
575 | /* ^^^^^^^^^ "ip -oneline a" does not print link info */ | 576 | /* ^^^^^^^^^ "ip -oneline a" does not print link info */ |
577 | || (print_linkinfo(&l->h) == 0) | ||
576 | ) { | 578 | ) { |
577 | struct ifinfomsg *ifi = NLMSG_DATA(&l->h); | 579 | struct ifinfomsg *ifi = NLMSG_DATA(&l->h); |
578 | if (G_filter.family != AF_PACKET) | 580 | if (G_filter.family != AF_PACKET) |
diff --git a/networking/libiproute/ipneigh.c b/networking/libiproute/ipneigh.c index f572414e9..984dd4bdd 100644 --- a/networking/libiproute/ipneigh.c +++ b/networking/libiproute/ipneigh.c | |||
@@ -32,7 +32,10 @@ struct filter_t { | |||
32 | int state; | 32 | int state; |
33 | int unused_only; | 33 | int unused_only; |
34 | inet_prefix pfx; | 34 | inet_prefix pfx; |
35 | /* Misnomer. Does not mean "flushed N something" */ | ||
36 | /* More like "no_of_flush_commands_constructed_by_print_neigh()" */ | ||
35 | int flushed; | 37 | int flushed; |
38 | /* Flush cmd buf. If !NULL, print_neigh() constructs flush commands in it */ | ||
36 | char *flushb; | 39 | char *flushb; |
37 | int flushp; | 40 | int flushp; |
38 | int flushe; | 41 | int flushe; |
@@ -45,7 +48,7 @@ typedef struct filter_t filter_t; | |||
45 | 48 | ||
46 | static int flush_update(void) | 49 | static int flush_update(void) |
47 | { | 50 | { |
48 | if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { | 51 | if (rtnl_send_check(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { |
49 | bb_perror_msg("can't send flush request"); | 52 | bb_perror_msg("can't send flush request"); |
50 | return -1; | 53 | return -1; |
51 | } | 54 | } |
@@ -299,9 +302,7 @@ static int FAST_FUNC ipneigh_list_or_flush(char **argv, int flush) | |||
299 | G_filter.rth = &rth; | 302 | G_filter.rth = &rth; |
300 | 303 | ||
301 | while (round < MAX_ROUNDS) { | 304 | while (round < MAX_ROUNDS) { |
302 | if (xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETNEIGH) < 0) { | 305 | xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETNEIGH); |
303 | bb_perror_msg_and_die("can't send dump request"); | ||
304 | } | ||
305 | G_filter.flushed = 0; | 306 | G_filter.flushed = 0; |
306 | if (xrtnl_dump_filter(&rth, print_neigh, NULL) < 0) { | 307 | if (xrtnl_dump_filter(&rth, print_neigh, NULL) < 0) { |
307 | bb_perror_msg_and_die("flush terminated"); | 308 | bb_perror_msg_and_die("flush terminated"); |
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index 2a8610ea6..b11078ed5 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c | |||
@@ -26,7 +26,10 @@ | |||
26 | 26 | ||
27 | struct filter_t { | 27 | struct filter_t { |
28 | int tb; | 28 | int tb; |
29 | /* Misnomer. Does not mean "flushed something" */ | ||
30 | /* More like "flush commands were constructed by print_route()" */ | ||
29 | smallint flushed; | 31 | smallint flushed; |
32 | /* Flush cmd buf. If !NULL, print_route() constructs flush commands in it */ | ||
30 | char *flushb; | 33 | char *flushb; |
31 | int flushp; | 34 | int flushp; |
32 | int flushe; | 35 | int flushe; |
@@ -53,7 +56,7 @@ typedef struct filter_t filter_t; | |||
53 | 56 | ||
54 | static int flush_update(void) | 57 | static int flush_update(void) |
55 | { | 58 | { |
56 | if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { | 59 | if (rtnl_send_check(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { |
57 | bb_perror_msg("can't send flush request"); | 60 | bb_perror_msg("can't send flush request"); |
58 | return -1; | 61 | return -1; |
59 | } | 62 | } |
diff --git a/networking/libiproute/libnetlink.c b/networking/libiproute/libnetlink.c index 40955fcae..b0d4166ac 100644 --- a/networking/libiproute/libnetlink.c +++ b/networking/libiproute/libnetlink.c | |||
@@ -34,7 +34,7 @@ void FAST_FUNC xrtnl_open(struct rtnl_handle *rth/*, unsigned subscriptions*/) | |||
34 | rth->seq = time(NULL); | 34 | rth->seq = time(NULL); |
35 | } | 35 | } |
36 | 36 | ||
37 | int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) | 37 | void FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) |
38 | { | 38 | { |
39 | struct { | 39 | struct { |
40 | struct nlmsghdr nlh; | 40 | struct nlmsghdr nlh; |
@@ -48,18 +48,45 @@ int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int ty | |||
48 | req.nlh.nlmsg_seq = rth->dump = ++rth->seq; | 48 | req.nlh.nlmsg_seq = rth->dump = ++rth->seq; |
49 | req.g.rtgen_family = family; | 49 | req.g.rtgen_family = family; |
50 | 50 | ||
51 | return rtnl_send(rth, (void*)&req, sizeof(req)); | 51 | rtnl_send(rth, (void*)&req, sizeof(req)); |
52 | } | 52 | } |
53 | 53 | ||
54 | //TODO: pass rth->fd instead of full rth? | 54 | /* A version which checks for e.g. EPERM errors. |
55 | int FAST_FUNC rtnl_send(struct rtnl_handle *rth, char *buf, int len) | 55 | * Try: setuidgid 1:1 ip addr flush dev eth0 |
56 | */ | ||
57 | int FAST_FUNC rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len) | ||
56 | { | 58 | { |
57 | struct sockaddr_nl nladdr; | 59 | struct nlmsghdr *h; |
60 | int status; | ||
61 | char resp[1024]; | ||
58 | 62 | ||
59 | memset(&nladdr, 0, sizeof(nladdr)); | 63 | status = write(rth->fd, buf, len); |
60 | nladdr.nl_family = AF_NETLINK; | 64 | if (status < 0) |
65 | return status; | ||
66 | |||
67 | /* Check for immediate errors */ | ||
68 | status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK); | ||
69 | if (status < 0) { | ||
70 | if (errno == EAGAIN) /* if no error, this happens */ | ||
71 | return 0; | ||
72 | return -1; | ||
73 | } | ||
61 | 74 | ||
62 | return xsendto(rth->fd, buf, len, (struct sockaddr*)&nladdr, sizeof(nladdr)); | 75 | for (h = (struct nlmsghdr *)resp; |
76 | NLMSG_OK(h, status); | ||
77 | h = NLMSG_NEXT(h, status) | ||
78 | ) { | ||
79 | if (h->nlmsg_type == NLMSG_ERROR) { | ||
80 | struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); | ||
81 | if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) | ||
82 | bb_error_msg("ERROR truncated"); | ||
83 | else | ||
84 | errno = -err->error; | ||
85 | return -1; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | return 0; | ||
63 | } | 90 | } |
64 | 91 | ||
65 | int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) | 92 | int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) |
diff --git a/networking/libiproute/libnetlink.h b/networking/libiproute/libnetlink.h index 51bee2d67..1b082e019 100644 --- a/networking/libiproute/libnetlink.h +++ b/networking/libiproute/libnetlink.h | |||
@@ -20,7 +20,7 @@ struct rtnl_handle { | |||
20 | 20 | ||
21 | extern void xrtnl_open(struct rtnl_handle *rth) FAST_FUNC; | 21 | extern void xrtnl_open(struct rtnl_handle *rth) FAST_FUNC; |
22 | #define rtnl_close(rth) (close((rth)->fd)) | 22 | #define rtnl_close(rth) (close((rth)->fd)) |
23 | extern int xrtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type) FAST_FUNC; | 23 | extern void xrtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type) FAST_FUNC; |
24 | extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) FAST_FUNC; | 24 | extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) FAST_FUNC; |
25 | extern int xrtnl_dump_filter(struct rtnl_handle *rth, | 25 | extern int xrtnl_dump_filter(struct rtnl_handle *rth, |
26 | int (*filter)(const struct sockaddr_nl*, struct nlmsghdr *n, void*) FAST_FUNC, | 26 | int (*filter)(const struct sockaddr_nl*, struct nlmsghdr *n, void*) FAST_FUNC, |
@@ -34,8 +34,23 @@ extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, | |||
34 | int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *), | 34 | int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *), |
35 | void *jarg) FAST_FUNC; | 35 | void *jarg) FAST_FUNC; |
36 | 36 | ||
37 | extern int rtnl_send(struct rtnl_handle *rth, char *buf, int) FAST_FUNC; | 37 | int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len) FAST_FUNC; |
38 | //TODO: pass rth->fd instead of full rth? | ||
39 | static ALWAYS_INLINE void rtnl_send(struct rtnl_handle *rth, const void *buf, int len) | ||
40 | { | ||
41 | // Used to be: | ||
42 | //struct sockaddr_nl nladdr; | ||
43 | //memset(&nladdr, 0, sizeof(nladdr)); | ||
44 | //nladdr.nl_family = AF_NETLINK; | ||
45 | //return xsendto(rth->fd, buf, len, (struct sockaddr*)&nladdr, sizeof(nladdr)); | ||
38 | 46 | ||
47 | // iproute2-4.2.0 simplified the above to: | ||
48 | //return send(rth->fd, buf, len, 0); | ||
49 | |||
50 | // We are using even shorter: | ||
51 | xwrite(rth->fd, buf, len); | ||
52 | // and convert to void, inline. | ||
53 | } | ||
39 | 54 | ||
40 | extern int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data) FAST_FUNC; | 55 | extern int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data) FAST_FUNC; |
41 | extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) FAST_FUNC; | 56 | extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) FAST_FUNC; |
diff --git a/networking/libiproute/ll_proto.c b/networking/libiproute/ll_proto.c index 7d46221ac..611e0a2c9 100644 --- a/networking/libiproute/ll_proto.c +++ b/networking/libiproute/ll_proto.c | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | /* Please conditionalize exotic protocols on CONFIG_something */ | 16 | /* Please conditionalize exotic protocols on CONFIG_something */ |
17 | 17 | ||
18 | static const uint16_t llproto_ids[] = { | 18 | static const uint16_t llproto_ids[] ALIGN2 = { |
19 | #define __PF(f,n) ETH_P_##f, | 19 | #define __PF(f,n) ETH_P_##f, |
20 | __PF(LOOP,loop) | 20 | __PF(LOOP,loop) |
21 | __PF(PUP,pup) | 21 | __PF(PUP,pup) |
diff --git a/networking/ntpd.c b/networking/ntpd.c index 027cfe783..cd6da2b38 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -1130,7 +1130,7 @@ step_time(double offset) | |||
1130 | } | 1130 | } |
1131 | tval = tvn.tv_sec; | 1131 | tval = tvn.tv_sec; |
1132 | strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval); | 1132 | strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval); |
1133 | bb_error_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset); | 1133 | bb_info_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset); |
1134 | //maybe? G.FREQHOLD_cnt = 0; | 1134 | //maybe? G.FREQHOLD_cnt = 0; |
1135 | 1135 | ||
1136 | /* Correct various fields which contain time-relative values: */ | 1136 | /* Correct various fields which contain time-relative values: */ |
@@ -2132,7 +2132,7 @@ recv_and_process_peer_pkt(peer_t *p) | |||
2132 | 2132 | ||
2133 | p->reachable_bits |= 1; | 2133 | p->reachable_bits |= 1; |
2134 | if ((MAX_VERBOSE && G.verbose) || (option_mask32 & OPT_w)) { | 2134 | if ((MAX_VERBOSE && G.verbose) || (option_mask32 & OPT_w)) { |
2135 | bb_error_msg("reply from %s: offset:%+f delay:%f status:0x%02x strat:%d refid:0x%08x rootdelay:%f reach:0x%02x", | 2135 | bb_info_msg("reply from %s: offset:%+f delay:%f status:0x%02x strat:%d refid:0x%08x rootdelay:%f reach:0x%02x", |
2136 | p->p_dotted, | 2136 | p->p_dotted, |
2137 | offset, | 2137 | offset, |
2138 | p->p_raw_delay, | 2138 | p->p_raw_delay, |
diff --git a/networking/tc.c b/networking/tc.c index 3e9808328..2e1078d31 100644 --- a/networking/tc.c +++ b/networking/tc.c | |||
@@ -124,7 +124,8 @@ static char* print_tc_classid(uint32_t cid) | |||
124 | } | 124 | } |
125 | 125 | ||
126 | /* Get a qdisc handle. Return 0 on success, !0 otherwise. */ | 126 | /* Get a qdisc handle. Return 0 on success, !0 otherwise. */ |
127 | static int get_qdisc_handle(uint32_t *h, const char *str) { | 127 | static int get_qdisc_handle(uint32_t *h, const char *str) |
128 | { | ||
128 | uint32_t maj; | 129 | uint32_t maj; |
129 | char *p; | 130 | char *p; |
130 | 131 | ||
@@ -143,7 +144,8 @@ static int get_qdisc_handle(uint32_t *h, const char *str) { | |||
143 | } | 144 | } |
144 | 145 | ||
145 | /* Get class ID. Return 0 on success, !0 otherwise. */ | 146 | /* Get class ID. Return 0 on success, !0 otherwise. */ |
146 | static int get_tc_classid(uint32_t *h, const char *str) { | 147 | static int get_tc_classid(uint32_t *h, const char *str) |
148 | { | ||
147 | uint32_t maj, min; | 149 | uint32_t maj, min; |
148 | char *p; | 150 | char *p; |
149 | 151 | ||
diff --git a/networking/tftp.c b/networking/tftp.c index d20d4ca4b..5ebd22105 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
@@ -245,7 +245,7 @@ static int tftp_blksize_check(const char *blksize_str, int maxsize) | |||
245 | return -1; | 245 | return -1; |
246 | } | 246 | } |
247 | # if ENABLE_TFTP_DEBUG | 247 | # if ENABLE_TFTP_DEBUG |
248 | bb_error_msg("using blksize %u", blksize); | 248 | bb_info_msg("using blksize %u", blksize); |
249 | # endif | 249 | # endif |
250 | return blksize; | 250 | return blksize; |
251 | } | 251 | } |
diff --git a/networking/tls.c b/networking/tls.c index d2385efe8..d1a0204ed 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -1393,12 +1393,12 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) | |||
1393 | /* enter subjectPublicKeyInfo */ | 1393 | /* enter subjectPublicKeyInfo */ |
1394 | der = enter_der_item(der, &end); | 1394 | der = enter_der_item(der, &end); |
1395 | { /* check subjectPublicKeyInfo.algorithm */ | 1395 | { /* check subjectPublicKeyInfo.algorithm */ |
1396 | static const uint8_t OID_RSA_KEY_ALG[] = { | 1396 | static const uint8_t OID_RSA_KEY_ALG[] ALIGN1 = { |
1397 | 0x30,0x0d, // SEQ 13 bytes | 1397 | 0x30,0x0d, // SEQ 13 bytes |
1398 | 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, //OID_RSA_KEY_ALG 42.134.72.134.247.13.1.1.1 | 1398 | 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, //OID_RSA_KEY_ALG 42.134.72.134.247.13.1.1.1 |
1399 | //0x05,0x00, // NULL | 1399 | //0x05,0x00, // NULL |
1400 | }; | 1400 | }; |
1401 | static const uint8_t OID_ECDSA_KEY_ALG[] = { | 1401 | static const uint8_t OID_ECDSA_KEY_ALG[] ALIGN1 = { |
1402 | 0x30,0x13, // SEQ 0x13 bytes | 1402 | 0x30,0x13, // SEQ 0x13 bytes |
1403 | 0x06,0x07, 0x2a,0x86,0x48,0xce,0x3d,0x02,0x01, //OID_ECDSA_KEY_ALG 42.134.72.206.61.2.1 | 1403 | 0x06,0x07, 0x2a,0x86,0x48,0xce,0x3d,0x02,0x01, //OID_ECDSA_KEY_ALG 42.134.72.206.61.2.1 |
1404 | //allow any curve code for now... | 1404 | //allow any curve code for now... |
@@ -2089,7 +2089,7 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
2089 | } | 2089 | } |
2090 | } | 2090 | } |
2091 | 2091 | ||
2092 | static const uint8_t rec_CHANGE_CIPHER_SPEC[] = { | 2092 | static const uint8_t rec_CHANGE_CIPHER_SPEC[] ALIGN1 = { |
2093 | RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01, | 2093 | RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01, |
2094 | 01 | 2094 | 01 |
2095 | }; | 2095 | }; |
diff --git a/networking/tls_aes.c b/networking/tls_aes.c index cf6b5fe3d..5400ad9b5 100644 --- a/networking/tls_aes.c +++ b/networking/tls_aes.c | |||
@@ -130,7 +130,7 @@ static int KeyExpansion(uint32_t *RoundKey, const void *key, unsigned key_len) | |||
130 | // The round constant word array, Rcon[i], contains the values given by | 130 | // The round constant word array, Rcon[i], contains the values given by |
131 | // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8). | 131 | // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8). |
132 | // Note that i starts at 2, not 0. | 132 | // Note that i starts at 2, not 0. |
133 | static const uint8_t Rcon[] = { | 133 | static const uint8_t Rcon[] ALIGN1 = { |
134 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 | 134 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 |
135 | //..... 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6,... | 135 | //..... 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6,... |
136 | // but aes256 only uses values up to 0x36 | 136 | // but aes256 only uses values up to 0x36 |
diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c index d46e2aa2b..20f9c26d5 100644 --- a/networking/tls_pstm_montgomery_reduce.c +++ b/networking/tls_pstm_montgomery_reduce.c | |||
@@ -73,7 +73,7 @@ asm( \ | |||
73 | "movl %%edx,%1 \n\t" \ | 73 | "movl %%edx,%1 \n\t" \ |
74 | :"=g"(_c[LO]), "=r"(cy) \ | 74 | :"=g"(_c[LO]), "=r"(cy) \ |
75 | :"0"(_c[LO]), "1"(cy), "g"(mu), "g"(*tmpm++) \ | 75 | :"0"(_c[LO]), "1"(cy), "g"(mu), "g"(*tmpm++) \ |
76 | : "%eax", "%edx", "%cc") | 76 | : "%eax", "%edx", "cc") |
77 | 77 | ||
78 | #define PROPCARRY \ | 78 | #define PROPCARRY \ |
79 | asm( \ | 79 | asm( \ |
@@ -82,7 +82,7 @@ asm( \ | |||
82 | "movzbl %%al,%1 \n\t" \ | 82 | "movzbl %%al,%1 \n\t" \ |
83 | :"=g"(_c[LO]), "=r"(cy) \ | 83 | :"=g"(_c[LO]), "=r"(cy) \ |
84 | :"0"(_c[LO]), "1"(cy) \ | 84 | :"0"(_c[LO]), "1"(cy) \ |
85 | : "%eax", "%cc") | 85 | : "%eax", "cc") |
86 | 86 | ||
87 | /******************************************************************************/ | 87 | /******************************************************************************/ |
88 | #elif defined(PSTM_X86_64) | 88 | #elif defined(PSTM_X86_64) |
@@ -235,7 +235,7 @@ asm( \ | |||
235 | " STR r0,%1 \n\t" \ | 235 | " STR r0,%1 \n\t" \ |
236 | :"=r"(cy),"=m"(_c[0])\ | 236 | :"=r"(cy),"=m"(_c[0])\ |
237 | :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\ | 237 | :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\ |
238 | :"r0","%cc"); | 238 | :"r0","cc"); |
239 | #define PROPCARRY \ | 239 | #define PROPCARRY \ |
240 | asm( \ | 240 | asm( \ |
241 | " LDR r0,%1 \n\t" \ | 241 | " LDR r0,%1 \n\t" \ |
@@ -246,7 +246,7 @@ asm( \ | |||
246 | " MOVCC %0,#0 \n\t" \ | 246 | " MOVCC %0,#0 \n\t" \ |
247 | :"=r"(cy),"=m"(_c[0])\ | 247 | :"=r"(cy),"=m"(_c[0])\ |
248 | :"0"(cy),"m"(_c[0])\ | 248 | :"0"(cy),"m"(_c[0])\ |
249 | :"r0","%cc"); | 249 | :"r0","cc"); |
250 | #else /* Non-Thumb2 code */ | 250 | #else /* Non-Thumb2 code */ |
251 | //#pragma message ("Using 32 bit ARM Assembly Optimizations") | 251 | //#pragma message ("Using 32 bit ARM Assembly Optimizations") |
252 | #define INNERMUL \ | 252 | #define INNERMUL \ |
@@ -259,7 +259,7 @@ asm( \ | |||
259 | " STR r0,%1 \n\t" \ | 259 | " STR r0,%1 \n\t" \ |
260 | :"=r"(cy),"=m"(_c[0])\ | 260 | :"=r"(cy),"=m"(_c[0])\ |
261 | :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\ | 261 | :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\ |
262 | :"r0","%cc"); | 262 | :"r0","cc"); |
263 | #define PROPCARRY \ | 263 | #define PROPCARRY \ |
264 | asm( \ | 264 | asm( \ |
265 | " LDR r0,%1 \n\t" \ | 265 | " LDR r0,%1 \n\t" \ |
@@ -269,7 +269,7 @@ asm( \ | |||
269 | " MOVCC %0,#0 \n\t" \ | 269 | " MOVCC %0,#0 \n\t" \ |
270 | :"=r"(cy),"=m"(_c[0])\ | 270 | :"=r"(cy),"=m"(_c[0])\ |
271 | :"0"(cy),"m"(_c[0])\ | 271 | :"0"(cy),"m"(_c[0])\ |
272 | :"r0","%cc"); | 272 | :"r0","cc"); |
273 | #endif /* __thumb2__ */ | 273 | #endif /* __thumb2__ */ |
274 | 274 | ||
275 | 275 | ||
diff --git a/networking/tls_pstm_mul_comba.c b/networking/tls_pstm_mul_comba.c index ac4fcc3ef..af50358e5 100644 --- a/networking/tls_pstm_mul_comba.c +++ b/networking/tls_pstm_mul_comba.c | |||
@@ -85,7 +85,7 @@ asm( \ | |||
85 | "addl %%eax,%0 \n\t" \ | 85 | "addl %%eax,%0 \n\t" \ |
86 | "adcl %%edx,%1 \n\t" \ | 86 | "adcl %%edx,%1 \n\t" \ |
87 | "adcl $0,%2 \n\t" \ | 87 | "adcl $0,%2 \n\t" \ |
88 | :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc"); | 88 | :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","cc"); |
89 | //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build | 89 | //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build |
90 | 90 | ||
91 | /******************************************************************************/ | 91 | /******************************************************************************/ |
@@ -155,7 +155,7 @@ asm( \ | |||
155 | " ADDS %0,%0,r0 \n\t" \ | 155 | " ADDS %0,%0,r0 \n\t" \ |
156 | " ADCS %1,%1,r1 \n\t" \ | 156 | " ADCS %1,%1,r1 \n\t" \ |
157 | " ADC %2,%2,#0 \n\t" \ | 157 | " ADC %2,%2,#0 \n\t" \ |
158 | :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc"); | 158 | :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc"); |
159 | 159 | ||
160 | /******************************************************************************/ | 160 | /******************************************************************************/ |
161 | #elif defined(PSTM_MIPS) | 161 | #elif defined(PSTM_MIPS) |
diff --git a/networking/tls_pstm_sqr_comba.c b/networking/tls_pstm_sqr_comba.c index 8604132d6..a4d421b89 100644 --- a/networking/tls_pstm_sqr_comba.c +++ b/networking/tls_pstm_sqr_comba.c | |||
@@ -78,7 +78,7 @@ asm( \ | |||
78 | "addl %%eax,%0 \n\t" \ | 78 | "addl %%eax,%0 \n\t" \ |
79 | "adcl %%edx,%1 \n\t" \ | 79 | "adcl %%edx,%1 \n\t" \ |
80 | "adcl $0,%2 \n\t" \ | 80 | "adcl $0,%2 \n\t" \ |
81 | :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","%cc"); | 81 | :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","cc"); |
82 | //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build | 82 | //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build |
83 | 83 | ||
84 | #define SQRADD2(i, j) \ | 84 | #define SQRADD2(i, j) \ |
@@ -91,7 +91,7 @@ asm( \ | |||
91 | "addl %%eax,%0 \n\t" \ | 91 | "addl %%eax,%0 \n\t" \ |
92 | "adcl %%edx,%1 \n\t" \ | 92 | "adcl %%edx,%1 \n\t" \ |
93 | "adcl $0,%2 \n\t" \ | 93 | "adcl $0,%2 \n\t" \ |
94 | :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc"); | 94 | :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","cc"); |
95 | //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build | 95 | //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build |
96 | 96 | ||
97 | #define SQRADDSC(i, j) \ | 97 | #define SQRADDSC(i, j) \ |
@@ -101,7 +101,7 @@ asm( \ | |||
101 | "movl %%eax,%0 \n\t" \ | 101 | "movl %%eax,%0 \n\t" \ |
102 | "movl %%edx,%1 \n\t" \ | 102 | "movl %%edx,%1 \n\t" \ |
103 | "xorl %2,%2 \n\t" \ | 103 | "xorl %2,%2 \n\t" \ |
104 | :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc"); | 104 | :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","cc"); |
105 | 105 | ||
106 | #define SQRADDAC(i, j) \ | 106 | #define SQRADDAC(i, j) \ |
107 | asm( \ | 107 | asm( \ |
@@ -110,7 +110,7 @@ asm( \ | |||
110 | "addl %%eax,%0 \n\t" \ | 110 | "addl %%eax,%0 \n\t" \ |
111 | "adcl %%edx,%1 \n\t" \ | 111 | "adcl %%edx,%1 \n\t" \ |
112 | "adcl $0,%2 \n\t" \ | 112 | "adcl $0,%2 \n\t" \ |
113 | :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc"); | 113 | :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","cc"); |
114 | 114 | ||
115 | #define SQRADDDB \ | 115 | #define SQRADDDB \ |
116 | asm( \ | 116 | asm( \ |
@@ -120,7 +120,7 @@ asm( \ | |||
120 | "addl %6,%0 \n\t" \ | 120 | "addl %6,%0 \n\t" \ |
121 | "adcl %7,%1 \n\t" \ | 121 | "adcl %7,%1 \n\t" \ |
122 | "adcl %8,%2 \n\t" \ | 122 | "adcl %8,%2 \n\t" \ |
123 | :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "%cc"); | 123 | :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc"); |
124 | 124 | ||
125 | /******************************************************************************/ | 125 | /******************************************************************************/ |
126 | #elif defined(PSTM_X86_64) | 126 | #elif defined(PSTM_X86_64) |
@@ -223,7 +223,7 @@ asm( \ | |||
223 | " ADDS %0,%0,r0 \n\t" \ | 223 | " ADDS %0,%0,r0 \n\t" \ |
224 | " ADCS %1,%1,r1 \n\t" \ | 224 | " ADCS %1,%1,r1 \n\t" \ |
225 | " ADC %2,%2,#0 \n\t" \ | 225 | " ADC %2,%2,#0 \n\t" \ |
226 | :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "%cc"); | 226 | :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "cc"); |
227 | 227 | ||
228 | /* for squaring some of the terms are doubled... */ | 228 | /* for squaring some of the terms are doubled... */ |
229 | #define SQRADD2(i, j) \ | 229 | #define SQRADD2(i, j) \ |
@@ -235,13 +235,13 @@ asm( \ | |||
235 | " ADDS %0,%0,r0 \n\t" \ | 235 | " ADDS %0,%0,r0 \n\t" \ |
236 | " ADCS %1,%1,r1 \n\t" \ | 236 | " ADCS %1,%1,r1 \n\t" \ |
237 | " ADC %2,%2,#0 \n\t" \ | 237 | " ADC %2,%2,#0 \n\t" \ |
238 | :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc"); | 238 | :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc"); |
239 | 239 | ||
240 | #define SQRADDSC(i, j) \ | 240 | #define SQRADDSC(i, j) \ |
241 | asm( \ | 241 | asm( \ |
242 | " UMULL %0,%1,%6,%7 \n\t" \ | 242 | " UMULL %0,%1,%6,%7 \n\t" \ |
243 | " SUB %2,%2,%2 \n\t" \ | 243 | " SUB %2,%2,%2 \n\t" \ |
244 | :"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "%cc"); | 244 | :"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "cc"); |
245 | 245 | ||
246 | #define SQRADDAC(i, j) \ | 246 | #define SQRADDAC(i, j) \ |
247 | asm( \ | 247 | asm( \ |
@@ -249,7 +249,7 @@ asm( \ | |||
249 | " ADDS %0,%0,r0 \n\t" \ | 249 | " ADDS %0,%0,r0 \n\t" \ |
250 | " ADCS %1,%1,r1 \n\t" \ | 250 | " ADCS %1,%1,r1 \n\t" \ |
251 | " ADC %2,%2,#0 \n\t" \ | 251 | " ADC %2,%2,#0 \n\t" \ |
252 | :"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "%cc"); | 252 | :"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "cc"); |
253 | 253 | ||
254 | #define SQRADDDB \ | 254 | #define SQRADDDB \ |
255 | asm( \ | 255 | asm( \ |
@@ -259,7 +259,7 @@ asm( \ | |||
259 | " ADDS %0,%0,%3 \n\t" \ | 259 | " ADDS %0,%0,%3 \n\t" \ |
260 | " ADCS %1,%1,%4 \n\t" \ | 260 | " ADCS %1,%1,%4 \n\t" \ |
261 | " ADC %2,%2,%5 \n\t" \ | 261 | " ADC %2,%2,%5 \n\t" \ |
262 | :"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "%cc"); | 262 | :"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc"); |
263 | 263 | ||
264 | /******************************************************************************/ | 264 | /******************************************************************************/ |
265 | #elif defined(PSTM_MIPS) | 265 | #elif defined(PSTM_MIPS) |
@@ -330,7 +330,7 @@ asm( \ | |||
330 | " mflo %0 \n\t" \ | 330 | " mflo %0 \n\t" \ |
331 | " mfhi %1 \n\t" \ | 331 | " mfhi %1 \n\t" \ |
332 | " xor %2,%2,%2 \n\t" \ | 332 | " xor %2,%2,%2 \n\t" \ |
333 | :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "%cc"); | 333 | :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc"); |
334 | 334 | ||
335 | #define SQRADDAC(i, j) \ | 335 | #define SQRADDAC(i, j) \ |
336 | asm( \ | 336 | asm( \ |
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 59cf723ee..62ad248ce 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -191,7 +191,7 @@ static void log_option(const char *pfx, const uint8_t *opt) | |||
191 | if (dhcp_verbose >= 2) { | 191 | if (dhcp_verbose >= 2) { |
192 | char buf[256 * 2 + 2]; | 192 | char buf[256 * 2 + 2]; |
193 | *bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0'; | 193 | *bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0'; |
194 | bb_error_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf); | 194 | bb_info_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf); |
195 | } | 195 | } |
196 | } | 196 | } |
197 | #else | 197 | #else |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 9d1f71aae..bba3d6037 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -40,7 +40,7 @@ struct dhcp_packet { | |||
40 | uint32_t yiaddr; /* 'your' (client) IP address */ | 40 | uint32_t yiaddr; /* 'your' (client) IP address */ |
41 | /* IP address of next server to use in bootstrap, returned in DHCPOFFER, DHCPACK by server */ | 41 | /* IP address of next server to use in bootstrap, returned in DHCPOFFER, DHCPACK by server */ |
42 | uint32_t siaddr_nip; | 42 | uint32_t siaddr_nip; |
43 | uint32_t gateway_nip; /* relay agent IP address */ | 43 | uint32_t gateway_nip; /* aka 'giaddr': relay agent IP address */ |
44 | uint8_t chaddr[16]; /* link-layer client hardware address (MAC) */ | 44 | uint8_t chaddr[16]; /* link-layer client hardware address (MAC) */ |
45 | uint8_t sname[64]; /* server host name (ASCIZ) */ | 45 | uint8_t sname[64]; /* server host name (ASCIZ) */ |
46 | uint8_t file[128]; /* boot file name (ASCIZ) */ | 46 | uint8_t file[128]; /* boot file name (ASCIZ) */ |
@@ -222,10 +222,9 @@ uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) | |||
222 | #endif | 222 | #endif |
223 | struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; | 223 | struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; |
224 | 224 | ||
225 | |||
226 | // RFC 2131 Table 5: Fields and options used by DHCP clients | 225 | // RFC 2131 Table 5: Fields and options used by DHCP clients |
227 | // | 226 | // |
228 | // Fields 'hops', 'yiaddr', 'siaddr', 'giaddr' are always zero | 227 | // Fields 'hops', 'yiaddr', 'siaddr', 'giaddr' are always zero, 'chaddr' is always client's MAC |
229 | // | 228 | // |
230 | // Field DHCPDISCOVER DHCPINFORM DHCPREQUEST DHCPDECLINE DHCPRELEASE | 229 | // Field DHCPDISCOVER DHCPINFORM DHCPREQUEST DHCPDECLINE DHCPRELEASE |
231 | // ----- ------------ ------------ ----------- ----------- ----------- | 230 | // ----- ------------ ------------ ----------- ----------- ----------- |
@@ -234,56 +233,49 @@ struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) | |||
234 | // 'secs' 0 or seconds since 0 or seconds since 0 or seconds since 0 0 | 233 | // 'secs' 0 or seconds since 0 or seconds since 0 or seconds since 0 0 |
235 | // DHCP process started DHCP process started DHCP process started | 234 | // DHCP process started DHCP process started DHCP process started |
236 | // 'flags' Set 'BROADCAST' Set 'BROADCAST' Set 'BROADCAST' 0 0 | 235 | // 'flags' Set 'BROADCAST' Set 'BROADCAST' Set 'BROADCAST' 0 0 |
237 | // flag if client flag if client flag if client | 236 | // flag if client needs flag if client needs flag if client needs |
238 | // requires broadcast requires broadcast requires broadcast | 237 | // broadcast reply broadcast reply broadcast reply |
239 | // reply reply reply | ||
240 | // 'ciaddr' 0 client's IP 0 or client's IP 0 client's IP | 238 | // 'ciaddr' 0 client's IP 0 or client's IP 0 client's IP |
241 | // (BOUND/RENEW/REBIND) | 239 | // (BOUND/RENEW/REBIND) |
242 | // 'chaddr' client's MAC client's MAC client's MAC client's MAC client's MAC | ||
243 | // 'sname' options or sname options or sname options or sname (unused) (unused) | 240 | // 'sname' options or sname options or sname options or sname (unused) (unused) |
244 | // 'file' options or file options or file options or file (unused) (unused) | 241 | // 'file' options or file options or file options or file (unused) (unused) |
245 | // 'options' options options options message type opt message type opt | 242 | // 'options' options options options message type opt message type opt |
246 | // | 243 | // |
247 | // Option DHCPDISCOVER DHCPINFORM DHCPREQUEST DHCPDECLINE DHCPRELEASE | 244 | // Option DHCPDISCOVER DHCPINFORM DHCPREQUEST DHCPDECLINE DHCPRELEASE |
248 | // ------ ------------ ---------- ----------- ----------- ----------- | 245 | // ------ ------------ ---------- ----------- ----------- ----------- |
249 | // Requested IP address MAY MUST NOT MUST (in MUST MUST NOT | 246 | // Requested IP address MAY MUST NOT MUST (in SELECTING MUST MUST NOT |
250 | // SELECTING or | 247 | // or INIT-REBOOT) |
251 | // INIT-REBOOT) | 248 | // MUST NOT (in BOUND |
252 | // MUST NOT (in | 249 | // or RENEWING) |
253 | // BOUND or | 250 | // IP address lease time MAY MUST NOT MAY MUST NOT MUST NOT |
254 | // RENEWING) | 251 | // Use 'file'/'sname' fields MAY MAY MAY MAY MAY |
255 | // IP address lease time MAY MUST NOT MAY MUST NOT MUST NOT | 252 | // Client identifier MAY MAY MAY MAY MAY |
256 | // Use 'file'/'sname' fields MAY MAY MAY MAY MAY | 253 | // Vendor class identifier MAY MAY MAY MUST NOT MUST NOT |
257 | // Client identifier MAY MAY MAY MAY MAY | 254 | // Server identifier MUST NOT MUST NOT MUST (after SELECTING) MUST MUST |
258 | // Vendor class identifier MAY MAY MAY MUST NOT MUST NOT | ||
259 | // Server identifier MUST NOT MUST NOT MUST (after MUST MUST | ||
260 | // SELECTING) | ||
261 | // MUST NOT (after | 255 | // MUST NOT (after |
262 | // INIT-REBOOT, | 256 | // INIT-REBOOT, BOUND, |
263 | // BOUND, RENEWING | 257 | // RENEWING or REBINDING) |
264 | // or REBINDING) | 258 | // Parameter request list MAY MAY MAY MUST NOT MUST NOT |
265 | // Parameter request list MAY MAY MAY MUST NOT MUST NOT | 259 | // Maximum message size MAY MAY MAY MUST NOT MUST NOT |
266 | // Maximum message size MAY MAY MAY MUST NOT MUST NOT | 260 | // Message SHOULD NOT SHOULD NOT SHOULD NOT SHOULD SHOULD |
267 | // Message SHOULD NOT SHOULD NOT SHOULD NOT SHOULD SHOULD | 261 | // Site-specific MAY MAY MAY MUST NOT MUST NOT |
268 | // Site-specific MAY MAY MAY MUST NOT MUST NOT | 262 | // All others MAY MAY MAY MUST NOT MUST NOT |
269 | // All others MAY MAY MAY MUST NOT MUST NOT | ||
270 | |||
271 | 263 | ||
272 | /*** Logging ***/ | 264 | /*** Logging ***/ |
273 | 265 | ||
274 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 | 266 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 |
275 | # define IF_UDHCP_VERBOSE(...) __VA_ARGS__ | 267 | # define IF_UDHCP_VERBOSE(...) __VA_ARGS__ |
276 | extern unsigned dhcp_verbose; | 268 | extern unsigned dhcp_verbose; |
277 | # define log1(...) do { if (dhcp_verbose >= 1) bb_error_msg(__VA_ARGS__); } while (0) | 269 | # define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0) |
278 | # if CONFIG_UDHCP_DEBUG >= 2 | 270 | # if CONFIG_UDHCP_DEBUG >= 2 |
279 | void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; | 271 | void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; |
280 | # define log2(...) do { if (dhcp_verbose >= 2) bb_error_msg(__VA_ARGS__); } while (0) | 272 | # define log2(...) do { if (dhcp_verbose >= 2) bb_info_msg(__VA_ARGS__); } while (0) |
281 | # else | 273 | # else |
282 | # define udhcp_dump_packet(...) ((void)0) | 274 | # define udhcp_dump_packet(...) ((void)0) |
283 | # define log2(...) ((void)0) | 275 | # define log2(...) ((void)0) |
284 | # endif | 276 | # endif |
285 | # if CONFIG_UDHCP_DEBUG >= 3 | 277 | # if CONFIG_UDHCP_DEBUG >= 3 |
286 | # define log3(...) do { if (dhcp_verbose >= 3) bb_error_msg(__VA_ARGS__); } while (0) | 278 | # define log3(...) do { if (dhcp_verbose >= 3) bb_info_msg(__VA_ARGS__); } while (0) |
287 | # else | 279 | # else |
288 | # define log3(...) ((void)0) | 280 | # define log3(...) ((void)0) |
289 | # endif | 281 | # endif |
diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h index 2178cb9d6..dee2558e2 100644 --- a/networking/udhcp/d6_common.h +++ b/networking/udhcp/d6_common.h | |||
@@ -141,7 +141,7 @@ struct client6_data_t { | |||
141 | unsigned env_idx; | 141 | unsigned env_idx; |
142 | /* link-local IPv6 address */ | 142 | /* link-local IPv6 address */ |
143 | struct in6_addr ll_ip6; | 143 | struct in6_addr ll_ip6; |
144 | }; | 144 | } FIX_ALIASING; |
145 | 145 | ||
146 | #define client6_data (*(struct client6_data_t*)(&bb_common_bufsiz1[COMMON_BUFSIZE - sizeof(struct client6_data_t)])) | 146 | #define client6_data (*(struct client6_data_t*)(&bb_common_bufsiz1[COMMON_BUFSIZE - sizeof(struct client6_data_t)])) |
147 | 147 | ||
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 3562988fd..15e9f3924 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -63,7 +63,7 @@ | |||
63 | #include <netpacket/packet.h> | 63 | #include <netpacket/packet.h> |
64 | #include <linux/filter.h> | 64 | #include <linux/filter.h> |
65 | 65 | ||
66 | /* "struct client_config_t client_config" is in bb_common_bufsiz1 */ | 66 | /* "struct client_data_t client_data" is in bb_common_bufsiz1 */ |
67 | 67 | ||
68 | static const struct dhcp_optflag d6_optflags[] = { | 68 | static const struct dhcp_optflag d6_optflags[] = { |
69 | #if ENABLE_FEATURE_UDHCPC6_RFC3646 | 69 | #if ENABLE_FEATURE_UDHCPC6_RFC3646 |
@@ -427,7 +427,7 @@ static char **fill_envp(const uint8_t *option, const uint8_t *option_end) | |||
427 | client6_data.env_ptr = NULL; | 427 | client6_data.env_ptr = NULL; |
428 | client6_data.env_idx = 0; | 428 | client6_data.env_idx = 0; |
429 | 429 | ||
430 | *new_env() = xasprintf("interface=%s", client_config.interface); | 430 | *new_env() = xasprintf("interface=%s", client_data.interface); |
431 | 431 | ||
432 | if (option) | 432 | if (option) |
433 | option_to_env(option, option_end); | 433 | option_to_env(option, option_end); |
@@ -449,8 +449,8 @@ static void d6_run_script(const uint8_t *option, const uint8_t *option_end, | |||
449 | envp = fill_envp(option, option_end); | 449 | envp = fill_envp(option, option_end); |
450 | 450 | ||
451 | /* call script */ | 451 | /* call script */ |
452 | log1("executing %s %s", client_config.script, name); | 452 | log1("executing %s %s", client_data.script, name); |
453 | argv[0] = (char*) client_config.script; | 453 | argv[0] = (char*) client_data.script; |
454 | argv[1] = (char*) name; | 454 | argv[1] = (char*) name; |
455 | argv[2] = NULL; | 455 | argv[2] = NULL; |
456 | spawn_and_wait(argv); | 456 | spawn_and_wait(argv); |
@@ -486,7 +486,7 @@ static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid | |||
486 | packet->d6_xid32 = xid; | 486 | packet->d6_xid32 = xid; |
487 | packet->d6_msg_type = type; | 487 | packet->d6_msg_type = type; |
488 | 488 | ||
489 | clientid = (void*)client_config.clientid; | 489 | clientid = (void*)client_data.clientid; |
490 | return mempcpy(packet->d6_options, clientid, clientid->len + 2+2); | 490 | return mempcpy(packet->d6_options, clientid, clientid->len + 2+2); |
491 | } | 491 | } |
492 | 492 | ||
@@ -499,7 +499,7 @@ static uint8_t *add_d6_client_options(uint8_t *ptr) | |||
499 | 499 | ||
500 | ptr += 4; | 500 | ptr += 4; |
501 | for (option = 1; option < 256; option++) { | 501 | for (option = 1; option < 256; option++) { |
502 | if (client_config.opt_mask[option >> 3] & (1 << (option & 7))) { | 502 | if (client_data.opt_mask[option >> 3] & (1 << (option & 7))) { |
503 | ptr[0] = (option >> 8); | 503 | ptr[0] = (option >> 8); |
504 | ptr[1] = option; | 504 | ptr[1] = option; |
505 | ptr += 2; | 505 | ptr += 2; |
@@ -518,7 +518,7 @@ static uint8_t *add_d6_client_options(uint8_t *ptr) | |||
518 | ptr = mempcpy(ptr, &opt_fqdn_req, sizeof(opt_fqdn_req)); | 518 | ptr = mempcpy(ptr, &opt_fqdn_req, sizeof(opt_fqdn_req)); |
519 | #endif | 519 | #endif |
520 | /* Add -x options if any */ | 520 | /* Add -x options if any */ |
521 | curr = client_config.options; | 521 | curr = client_data.options; |
522 | while (curr) { | 522 | while (curr) { |
523 | len = (curr->data[D6_OPT_LEN] << 8) | curr->data[D6_OPT_LEN + 1]; | 523 | len = (curr->data[D6_OPT_LEN] << 8) | curr->data[D6_OPT_LEN + 1]; |
524 | ptr = mempcpy(ptr, curr->data, D6_OPT_DATA + len); | 524 | ptr = mempcpy(ptr, curr->data, D6_OPT_DATA + len); |
@@ -528,7 +528,7 @@ static uint8_t *add_d6_client_options(uint8_t *ptr) | |||
528 | return ptr; | 528 | return ptr; |
529 | } | 529 | } |
530 | 530 | ||
531 | static int d6_mcast_from_client_config_ifindex(struct d6_packet *packet, uint8_t *end) | 531 | static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t *end) |
532 | { | 532 | { |
533 | /* FF02::1:2 is "All_DHCP_Relay_Agents_and_Servers" address */ | 533 | /* FF02::1:2 is "All_DHCP_Relay_Agents_and_Servers" address */ |
534 | static const uint8_t FF02__1_2[16] = { | 534 | static const uint8_t FF02__1_2[16] = { |
@@ -540,7 +540,7 @@ static int d6_mcast_from_client_config_ifindex(struct d6_packet *packet, uint8_t | |||
540 | packet, (end - (uint8_t*) packet), | 540 | packet, (end - (uint8_t*) packet), |
541 | /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, | 541 | /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, |
542 | /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_BCAST_ADDR, | 542 | /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_BCAST_ADDR, |
543 | client_config.ifindex | 543 | client_data.ifindex |
544 | ); | 544 | ); |
545 | } | 545 | } |
546 | 546 | ||
@@ -670,8 +670,8 @@ static NOINLINE int send_d6_discover(uint32_t xid, struct in6_addr *requested_ip | |||
670 | */ | 670 | */ |
671 | opt_ptr = add_d6_client_options(opt_ptr); | 671 | opt_ptr = add_d6_client_options(opt_ptr); |
672 | 672 | ||
673 | bb_error_msg("sending %s", "discover"); | 673 | bb_info_msg("sending %s", "discover"); |
674 | return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); | 674 | return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); |
675 | } | 675 | } |
676 | 676 | ||
677 | /* Multicast a DHCPv6 request message | 677 | /* Multicast a DHCPv6 request message |
@@ -727,8 +727,8 @@ static NOINLINE int send_d6_select(uint32_t xid) | |||
727 | */ | 727 | */ |
728 | opt_ptr = add_d6_client_options(opt_ptr); | 728 | opt_ptr = add_d6_client_options(opt_ptr); |
729 | 729 | ||
730 | bb_error_msg("sending %s", "select"); | 730 | bb_info_msg("sending %s", "select"); |
731 | return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); | 731 | return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); |
732 | } | 732 | } |
733 | 733 | ||
734 | /* Unicast or broadcast a DHCP renew message | 734 | /* Unicast or broadcast a DHCP renew message |
@@ -800,15 +800,15 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st | |||
800 | */ | 800 | */ |
801 | opt_ptr = add_d6_client_options(opt_ptr); | 801 | opt_ptr = add_d6_client_options(opt_ptr); |
802 | 802 | ||
803 | bb_error_msg("sending %s", "renew"); | 803 | bb_info_msg("sending %s", "renew"); |
804 | if (server_ipv6) | 804 | if (server_ipv6) |
805 | return d6_send_kernel_packet( | 805 | return d6_send_kernel_packet( |
806 | &packet, (opt_ptr - (uint8_t*) &packet), | 806 | &packet, (opt_ptr - (uint8_t*) &packet), |
807 | our_cur_ipv6, CLIENT_PORT6, | 807 | our_cur_ipv6, CLIENT_PORT6, |
808 | server_ipv6, SERVER_PORT6, | 808 | server_ipv6, SERVER_PORT6, |
809 | client_config.ifindex | 809 | client_data.ifindex |
810 | ); | 810 | ); |
811 | return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); | 811 | return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); |
812 | } | 812 | } |
813 | 813 | ||
814 | /* Unicast a DHCP release message */ | 814 | /* Unicast a DHCP release message */ |
@@ -830,12 +830,12 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) | |||
830 | if (client6_data.ia_pd) | 830 | if (client6_data.ia_pd) |
831 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); | 831 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); |
832 | 832 | ||
833 | bb_error_msg("sending %s", "release"); | 833 | bb_info_msg("sending %s", "release"); |
834 | return d6_send_kernel_packet( | 834 | return d6_send_kernel_packet( |
835 | &packet, (opt_ptr - (uint8_t*) &packet), | 835 | &packet, (opt_ptr - (uint8_t*) &packet), |
836 | our_cur_ipv6, CLIENT_PORT6, | 836 | our_cur_ipv6, CLIENT_PORT6, |
837 | server_ipv6, SERVER_PORT6, | 837 | server_ipv6, SERVER_PORT6, |
838 | client_config.ifindex | 838 | client_data.ifindex |
839 | ); | 839 | ); |
840 | } | 840 | } |
841 | 841 | ||
@@ -903,13 +903,12 @@ static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6, struct d6_pac | |||
903 | 903 | ||
904 | /*** Main ***/ | 904 | /*** Main ***/ |
905 | 905 | ||
906 | static int sockfd = -1; | 906 | /* Values for client_data.listen_mode */ |
907 | |||
908 | #define LISTEN_NONE 0 | 907 | #define LISTEN_NONE 0 |
909 | #define LISTEN_KERNEL 1 | 908 | #define LISTEN_KERNEL 1 |
910 | #define LISTEN_RAW 2 | 909 | #define LISTEN_RAW 2 |
911 | static smallint listen_mode; | ||
912 | 910 | ||
911 | /* Values for client_data.state */ | ||
913 | /* initial state: (re)start DHCP negotiation */ | 912 | /* initial state: (re)start DHCP negotiation */ |
914 | #define INIT_SELECTING 0 | 913 | #define INIT_SELECTING 0 |
915 | /* discover was sent, DHCPOFFER reply received */ | 914 | /* discover was sent, DHCPOFFER reply received */ |
@@ -924,7 +923,6 @@ static smallint listen_mode; | |||
924 | #define RENEW_REQUESTED 5 | 923 | #define RENEW_REQUESTED 5 |
925 | /* release, possibly manually requested (SIGUSR2) */ | 924 | /* release, possibly manually requested (SIGUSR2) */ |
926 | #define RELEASED 6 | 925 | #define RELEASED 6 |
927 | static smallint state; | ||
928 | 926 | ||
929 | static int d6_raw_socket(int ifindex) | 927 | static int d6_raw_socket(int ifindex) |
930 | { | 928 | { |
@@ -1018,35 +1016,35 @@ static void change_listen_mode(int new_mode) | |||
1018 | : "none" | 1016 | : "none" |
1019 | ); | 1017 | ); |
1020 | 1018 | ||
1021 | listen_mode = new_mode; | 1019 | client_data.listen_mode = new_mode; |
1022 | if (sockfd >= 0) { | 1020 | if (client_data.sockfd >= 0) { |
1023 | close(sockfd); | 1021 | close(client_data.sockfd); |
1024 | sockfd = -1; | 1022 | client_data.sockfd = -1; |
1025 | } | 1023 | } |
1026 | if (new_mode == LISTEN_KERNEL) | 1024 | if (new_mode == LISTEN_KERNEL) |
1027 | sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT6, client_config.interface); | 1025 | client_data.sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT6, client_data.interface); |
1028 | else if (new_mode != LISTEN_NONE) | 1026 | else if (new_mode != LISTEN_NONE) |
1029 | sockfd = d6_raw_socket(client_config.ifindex); | 1027 | client_data.sockfd = d6_raw_socket(client_data.ifindex); |
1030 | /* else LISTEN_NONE: sockfd stays closed */ | 1028 | /* else LISTEN_NONE: client_data.sockfd stays closed */ |
1031 | } | 1029 | } |
1032 | 1030 | ||
1033 | /* Called only on SIGUSR1 */ | 1031 | /* Called only on SIGUSR1 */ |
1034 | static void perform_renew(void) | 1032 | static void perform_renew(void) |
1035 | { | 1033 | { |
1036 | bb_error_msg("performing DHCP renew"); | 1034 | bb_info_msg("performing DHCP renew"); |
1037 | switch (state) { | 1035 | switch (client_data.state) { |
1038 | case BOUND: | 1036 | case BOUND: |
1039 | change_listen_mode(LISTEN_KERNEL); | 1037 | change_listen_mode(LISTEN_KERNEL); |
1040 | case RENEWING: | 1038 | case RENEWING: |
1041 | case REBINDING: | 1039 | case REBINDING: |
1042 | state = RENEW_REQUESTED; | 1040 | client_data.state = RENEW_REQUESTED; |
1043 | break; | 1041 | break; |
1044 | case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ | 1042 | case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ |
1045 | d6_run_script_no_option("deconfig"); | 1043 | d6_run_script_no_option("deconfig"); |
1046 | case REQUESTING: | 1044 | case REQUESTING: |
1047 | case RELEASED: | 1045 | case RELEASED: |
1048 | change_listen_mode(LISTEN_RAW); | 1046 | change_listen_mode(LISTEN_RAW); |
1049 | state = INIT_SELECTING; | 1047 | client_data.state = INIT_SELECTING; |
1050 | break; | 1048 | break; |
1051 | case INIT_SELECTING: | 1049 | case INIT_SELECTING: |
1052 | break; | 1050 | break; |
@@ -1056,15 +1054,15 @@ static void perform_renew(void) | |||
1056 | static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) | 1054 | static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) |
1057 | { | 1055 | { |
1058 | /* send release packet */ | 1056 | /* send release packet */ |
1059 | if (state == BOUND | 1057 | if (client_data.state == BOUND |
1060 | || state == RENEWING | 1058 | || client_data.state == RENEWING |
1061 | || state == REBINDING | 1059 | || client_data.state == REBINDING |
1062 | || state == RENEW_REQUESTED | 1060 | || client_data.state == RENEW_REQUESTED |
1063 | ) { | 1061 | ) { |
1064 | bb_error_msg("unicasting a release"); | 1062 | bb_info_msg("unicasting a release"); |
1065 | send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */ | 1063 | send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */ |
1066 | } | 1064 | } |
1067 | bb_error_msg("entering released state"); | 1065 | bb_info_msg("entering released state"); |
1068 | /* | 1066 | /* |
1069 | * We can be here on: SIGUSR2, | 1067 | * We can be here on: SIGUSR2, |
1070 | * or on exit (SIGTERM) and -R "release on quit" is specified. | 1068 | * or on exit (SIGTERM) and -R "release on quit" is specified. |
@@ -1073,7 +1071,7 @@ static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *ou | |||
1073 | */ | 1071 | */ |
1074 | d6_run_script_no_option("deconfig"); | 1072 | d6_run_script_no_option("deconfig"); |
1075 | change_listen_mode(LISTEN_NONE); | 1073 | change_listen_mode(LISTEN_NONE); |
1076 | state = RELEASED; | 1074 | client_data.state = RELEASED; |
1077 | } | 1075 | } |
1078 | 1076 | ||
1079 | ///static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) | 1077 | ///static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) |
@@ -1093,7 +1091,7 @@ static void client_background(void) | |||
1093 | bb_daemonize(0); | 1091 | bb_daemonize(0); |
1094 | logmode &= ~LOGMODE_STDIO; | 1092 | logmode &= ~LOGMODE_STDIO; |
1095 | /* rewrite pidfile, as our pid is different now */ | 1093 | /* rewrite pidfile, as our pid is different now */ |
1096 | write_pidfile(client_config.pidfile); | 1094 | write_pidfile(client_data.pidfile); |
1097 | } | 1095 | } |
1098 | #endif | 1096 | #endif |
1099 | 1097 | ||
@@ -1172,8 +1170,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1172 | /* Default options */ | 1170 | /* Default options */ |
1173 | IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) | 1171 | IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) |
1174 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) | 1172 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) |
1175 | client_config.interface = "eth0"; | 1173 | client_data.interface = "eth0"; |
1176 | client_config.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; | 1174 | client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; |
1175 | client_data.sockfd = -1; | ||
1177 | 1176 | ||
1178 | /* Parse command line */ | 1177 | /* Parse command line */ |
1179 | opt = getopt32long(argv, "^" | 1178 | opt = getopt32long(argv, "^" |
@@ -1185,8 +1184,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1185 | "v" | 1184 | "v" |
1186 | "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */ | 1185 | "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */ |
1187 | , udhcpc6_longopts | 1186 | , udhcpc6_longopts |
1188 | , &client_config.interface, &client_config.pidfile, &str_r /* i,p */ | 1187 | , &client_data.interface, &client_data.pidfile, &str_r /* i,p */ |
1189 | , &client_config.script /* s */ | 1188 | , &client_data.script /* s */ |
1190 | , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ | 1189 | , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ |
1191 | , &list_O | 1190 | , &list_O |
1192 | , &list_x | 1191 | , &list_x |
@@ -1217,29 +1216,29 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1217 | n = udhcp_option_idx(optstr, d6_option_strings); | 1216 | n = udhcp_option_idx(optstr, d6_option_strings); |
1218 | n = d6_optflags[n].code; | 1217 | n = d6_optflags[n].code; |
1219 | } | 1218 | } |
1220 | client_config.opt_mask[n >> 3] |= 1 << (n & 7); | 1219 | client_data.opt_mask[n >> 3] |= 1 << (n & 7); |
1221 | } | 1220 | } |
1222 | if (!(opt & OPT_o)) { | 1221 | if (!(opt & OPT_o)) { |
1223 | unsigned i, n; | 1222 | unsigned i, n; |
1224 | for (i = 0; (n = d6_optflags[i].code) != 0; i++) { | 1223 | for (i = 0; (n = d6_optflags[i].code) != 0; i++) { |
1225 | if (d6_optflags[i].flags & OPTION_REQ) { | 1224 | if (d6_optflags[i].flags & OPTION_REQ) { |
1226 | client_config.opt_mask[n >> 3] |= 1 << (n & 7); | 1225 | client_data.opt_mask[n >> 3] |= 1 << (n & 7); |
1227 | } | 1226 | } |
1228 | } | 1227 | } |
1229 | } | 1228 | } |
1230 | while (list_x) { | 1229 | while (list_x) { |
1231 | char *optstr = xstrdup(llist_pop(&list_x)); | 1230 | char *optstr = xstrdup(llist_pop(&list_x)); |
1232 | udhcp_str2optset(optstr, &client_config.options, | 1231 | udhcp_str2optset(optstr, &client_data.options, |
1233 | d6_optflags, d6_option_strings, | 1232 | d6_optflags, d6_option_strings, |
1234 | /*dhcpv6:*/ 1 | 1233 | /*dhcpv6:*/ 1 |
1235 | ); | 1234 | ); |
1236 | free(optstr); | 1235 | free(optstr); |
1237 | } | 1236 | } |
1238 | 1237 | ||
1239 | if (d6_read_interface(client_config.interface, | 1238 | if (d6_read_interface(client_data.interface, |
1240 | &client_config.ifindex, | 1239 | &client_data.ifindex, |
1241 | &client6_data.ll_ip6, | 1240 | &client6_data.ll_ip6, |
1242 | client_config.client_mac) | 1241 | client_data.client_mac) |
1243 | ) { | 1242 | ) { |
1244 | return 1; | 1243 | return 1; |
1245 | } | 1244 | } |
@@ -1253,8 +1252,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1253 | clientid->data[1] = 3; /* DUID-LL */ | 1252 | clientid->data[1] = 3; /* DUID-LL */ |
1254 | clientid->data[3] = 1; /* ethernet */ | 1253 | clientid->data[3] = 1; /* ethernet */ |
1255 | clientid_mac_ptr = clientid->data + 2+2; | 1254 | clientid_mac_ptr = clientid->data + 2+2; |
1256 | memcpy(clientid_mac_ptr, client_config.client_mac, 6); | 1255 | memcpy(clientid_mac_ptr, client_data.client_mac, 6); |
1257 | client_config.clientid = (void*)clientid; | 1256 | client_data.clientid = (void*)clientid; |
1258 | } | 1257 | } |
1259 | 1258 | ||
1260 | #if !BB_MMU | 1259 | #if !BB_MMU |
@@ -1272,13 +1271,13 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1272 | /* Make sure fd 0,1,2 are open */ | 1271 | /* Make sure fd 0,1,2 are open */ |
1273 | bb_sanitize_stdio(); | 1272 | bb_sanitize_stdio(); |
1274 | /* Create pidfile */ | 1273 | /* Create pidfile */ |
1275 | write_pidfile(client_config.pidfile); | 1274 | write_pidfile(client_data.pidfile); |
1276 | /* Goes to stdout (unless NOMMU) and possibly syslog */ | 1275 | /* Goes to stdout (unless NOMMU) and possibly syslog */ |
1277 | bb_error_msg("started, v"BB_VER); | 1276 | bb_info_msg("started, v"BB_VER); |
1278 | /* Set up the signal pipe */ | 1277 | /* Set up the signal pipe */ |
1279 | udhcp_sp_setup(); | 1278 | udhcp_sp_setup(); |
1280 | 1279 | ||
1281 | state = INIT_SELECTING; | 1280 | client_data.state = INIT_SELECTING; |
1282 | d6_run_script_no_option("deconfig"); | 1281 | d6_run_script_no_option("deconfig"); |
1283 | change_listen_mode(LISTEN_RAW); | 1282 | change_listen_mode(LISTEN_RAW); |
1284 | packet_num = 0; | 1283 | packet_num = 0; |
@@ -1297,16 +1296,16 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1297 | /* silence "uninitialized!" warning */ | 1296 | /* silence "uninitialized!" warning */ |
1298 | unsigned timestamp_before_wait = timestamp_before_wait; | 1297 | unsigned timestamp_before_wait = timestamp_before_wait; |
1299 | 1298 | ||
1300 | //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode); | 1299 | //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode); |
1301 | 1300 | ||
1302 | /* Was opening raw or udp socket here | 1301 | /* Was opening raw or udp socket here |
1303 | * if (listen_mode != LISTEN_NONE && sockfd < 0), | 1302 | * if (client_data.listen_mode != LISTEN_NONE && client_data.sockfd < 0), |
1304 | * but on fast network renew responses return faster | 1303 | * but on fast network renew responses return faster |
1305 | * than we open sockets. Thus this code is moved | 1304 | * than we open sockets. Thus this code is moved |
1306 | * to change_listen_mode(). Thus we open listen socket | 1305 | * to change_listen_mode(). Thus we open listen socket |
1307 | * BEFORE we send renew request (see "case BOUND:"). */ | 1306 | * BEFORE we send renew request (see "case BOUND:"). */ |
1308 | 1307 | ||
1309 | udhcp_sp_fd_set(pfds, sockfd); | 1308 | udhcp_sp_fd_set(pfds, client_data.sockfd); |
1310 | 1309 | ||
1311 | tv = timeout - already_waited_sec; | 1310 | tv = timeout - already_waited_sec; |
1312 | retval = 0; | 1311 | retval = 0; |
@@ -1335,20 +1334,20 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1335 | * or if the status of the bridge changed). | 1334 | * or if the status of the bridge changed). |
1336 | * Refresh ifindex and client_mac: | 1335 | * Refresh ifindex and client_mac: |
1337 | */ | 1336 | */ |
1338 | if (d6_read_interface(client_config.interface, | 1337 | if (d6_read_interface(client_data.interface, |
1339 | &client_config.ifindex, | 1338 | &client_data.ifindex, |
1340 | &client6_data.ll_ip6, | 1339 | &client6_data.ll_ip6, |
1341 | client_config.client_mac) | 1340 | client_data.client_mac) |
1342 | ) { | 1341 | ) { |
1343 | goto ret0; /* iface is gone? */ | 1342 | goto ret0; /* iface is gone? */ |
1344 | } | 1343 | } |
1345 | 1344 | ||
1346 | memcpy(clientid_mac_ptr, client_config.client_mac, 6); | 1345 | memcpy(clientid_mac_ptr, client_data.client_mac, 6); |
1347 | 1346 | ||
1348 | /* We will restart the wait in any case */ | 1347 | /* We will restart the wait in any case */ |
1349 | already_waited_sec = 0; | 1348 | already_waited_sec = 0; |
1350 | 1349 | ||
1351 | switch (state) { | 1350 | switch (client_data.state) { |
1352 | case INIT_SELECTING: | 1351 | case INIT_SELECTING: |
1353 | if (!discover_retries || packet_num < discover_retries) { | 1352 | if (!discover_retries || packet_num < discover_retries) { |
1354 | if (packet_num == 0) | 1353 | if (packet_num == 0) |
@@ -1363,7 +1362,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1363 | d6_run_script_no_option("leasefail"); | 1362 | d6_run_script_no_option("leasefail"); |
1364 | #if BB_MMU /* -b is not supported on NOMMU */ | 1363 | #if BB_MMU /* -b is not supported on NOMMU */ |
1365 | if (opt & OPT_b) { /* background if no lease */ | 1364 | if (opt & OPT_b) { /* background if no lease */ |
1366 | bb_error_msg("no lease, forking to background"); | 1365 | bb_info_msg("no lease, forking to background"); |
1367 | client_background(); | 1366 | client_background(); |
1368 | /* do not background again! */ | 1367 | /* do not background again! */ |
1369 | opt = ((opt & ~(OPT_b|OPT_n)) | OPT_f); | 1368 | opt = ((opt & ~(OPT_b|OPT_n)) | OPT_f); |
@@ -1376,7 +1375,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1376 | } else | 1375 | } else |
1377 | #endif | 1376 | #endif |
1378 | if (opt & OPT_n) { /* abort if no lease */ | 1377 | if (opt & OPT_n) { /* abort if no lease */ |
1379 | bb_error_msg("no lease, failing"); | 1378 | bb_info_msg("no lease, failing"); |
1380 | retval = 1; | 1379 | retval = 1; |
1381 | goto ret; | 1380 | goto ret; |
1382 | } | 1381 | } |
@@ -1397,12 +1396,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1397 | * were seen in the wild. Treat them similarly | 1396 | * were seen in the wild. Treat them similarly |
1398 | * to "no response to discover" case */ | 1397 | * to "no response to discover" case */ |
1399 | change_listen_mode(LISTEN_RAW); | 1398 | change_listen_mode(LISTEN_RAW); |
1400 | state = INIT_SELECTING; | 1399 | client_data.state = INIT_SELECTING; |
1401 | goto leasefail; | 1400 | goto leasefail; |
1402 | case BOUND: | 1401 | case BOUND: |
1403 | /* 1/2 lease passed, enter renewing state */ | 1402 | /* 1/2 lease passed, enter renewing state */ |
1404 | state = RENEWING; | 1403 | client_data.state = RENEWING; |
1405 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1404 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1406 | change_listen_mode(LISTEN_KERNEL); | 1405 | change_listen_mode(LISTEN_KERNEL); |
1407 | log1("entering renew state"); | 1406 | log1("entering renew state"); |
1408 | /* fall right through */ | 1407 | /* fall right through */ |
@@ -1425,7 +1424,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1425 | } | 1424 | } |
1426 | /* Timed out, enter rebinding state */ | 1425 | /* Timed out, enter rebinding state */ |
1427 | log1("entering rebinding state"); | 1426 | log1("entering rebinding state"); |
1428 | state = REBINDING; | 1427 | client_data.state = REBINDING; |
1429 | /* fall right through */ | 1428 | /* fall right through */ |
1430 | case REBINDING: | 1429 | case REBINDING: |
1431 | /* Switch to bcast receive */ | 1430 | /* Switch to bcast receive */ |
@@ -1439,10 +1438,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1439 | continue; | 1438 | continue; |
1440 | } | 1439 | } |
1441 | /* Timed out, enter init state */ | 1440 | /* Timed out, enter init state */ |
1442 | bb_error_msg("lease lost, entering init state"); | 1441 | bb_info_msg("lease lost, entering init state"); |
1443 | d6_run_script_no_option("deconfig"); | 1442 | d6_run_script_no_option("deconfig"); |
1444 | state = INIT_SELECTING; | 1443 | client_data.state = INIT_SELECTING; |
1445 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1444 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1446 | /*timeout = 0; - already is */ | 1445 | /*timeout = 0; - already is */ |
1447 | packet_num = 0; | 1446 | packet_num = 0; |
1448 | continue; | 1447 | continue; |
@@ -1458,10 +1457,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1458 | /* Is it a signal? */ | 1457 | /* Is it a signal? */ |
1459 | switch (udhcp_sp_read()) { | 1458 | switch (udhcp_sp_read()) { |
1460 | case SIGUSR1: | 1459 | case SIGUSR1: |
1461 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1460 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1462 | already_waited_sec = 0; | 1461 | already_waited_sec = 0; |
1463 | perform_renew(); | 1462 | perform_renew(); |
1464 | if (state == RENEW_REQUESTED) { | 1463 | if (client_data.state == RENEW_REQUESTED) { |
1465 | /* We might be either on the same network | 1464 | /* We might be either on the same network |
1466 | * (in which case renew might work), | 1465 | * (in which case renew might work), |
1467 | * or we might be on a completely different one | 1466 | * or we might be on a completely different one |
@@ -1484,7 +1483,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1484 | timeout = INT_MAX; | 1483 | timeout = INT_MAX; |
1485 | continue; | 1484 | continue; |
1486 | case SIGTERM: | 1485 | case SIGTERM: |
1487 | bb_error_msg("received %s", "SIGTERM"); | 1486 | bb_info_msg("received %s", "SIGTERM"); |
1488 | goto ret0; | 1487 | goto ret0; |
1489 | } | 1488 | } |
1490 | 1489 | ||
@@ -1496,15 +1495,15 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1496 | int len; | 1495 | int len; |
1497 | 1496 | ||
1498 | /* A packet is ready, read it */ | 1497 | /* A packet is ready, read it */ |
1499 | if (listen_mode == LISTEN_KERNEL) | 1498 | if (client_data.listen_mode == LISTEN_KERNEL) |
1500 | len = d6_recv_kernel_packet(&srv6_buf, &packet, sockfd); | 1499 | len = d6_recv_kernel_packet(&srv6_buf, &packet, client_data.sockfd); |
1501 | else | 1500 | else |
1502 | len = d6_recv_raw_packet(&srv6_buf, &packet, sockfd); | 1501 | len = d6_recv_raw_packet(&srv6_buf, &packet, client_data.sockfd); |
1503 | if (len == -1) { | 1502 | if (len == -1) { |
1504 | /* Error is severe, reopen socket */ | 1503 | /* Error is severe, reopen socket */ |
1505 | bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO); | 1504 | bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO); |
1506 | sleep(discover_timeout); /* 3 seconds by default */ | 1505 | sleep(discover_timeout); /* 3 seconds by default */ |
1507 | change_listen_mode(listen_mode); /* just close and reopen */ | 1506 | change_listen_mode(client_data.listen_mode); /* just close and reopen */ |
1508 | } | 1507 | } |
1509 | /* If this packet will turn out to be unrelated/bogus, | 1508 | /* If this packet will turn out to be unrelated/bogus, |
1510 | * we will go back and wait for next one. | 1509 | * we will go back and wait for next one. |
@@ -1521,7 +1520,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1521 | continue; | 1520 | continue; |
1522 | } | 1521 | } |
1523 | 1522 | ||
1524 | switch (state) { | 1523 | switch (client_data.state) { |
1525 | case INIT_SELECTING: | 1524 | case INIT_SELECTING: |
1526 | if (packet.d6_msg_type == D6_MSG_ADVERTISE) | 1525 | if (packet.d6_msg_type == D6_MSG_ADVERTISE) |
1527 | goto type_is_ok; | 1526 | goto type_is_ok; |
@@ -1544,15 +1543,15 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1544 | option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE); | 1543 | option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE); |
1545 | if (option && (option->data[0] | option->data[1]) != 0) { | 1544 | if (option && (option->data[0] | option->data[1]) != 0) { |
1546 | /* return to init state */ | 1545 | /* return to init state */ |
1547 | bb_error_msg("received DHCP NAK (%u)", option->data[4]); | 1546 | bb_info_msg("received DHCP NAK (%u)", option->data[4]); |
1548 | d6_run_script(packet.d6_options, | 1547 | d6_run_script(packet.d6_options, |
1549 | packet_end, "nak"); | 1548 | packet_end, "nak"); |
1550 | if (state != REQUESTING) | 1549 | if (client_data.state != REQUESTING) |
1551 | d6_run_script_no_option("deconfig"); | 1550 | d6_run_script_no_option("deconfig"); |
1552 | change_listen_mode(LISTEN_RAW); | 1551 | change_listen_mode(LISTEN_RAW); |
1553 | sleep(3); /* avoid excessive network traffic */ | 1552 | sleep(3); /* avoid excessive network traffic */ |
1554 | state = INIT_SELECTING; | 1553 | client_data.state = INIT_SELECTING; |
1555 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1554 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1556 | requested_ipv6 = NULL; | 1555 | requested_ipv6 = NULL; |
1557 | timeout = 0; | 1556 | timeout = 0; |
1558 | packet_num = 0; | 1557 | packet_num = 0; |
@@ -1561,7 +1560,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1561 | } | 1560 | } |
1562 | option = d6_copy_option(packet.d6_options, packet_end, D6_OPT_SERVERID); | 1561 | option = d6_copy_option(packet.d6_options, packet_end, D6_OPT_SERVERID); |
1563 | if (!option) { | 1562 | if (!option) { |
1564 | bb_error_msg("no server ID, ignoring packet"); | 1563 | bb_info_msg("no server ID, ignoring packet"); |
1565 | continue; | 1564 | continue; |
1566 | /* still selecting - this server looks bad */ | 1565 | /* still selecting - this server looks bad */ |
1567 | } | 1566 | } |
@@ -1572,7 +1571,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1572 | client6_data.server_id = option; | 1571 | client6_data.server_id = option; |
1573 | if (packet.d6_msg_type == D6_MSG_ADVERTISE) { | 1572 | if (packet.d6_msg_type == D6_MSG_ADVERTISE) { |
1574 | /* enter requesting state */ | 1573 | /* enter requesting state */ |
1575 | state = REQUESTING; | 1574 | client_data.state = REQUESTING; |
1576 | timeout = 0; | 1575 | timeout = 0; |
1577 | packet_num = 0; | 1576 | packet_num = 0; |
1578 | already_waited_sec = 0; | 1577 | already_waited_sec = 0; |
@@ -1670,11 +1669,11 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1670 | free(client6_data.ia_na); | 1669 | free(client6_data.ia_na); |
1671 | client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA); | 1670 | client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA); |
1672 | if (!client6_data.ia_na) { | 1671 | if (!client6_data.ia_na) { |
1673 | bb_error_msg("no %s option, ignoring packet", "IA_NA"); | 1672 | bb_info_msg("no %s option, ignoring packet", "IA_NA"); |
1674 | continue; | 1673 | continue; |
1675 | } | 1674 | } |
1676 | if (client6_data.ia_na->len < (4 + 4 + 4) + (2 + 2 + 16 + 4 + 4)) { | 1675 | if (client6_data.ia_na->len < (4 + 4 + 4) + (2 + 2 + 16 + 4 + 4)) { |
1677 | bb_error_msg("%s option is too short:%d bytes", | 1676 | bb_info_msg("%s option is too short:%d bytes", |
1678 | "IA_NA", client6_data.ia_na->len); | 1677 | "IA_NA", client6_data.ia_na->len); |
1679 | continue; | 1678 | continue; |
1680 | } | 1679 | } |
@@ -1683,11 +1682,11 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1683 | D6_OPT_IAADDR | 1682 | D6_OPT_IAADDR |
1684 | ); | 1683 | ); |
1685 | if (!iaaddr) { | 1684 | if (!iaaddr) { |
1686 | bb_error_msg("no %s option, ignoring packet", "IAADDR"); | 1685 | bb_info_msg("no %s option, ignoring packet", "IAADDR"); |
1687 | continue; | 1686 | continue; |
1688 | } | 1687 | } |
1689 | if (iaaddr->len < (16 + 4 + 4)) { | 1688 | if (iaaddr->len < (16 + 4 + 4)) { |
1690 | bb_error_msg("%s option is too short:%d bytes", | 1689 | bb_info_msg("%s option is too short:%d bytes", |
1691 | "IAADDR", iaaddr->len); | 1690 | "IAADDR", iaaddr->len); |
1692 | continue; | 1691 | continue; |
1693 | } | 1692 | } |
@@ -1698,7 +1697,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1698 | move_from_unaligned32(lease_seconds, iaaddr->data + 16 + 4); | 1697 | move_from_unaligned32(lease_seconds, iaaddr->data + 16 + 4); |
1699 | lease_seconds = ntohl(lease_seconds); | 1698 | lease_seconds = ntohl(lease_seconds); |
1700 | /// TODO: check for 0 lease time? | 1699 | /// TODO: check for 0 lease time? |
1701 | bb_error_msg("%s obtained, lease time %u", | 1700 | bb_info_msg("%s obtained, lease time %u", |
1702 | "IPv6", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); | 1701 | "IPv6", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); |
1703 | address_timeout = lease_seconds; | 1702 | address_timeout = lease_seconds; |
1704 | } | 1703 | } |
@@ -1708,11 +1707,11 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1708 | free(client6_data.ia_pd); | 1707 | free(client6_data.ia_pd); |
1709 | client6_data.ia_pd = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_PD); | 1708 | client6_data.ia_pd = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_PD); |
1710 | if (!client6_data.ia_pd) { | 1709 | if (!client6_data.ia_pd) { |
1711 | bb_error_msg("no %s option, ignoring packet", "IA_PD"); | 1710 | bb_info_msg("no %s option, ignoring packet", "IA_PD"); |
1712 | continue; | 1711 | continue; |
1713 | } | 1712 | } |
1714 | if (client6_data.ia_pd->len < (4 + 4 + 4) + (2 + 2 + 4 + 4 + 1 + 16)) { | 1713 | if (client6_data.ia_pd->len < (4 + 4 + 4) + (2 + 2 + 4 + 4 + 1 + 16)) { |
1715 | bb_error_msg("%s option is too short:%d bytes", | 1714 | bb_info_msg("%s option is too short:%d bytes", |
1716 | "IA_PD", client6_data.ia_pd->len); | 1715 | "IA_PD", client6_data.ia_pd->len); |
1717 | continue; | 1716 | continue; |
1718 | } | 1717 | } |
@@ -1721,17 +1720,17 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1721 | D6_OPT_IAPREFIX | 1720 | D6_OPT_IAPREFIX |
1722 | ); | 1721 | ); |
1723 | if (!iaprefix) { | 1722 | if (!iaprefix) { |
1724 | bb_error_msg("no %s option, ignoring packet", "IAPREFIX"); | 1723 | bb_info_msg("no %s option, ignoring packet", "IAPREFIX"); |
1725 | continue; | 1724 | continue; |
1726 | } | 1725 | } |
1727 | if (iaprefix->len < (4 + 4 + 1 + 16)) { | 1726 | if (iaprefix->len < (4 + 4 + 1 + 16)) { |
1728 | bb_error_msg("%s option is too short:%d bytes", | 1727 | bb_info_msg("%s option is too short:%d bytes", |
1729 | "IAPREFIX", iaprefix->len); | 1728 | "IAPREFIX", iaprefix->len); |
1730 | continue; | 1729 | continue; |
1731 | } | 1730 | } |
1732 | move_from_unaligned32(lease_seconds, iaprefix->data + 4); | 1731 | move_from_unaligned32(lease_seconds, iaprefix->data + 4); |
1733 | lease_seconds = ntohl(lease_seconds); | 1732 | lease_seconds = ntohl(lease_seconds); |
1734 | bb_error_msg("%s obtained, lease time %u", | 1733 | bb_info_msg("%s obtained, lease time %u", |
1735 | "prefix", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); | 1734 | "prefix", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); |
1736 | prefix_timeout = lease_seconds; | 1735 | prefix_timeout = lease_seconds; |
1737 | } | 1736 | } |
@@ -1747,9 +1746,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1747 | timeout = 61; | 1746 | timeout = 61; |
1748 | /* enter bound state */ | 1747 | /* enter bound state */ |
1749 | d6_run_script(packet.d6_options, packet_end, | 1748 | d6_run_script(packet.d6_options, packet_end, |
1750 | (state == REQUESTING ? "bound" : "renew")); | 1749 | (client_data.state == REQUESTING ? "bound" : "renew")); |
1751 | 1750 | ||
1752 | state = BOUND; | 1751 | client_data.state = BOUND; |
1753 | change_listen_mode(LISTEN_NONE); | 1752 | change_listen_mode(LISTEN_NONE); |
1754 | if (opt & OPT_q) { /* quit after lease */ | 1753 | if (opt & OPT_q) { /* quit after lease */ |
1755 | goto ret0; | 1754 | goto ret0; |
@@ -1778,7 +1777,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1778 | perform_d6_release(&srv6_buf, requested_ipv6); | 1777 | perform_d6_release(&srv6_buf, requested_ipv6); |
1779 | retval = 0; | 1778 | retval = 0; |
1780 | ret: | 1779 | ret: |
1781 | /*if (client_config.pidfile) - remove_pidfile has its own check */ | 1780 | /*if (client_data.pidfile) - remove_pidfile has its own check */ |
1782 | remove_pidfile(client_config.pidfile); | 1781 | remove_pidfile(client_data.pidfile); |
1783 | return retval; | 1782 | return retval; |
1784 | } | 1783 | } |
diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c index 493943d72..01d1c930b 100644 --- a/networking/udhcp/d6_packet.c +++ b/networking/udhcp/d6_packet.c | |||
@@ -17,7 +17,7 @@ void FAST_FUNC d6_dump_packet(struct d6_packet *packet) | |||
17 | if (dhcp_verbose < 2) | 17 | if (dhcp_verbose < 2) |
18 | return; | 18 | return; |
19 | 19 | ||
20 | bb_error_msg( | 20 | bb_info_msg( |
21 | " xid %x" | 21 | " xid %x" |
22 | , packet->d6_xid32 | 22 | , packet->d6_xid32 |
23 | ); | 23 | ); |
@@ -40,7 +40,7 @@ int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 | |||
40 | } | 40 | } |
41 | 41 | ||
42 | if (bytes < offsetof(struct d6_packet, d6_options)) { | 42 | if (bytes < offsetof(struct d6_packet, d6_options)) { |
43 | bb_error_msg("packet with bad magic, ignoring"); | 43 | bb_info_msg("packet with bad magic, ignoring"); |
44 | return -2; | 44 | return -2; |
45 | } | 45 | } |
46 | log1("received %s", "a packet"); | 46 | log1("received %s", "a packet"); |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index e2fb18aba..cb85fa9e3 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -49,7 +49,7 @@ struct tpacket_auxdata { | |||
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | 51 | ||
52 | /* "struct client_config_t client_config" is in bb_common_bufsiz1 */ | 52 | /* "struct client_data_t client_data" is in bb_common_bufsiz1 */ |
53 | 53 | ||
54 | 54 | ||
55 | #if ENABLE_LONG_OPTS | 55 | #if ENABLE_LONG_OPTS |
@@ -477,7 +477,7 @@ static char **fill_envp(struct dhcp_packet *packet) | |||
477 | } | 477 | } |
478 | curr = envp = xzalloc(sizeof(envp[0]) * envc); | 478 | curr = envp = xzalloc(sizeof(envp[0]) * envc); |
479 | 479 | ||
480 | *curr = xasprintf("interface=%s", client_config.interface); | 480 | *curr = xasprintf("interface=%s", client_data.interface); |
481 | putenv(*curr++); | 481 | putenv(*curr++); |
482 | 482 | ||
483 | if (!packet) | 483 | if (!packet) |
@@ -577,8 +577,8 @@ static void udhcp_run_script(struct dhcp_packet *packet, const char *name) | |||
577 | envp = fill_envp(packet); | 577 | envp = fill_envp(packet); |
578 | 578 | ||
579 | /* call script */ | 579 | /* call script */ |
580 | log1("executing %s %s", client_config.script, name); | 580 | log1("executing %s %s", client_data.script, name); |
581 | argv[0] = (char*) client_config.script; | 581 | argv[0] = (char*) client_data.script; |
582 | argv[1] = (char*) name; | 582 | argv[1] = (char*) name; |
583 | argv[2] = NULL; | 583 | argv[2] = NULL; |
584 | spawn_and_wait(argv); | 584 | spawn_and_wait(argv); |
@@ -608,15 +608,15 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
608 | 608 | ||
609 | packet->xid = random_xid(); | 609 | packet->xid = random_xid(); |
610 | 610 | ||
611 | client_config.last_secs = monotonic_sec(); | 611 | client_data.last_secs = monotonic_sec(); |
612 | if (client_config.first_secs == 0) | 612 | if (client_data.first_secs == 0) |
613 | client_config.first_secs = client_config.last_secs; | 613 | client_data.first_secs = client_data.last_secs; |
614 | secs = client_config.last_secs - client_config.first_secs; | 614 | secs = client_data.last_secs - client_data.first_secs; |
615 | packet->secs = htons(secs); | 615 | packet->secs = htons(secs); |
616 | 616 | ||
617 | memcpy(packet->chaddr, client_config.client_mac, 6); | 617 | memcpy(packet->chaddr, client_data.client_mac, 6); |
618 | if (client_config.clientid) | 618 | if (client_data.clientid) |
619 | udhcp_add_binary_option(packet, client_config.clientid); | 619 | udhcp_add_binary_option(packet, client_data.clientid); |
620 | } | 620 | } |
621 | 621 | ||
622 | static void add_client_options(struct dhcp_packet *packet) | 622 | static void add_client_options(struct dhcp_packet *packet) |
@@ -631,7 +631,7 @@ static void add_client_options(struct dhcp_packet *packet) | |||
631 | end = udhcp_end_option(packet->options); | 631 | end = udhcp_end_option(packet->options); |
632 | len = 0; | 632 | len = 0; |
633 | for (i = 1; i < DHCP_END; i++) { | 633 | for (i = 1; i < DHCP_END; i++) { |
634 | if (client_config.opt_mask[i >> 3] & (1 << (i & 7))) { | 634 | if (client_data.opt_mask[i >> 3] & (1 << (i & 7))) { |
635 | packet->options[end + OPT_DATA + len] = i; | 635 | packet->options[end + OPT_DATA + len] = i; |
636 | len++; | 636 | len++; |
637 | } | 637 | } |
@@ -642,12 +642,12 @@ static void add_client_options(struct dhcp_packet *packet) | |||
642 | packet->options[end + OPT_DATA + len] = DHCP_END; | 642 | packet->options[end + OPT_DATA + len] = DHCP_END; |
643 | } | 643 | } |
644 | 644 | ||
645 | if (client_config.vendorclass) | 645 | if (client_data.vendorclass) |
646 | udhcp_add_binary_option(packet, client_config.vendorclass); | 646 | udhcp_add_binary_option(packet, client_data.vendorclass); |
647 | if (client_config.hostname) | 647 | if (client_data.hostname) |
648 | udhcp_add_binary_option(packet, client_config.hostname); | 648 | udhcp_add_binary_option(packet, client_data.hostname); |
649 | if (client_config.fqdn) | 649 | if (client_data.fqdn) |
650 | udhcp_add_binary_option(packet, client_config.fqdn); | 650 | udhcp_add_binary_option(packet, client_data.fqdn); |
651 | 651 | ||
652 | /* Request broadcast replies if we have no IP addr */ | 652 | /* Request broadcast replies if we have no IP addr */ |
653 | if ((option_mask32 & OPT_B) && packet->ciaddr == 0) | 653 | if ((option_mask32 & OPT_B) && packet->ciaddr == 0) |
@@ -655,15 +655,15 @@ static void add_client_options(struct dhcp_packet *packet) | |||
655 | 655 | ||
656 | /* Add -x options if any */ | 656 | /* Add -x options if any */ |
657 | { | 657 | { |
658 | struct option_set *curr = client_config.options; | 658 | struct option_set *curr = client_data.options; |
659 | while (curr) { | 659 | while (curr) { |
660 | udhcp_add_binary_option(packet, curr->data); | 660 | udhcp_add_binary_option(packet, curr->data); |
661 | curr = curr->next; | 661 | curr = curr->next; |
662 | } | 662 | } |
663 | // if (client_config.sname) | 663 | // if (client_data.sname) |
664 | // strncpy((char*)packet->sname, client_config.sname, sizeof(packet->sname) - 1); | 664 | // strncpy((char*)packet->sname, client_data.sname, sizeof(packet->sname) - 1); |
665 | // if (client_config.boot_file) | 665 | // if (client_data.boot_file) |
666 | // strncpy((char*)packet->file, client_config.boot_file, sizeof(packet->file) - 1); | 666 | // strncpy((char*)packet->file, client_data.boot_file, sizeof(packet->file) - 1); |
667 | } | 667 | } |
668 | 668 | ||
669 | // This will be needed if we remove -V VENDOR_STR in favor of | 669 | // This will be needed if we remove -V VENDOR_STR in favor of |
@@ -691,12 +691,12 @@ static void add_client_options(struct dhcp_packet *packet) | |||
691 | * client reverts to using the IP broadcast address. | 691 | * client reverts to using the IP broadcast address. |
692 | */ | 692 | */ |
693 | 693 | ||
694 | static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint32_t src_nip) | 694 | static int raw_bcast_from_client_data_ifindex(struct dhcp_packet *packet, uint32_t src_nip) |
695 | { | 695 | { |
696 | return udhcp_send_raw_packet(packet, | 696 | return udhcp_send_raw_packet(packet, |
697 | /*src*/ src_nip, CLIENT_PORT, | 697 | /*src*/ src_nip, CLIENT_PORT, |
698 | /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, | 698 | /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, |
699 | client_config.ifindex); | 699 | client_data.ifindex); |
700 | } | 700 | } |
701 | 701 | ||
702 | static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) | 702 | static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) |
@@ -705,7 +705,7 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t | |||
705 | return udhcp_send_kernel_packet(packet, | 705 | return udhcp_send_kernel_packet(packet, |
706 | ciaddr, CLIENT_PORT, | 706 | ciaddr, CLIENT_PORT, |
707 | server, SERVER_PORT); | 707 | server, SERVER_PORT); |
708 | return raw_bcast_from_client_config_ifindex(packet, ciaddr); | 708 | return raw_bcast_from_client_data_ifindex(packet, ciaddr); |
709 | } | 709 | } |
710 | 710 | ||
711 | /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ | 711 | /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ |
@@ -730,8 +730,8 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested) | |||
730 | */ | 730 | */ |
731 | add_client_options(&packet); | 731 | add_client_options(&packet); |
732 | 732 | ||
733 | bb_error_msg("sending %s", "discover"); | 733 | bb_info_msg("sending %s", "discover"); |
734 | return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); | 734 | return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); |
735 | } | 735 | } |
736 | 736 | ||
737 | /* Broadcast a DHCP request message */ | 737 | /* Broadcast a DHCP request message */ |
@@ -774,8 +774,8 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste | |||
774 | add_client_options(&packet); | 774 | add_client_options(&packet); |
775 | 775 | ||
776 | temp_addr.s_addr = requested; | 776 | temp_addr.s_addr = requested; |
777 | bb_error_msg("sending select for %s", inet_ntoa(temp_addr)); | 777 | bb_info_msg("sending select for %s", inet_ntoa(temp_addr)); |
778 | return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); | 778 | return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); |
779 | } | 779 | } |
780 | 780 | ||
781 | /* Unicast or broadcast a DHCP renew message */ | 781 | /* Unicast or broadcast a DHCP renew message */ |
@@ -815,7 +815,7 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
815 | add_client_options(&packet); | 815 | add_client_options(&packet); |
816 | 816 | ||
817 | temp_addr.s_addr = server; | 817 | temp_addr.s_addr = server; |
818 | bb_error_msg("sending renew to %s", inet_ntoa(temp_addr)); | 818 | bb_info_msg("sending renew to %s", inet_ntoa(temp_addr)); |
819 | return bcast_or_ucast(&packet, ciaddr, server); | 819 | return bcast_or_ucast(&packet, ciaddr, server); |
820 | } | 820 | } |
821 | 821 | ||
@@ -844,8 +844,8 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req | |||
844 | 844 | ||
845 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 845 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
846 | 846 | ||
847 | bb_error_msg("sending %s", "decline"); | 847 | bb_info_msg("sending %s", "decline"); |
848 | return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); | 848 | return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); |
849 | } | 849 | } |
850 | #endif | 850 | #endif |
851 | 851 | ||
@@ -866,7 +866,7 @@ int send_release(uint32_t server, uint32_t ciaddr) | |||
866 | 866 | ||
867 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 867 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
868 | 868 | ||
869 | bb_error_msg("sending %s", "release"); | 869 | bb_info_msg("sending %s", "release"); |
870 | /* Note: normally we unicast here since "server" is not zero. | 870 | /* Note: normally we unicast here since "server" is not zero. |
871 | * However, there _are_ people who run "address-less" DHCP servers, | 871 | * However, there _are_ people who run "address-less" DHCP servers, |
872 | * and reportedly ISC dhcp client and Windows allow that. | 872 | * and reportedly ISC dhcp client and Windows allow that. |
@@ -969,7 +969,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
969 | skip_udp_sum_check: | 969 | skip_udp_sum_check: |
970 | 970 | ||
971 | if (packet.data.cookie != htonl(DHCP_MAGIC)) { | 971 | if (packet.data.cookie != htonl(DHCP_MAGIC)) { |
972 | bb_error_msg("packet with bad magic, ignoring"); | 972 | bb_info_msg("packet with bad magic, ignoring"); |
973 | return -2; | 973 | return -2; |
974 | } | 974 | } |
975 | 975 | ||
@@ -984,13 +984,12 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
984 | 984 | ||
985 | /*** Main ***/ | 985 | /*** Main ***/ |
986 | 986 | ||
987 | static int sockfd = -1; | 987 | /* Values for client_data.listen_mode */ |
988 | |||
989 | #define LISTEN_NONE 0 | 988 | #define LISTEN_NONE 0 |
990 | #define LISTEN_KERNEL 1 | 989 | #define LISTEN_KERNEL 1 |
991 | #define LISTEN_RAW 2 | 990 | #define LISTEN_RAW 2 |
992 | static smallint listen_mode; | ||
993 | 991 | ||
992 | /* Values for client_data.state */ | ||
994 | /* initial state: (re)start DHCP negotiation */ | 993 | /* initial state: (re)start DHCP negotiation */ |
995 | #define INIT_SELECTING 0 | 994 | #define INIT_SELECTING 0 |
996 | /* discover was sent, DHCPOFFER reply received */ | 995 | /* discover was sent, DHCPOFFER reply received */ |
@@ -1005,7 +1004,6 @@ static smallint listen_mode; | |||
1005 | #define RENEW_REQUESTED 5 | 1004 | #define RENEW_REQUESTED 5 |
1006 | /* release, possibly manually requested (SIGUSR2) */ | 1005 | /* release, possibly manually requested (SIGUSR2) */ |
1007 | #define RELEASED 6 | 1006 | #define RELEASED 6 |
1008 | static smallint state; | ||
1009 | 1007 | ||
1010 | static int udhcp_raw_socket(int ifindex) | 1008 | static int udhcp_raw_socket(int ifindex) |
1011 | { | 1009 | { |
@@ -1102,35 +1100,35 @@ static void change_listen_mode(int new_mode) | |||
1102 | : "none" | 1100 | : "none" |
1103 | ); | 1101 | ); |
1104 | 1102 | ||
1105 | listen_mode = new_mode; | 1103 | client_data.listen_mode = new_mode; |
1106 | if (sockfd >= 0) { | 1104 | if (client_data.sockfd >= 0) { |
1107 | close(sockfd); | 1105 | close(client_data.sockfd); |
1108 | sockfd = -1; | 1106 | client_data.sockfd = -1; |
1109 | } | 1107 | } |
1110 | if (new_mode == LISTEN_KERNEL) | 1108 | if (new_mode == LISTEN_KERNEL) |
1111 | sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface); | 1109 | client_data.sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_data.interface); |
1112 | else if (new_mode != LISTEN_NONE) | 1110 | else if (new_mode != LISTEN_NONE) |
1113 | sockfd = udhcp_raw_socket(client_config.ifindex); | 1111 | client_data.sockfd = udhcp_raw_socket(client_data.ifindex); |
1114 | /* else LISTEN_NONE: sockfd stays closed */ | 1112 | /* else LISTEN_NONE: client_data.sockfd stays closed */ |
1115 | } | 1113 | } |
1116 | 1114 | ||
1117 | /* Called only on SIGUSR1 */ | 1115 | /* Called only on SIGUSR1 */ |
1118 | static void perform_renew(void) | 1116 | static void perform_renew(void) |
1119 | { | 1117 | { |
1120 | bb_error_msg("performing DHCP renew"); | 1118 | bb_info_msg("performing DHCP renew"); |
1121 | switch (state) { | 1119 | switch (client_data.state) { |
1122 | case BOUND: | 1120 | case BOUND: |
1123 | change_listen_mode(LISTEN_KERNEL); | 1121 | change_listen_mode(LISTEN_KERNEL); |
1124 | case RENEWING: | 1122 | case RENEWING: |
1125 | case REBINDING: | 1123 | case REBINDING: |
1126 | state = RENEW_REQUESTED; | 1124 | client_data.state = RENEW_REQUESTED; |
1127 | break; | 1125 | break; |
1128 | case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ | 1126 | case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ |
1129 | udhcp_run_script(NULL, "deconfig"); | 1127 | udhcp_run_script(NULL, "deconfig"); |
1130 | case REQUESTING: | 1128 | case REQUESTING: |
1131 | case RELEASED: | 1129 | case RELEASED: |
1132 | change_listen_mode(LISTEN_RAW); | 1130 | change_listen_mode(LISTEN_RAW); |
1133 | state = INIT_SELECTING; | 1131 | client_data.state = INIT_SELECTING; |
1134 | break; | 1132 | break; |
1135 | case INIT_SELECTING: | 1133 | case INIT_SELECTING: |
1136 | break; | 1134 | break; |
@@ -1143,19 +1141,19 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip) | |||
1143 | struct in_addr temp_addr; | 1141 | struct in_addr temp_addr; |
1144 | 1142 | ||
1145 | /* send release packet */ | 1143 | /* send release packet */ |
1146 | if (state == BOUND | 1144 | if (client_data.state == BOUND |
1147 | || state == RENEWING | 1145 | || client_data.state == RENEWING |
1148 | || state == REBINDING | 1146 | || client_data.state == REBINDING |
1149 | || state == RENEW_REQUESTED | 1147 | || client_data.state == RENEW_REQUESTED |
1150 | ) { | 1148 | ) { |
1151 | temp_addr.s_addr = server_addr; | 1149 | temp_addr.s_addr = server_addr; |
1152 | strcpy(buffer, inet_ntoa(temp_addr)); | 1150 | strcpy(buffer, inet_ntoa(temp_addr)); |
1153 | temp_addr.s_addr = requested_ip; | 1151 | temp_addr.s_addr = requested_ip; |
1154 | bb_error_msg("unicasting a release of %s to %s", | 1152 | bb_info_msg("unicasting a release of %s to %s", |
1155 | inet_ntoa(temp_addr), buffer); | 1153 | inet_ntoa(temp_addr), buffer); |
1156 | send_release(server_addr, requested_ip); /* unicast */ | 1154 | send_release(server_addr, requested_ip); /* unicast */ |
1157 | } | 1155 | } |
1158 | bb_error_msg("entering released state"); | 1156 | bb_info_msg("entering released state"); |
1159 | /* | 1157 | /* |
1160 | * We can be here on: SIGUSR2, | 1158 | * We can be here on: SIGUSR2, |
1161 | * or on exit (SIGTERM) and -R "release on quit" is specified. | 1159 | * or on exit (SIGTERM) and -R "release on quit" is specified. |
@@ -1165,7 +1163,7 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip) | |||
1165 | udhcp_run_script(NULL, "deconfig"); | 1163 | udhcp_run_script(NULL, "deconfig"); |
1166 | 1164 | ||
1167 | change_listen_mode(LISTEN_NONE); | 1165 | change_listen_mode(LISTEN_NONE); |
1168 | state = RELEASED; | 1166 | client_data.state = RELEASED; |
1169 | } | 1167 | } |
1170 | 1168 | ||
1171 | static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) | 1169 | static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) |
@@ -1185,7 +1183,7 @@ static void client_background(void) | |||
1185 | bb_daemonize(0); | 1183 | bb_daemonize(0); |
1186 | logmode &= ~LOGMODE_STDIO; | 1184 | logmode &= ~LOGMODE_STDIO; |
1187 | /* rewrite pidfile, as our pid is different now */ | 1185 | /* rewrite pidfile, as our pid is different now */ |
1188 | write_pidfile(client_config.pidfile); | 1186 | write_pidfile(client_data.pidfile); |
1189 | } | 1187 | } |
1190 | #endif | 1188 | #endif |
1191 | 1189 | ||
@@ -1268,8 +1266,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1268 | /* Default options */ | 1266 | /* Default options */ |
1269 | IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) | 1267 | IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) |
1270 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) | 1268 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) |
1271 | client_config.interface = "eth0"; | 1269 | client_data.interface = "eth0"; |
1272 | client_config.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; | 1270 | client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; |
1271 | client_data.sockfd = -1; | ||
1273 | str_V = "udhcp "BB_VER; | 1272 | str_V = "udhcp "BB_VER; |
1274 | 1273 | ||
1275 | /* Parse command line */ | 1274 | /* Parse command line */ |
@@ -1283,9 +1282,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1283 | "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */ | 1282 | "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */ |
1284 | , udhcpc_longopts | 1283 | , udhcpc_longopts |
1285 | , &str_V, &str_h, &str_h, &str_F | 1284 | , &str_V, &str_h, &str_h, &str_F |
1286 | , &client_config.interface, &client_config.pidfile /* i,p */ | 1285 | , &client_data.interface, &client_data.pidfile /* i,p */ |
1287 | , &str_r /* r */ | 1286 | , &str_r /* r */ |
1288 | , &client_config.script /* s */ | 1287 | , &client_data.script /* s */ |
1289 | , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ | 1288 | , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ |
1290 | , &list_O | 1289 | , &list_O |
1291 | , &list_x | 1290 | , &list_x |
@@ -1296,11 +1295,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1296 | if (opt & (OPT_h|OPT_H)) { | 1295 | if (opt & (OPT_h|OPT_H)) { |
1297 | //msg added 2011-11 | 1296 | //msg added 2011-11 |
1298 | bb_error_msg("option -h NAME is deprecated, use -x hostname:NAME"); | 1297 | bb_error_msg("option -h NAME is deprecated, use -x hostname:NAME"); |
1299 | client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); | 1298 | client_data.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); |
1300 | } | 1299 | } |
1301 | if (opt & OPT_F) { | 1300 | if (opt & OPT_F) { |
1302 | /* FQDN option format: [0x51][len][flags][0][0]<fqdn> */ | 1301 | /* FQDN option format: [0x51][len][flags][0][0]<fqdn> */ |
1303 | client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3); | 1302 | client_data.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3); |
1304 | /* Flag bits: 0000NEOS | 1303 | /* Flag bits: 0000NEOS |
1305 | * S: 1 = Client requests server to update A RR in DNS as well as PTR | 1304 | * S: 1 = Client requests server to update A RR in DNS as well as PTR |
1306 | * O: 1 = Server indicates to client that DNS has been updated regardless | 1305 | * O: 1 = Server indicates to client that DNS has been updated regardless |
@@ -1309,9 +1308,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1309 | * N: 1 = Client requests server to not update DNS (S must be 0 then) | 1308 | * N: 1 = Client requests server to not update DNS (S must be 0 then) |
1310 | * Two [0] bytes which follow are deprecated and must be 0. | 1309 | * Two [0] bytes which follow are deprecated and must be 0. |
1311 | */ | 1310 | */ |
1312 | client_config.fqdn[OPT_DATA + 0] = 0x1; | 1311 | client_data.fqdn[OPT_DATA + 0] = 0x1; |
1313 | /*client_config.fqdn[OPT_DATA + 1] = 0; - xzalloc did it */ | 1312 | /*client_data.fqdn[OPT_DATA + 1] = 0; - xzalloc did it */ |
1314 | /*client_config.fqdn[OPT_DATA + 2] = 0; */ | 1313 | /*client_data.fqdn[OPT_DATA + 2] = 0; */ |
1315 | } | 1314 | } |
1316 | if (opt & OPT_r) | 1315 | if (opt & OPT_r) |
1317 | requested_ip = inet_addr(str_r); | 1316 | requested_ip = inet_addr(str_r); |
@@ -1329,49 +1328,49 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1329 | n = udhcp_option_idx(optstr, dhcp_option_strings); | 1328 | n = udhcp_option_idx(optstr, dhcp_option_strings); |
1330 | n = dhcp_optflags[n].code; | 1329 | n = dhcp_optflags[n].code; |
1331 | } | 1330 | } |
1332 | client_config.opt_mask[n >> 3] |= 1 << (n & 7); | 1331 | client_data.opt_mask[n >> 3] |= 1 << (n & 7); |
1333 | } | 1332 | } |
1334 | if (!(opt & OPT_o)) { | 1333 | if (!(opt & OPT_o)) { |
1335 | unsigned i, n; | 1334 | unsigned i, n; |
1336 | for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) { | 1335 | for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) { |
1337 | if (dhcp_optflags[i].flags & OPTION_REQ) { | 1336 | if (dhcp_optflags[i].flags & OPTION_REQ) { |
1338 | client_config.opt_mask[n >> 3] |= 1 << (n & 7); | 1337 | client_data.opt_mask[n >> 3] |= 1 << (n & 7); |
1339 | } | 1338 | } |
1340 | } | 1339 | } |
1341 | } | 1340 | } |
1342 | while (list_x) { | 1341 | while (list_x) { |
1343 | char *optstr = xstrdup(llist_pop(&list_x)); | 1342 | char *optstr = xstrdup(llist_pop(&list_x)); |
1344 | udhcp_str2optset(optstr, &client_config.options, | 1343 | udhcp_str2optset(optstr, &client_data.options, |
1345 | dhcp_optflags, dhcp_option_strings, | 1344 | dhcp_optflags, dhcp_option_strings, |
1346 | /*dhcpv6:*/ 0 | 1345 | /*dhcpv6:*/ 0 |
1347 | ); | 1346 | ); |
1348 | free(optstr); | 1347 | free(optstr); |
1349 | } | 1348 | } |
1350 | 1349 | ||
1351 | if (udhcp_read_interface(client_config.interface, | 1350 | if (udhcp_read_interface(client_data.interface, |
1352 | &client_config.ifindex, | 1351 | &client_data.ifindex, |
1353 | NULL, | 1352 | NULL, |
1354 | client_config.client_mac) | 1353 | client_data.client_mac) |
1355 | ) { | 1354 | ) { |
1356 | return 1; | 1355 | return 1; |
1357 | } | 1356 | } |
1358 | 1357 | ||
1359 | clientid_mac_ptr = NULL; | 1358 | clientid_mac_ptr = NULL; |
1360 | if (!(opt & OPT_C) && !udhcp_find_option(client_config.options, DHCP_CLIENT_ID)) { | 1359 | if (!(opt & OPT_C) && !udhcp_find_option(client_data.options, DHCP_CLIENT_ID)) { |
1361 | /* not suppressed and not set, set the default client ID */ | 1360 | /* not suppressed and not set, set the default client ID */ |
1362 | client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); | 1361 | client_data.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); |
1363 | client_config.clientid[OPT_DATA] = 1; /* type: ethernet */ | 1362 | client_data.clientid[OPT_DATA] = 1; /* type: ethernet */ |
1364 | clientid_mac_ptr = client_config.clientid + OPT_DATA+1; | 1363 | clientid_mac_ptr = client_data.clientid + OPT_DATA+1; |
1365 | memcpy(clientid_mac_ptr, client_config.client_mac, 6); | 1364 | memcpy(clientid_mac_ptr, client_data.client_mac, 6); |
1366 | } | 1365 | } |
1367 | if (str_V[0] != '\0') { | 1366 | if (str_V[0] != '\0') { |
1368 | // can drop -V, str_V, client_config.vendorclass, | 1367 | // can drop -V, str_V, client_data.vendorclass, |
1369 | // but need to add "vendor" to the list of recognized | 1368 | // but need to add "vendor" to the list of recognized |
1370 | // string opts for this to work; | 1369 | // string opts for this to work; |
1371 | // and need to tweak add_client_options() too... | 1370 | // and need to tweak add_client_options() too... |
1372 | // ...so the question is, should we? | 1371 | // ...so the question is, should we? |
1373 | //bb_error_msg("option -V VENDOR is deprecated, use -x vendor:VENDOR"); | 1372 | //bb_error_msg("option -V VENDOR is deprecated, use -x vendor:VENDOR"); |
1374 | client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); | 1373 | client_data.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); |
1375 | } | 1374 | } |
1376 | 1375 | ||
1377 | #if !BB_MMU | 1376 | #if !BB_MMU |
@@ -1389,15 +1388,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1389 | /* Make sure fd 0,1,2 are open */ | 1388 | /* Make sure fd 0,1,2 are open */ |
1390 | bb_sanitize_stdio(); | 1389 | bb_sanitize_stdio(); |
1391 | /* Create pidfile */ | 1390 | /* Create pidfile */ |
1392 | write_pidfile(client_config.pidfile); | 1391 | write_pidfile(client_data.pidfile); |
1393 | /* Goes to stdout (unless NOMMU) and possibly syslog */ | 1392 | /* Goes to stdout (unless NOMMU) and possibly syslog */ |
1394 | bb_error_msg("started, v"BB_VER); | 1393 | bb_info_msg("started, v"BB_VER); |
1395 | /* Set up the signal pipe */ | 1394 | /* Set up the signal pipe */ |
1396 | udhcp_sp_setup(); | 1395 | udhcp_sp_setup(); |
1397 | /* We want random_xid to be random... */ | 1396 | /* We want random_xid to be random... */ |
1398 | srand(monotonic_us()); | 1397 | srand(monotonic_us()); |
1399 | 1398 | ||
1400 | state = INIT_SELECTING; | 1399 | client_data.state = INIT_SELECTING; |
1401 | udhcp_run_script(NULL, "deconfig"); | 1400 | udhcp_run_script(NULL, "deconfig"); |
1402 | change_listen_mode(LISTEN_RAW); | 1401 | change_listen_mode(LISTEN_RAW); |
1403 | packet_num = 0; | 1402 | packet_num = 0; |
@@ -1415,16 +1414,16 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1415 | /* silence "uninitialized!" warning */ | 1414 | /* silence "uninitialized!" warning */ |
1416 | unsigned timestamp_before_wait = timestamp_before_wait; | 1415 | unsigned timestamp_before_wait = timestamp_before_wait; |
1417 | 1416 | ||
1418 | //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode); | 1417 | //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode); |
1419 | 1418 | ||
1420 | /* Was opening raw or udp socket here | 1419 | /* Was opening raw or udp socket here |
1421 | * if (listen_mode != LISTEN_NONE && sockfd < 0), | 1420 | * if (client_data.listen_mode != LISTEN_NONE && client_data.sockfd < 0), |
1422 | * but on fast network renew responses return faster | 1421 | * but on fast network renew responses return faster |
1423 | * than we open sockets. Thus this code is moved | 1422 | * than we open sockets. Thus this code is moved |
1424 | * to change_listen_mode(). Thus we open listen socket | 1423 | * to change_listen_mode(). Thus we open listen socket |
1425 | * BEFORE we send renew request (see "case BOUND:"). */ | 1424 | * BEFORE we send renew request (see "case BOUND:"). */ |
1426 | 1425 | ||
1427 | udhcp_sp_fd_set(pfds, sockfd); | 1426 | udhcp_sp_fd_set(pfds, client_data.sockfd); |
1428 | 1427 | ||
1429 | tv = timeout - already_waited_sec; | 1428 | tv = timeout - already_waited_sec; |
1430 | retval = 0; | 1429 | retval = 0; |
@@ -1453,20 +1452,20 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1453 | * or if the status of the bridge changed). | 1452 | * or if the status of the bridge changed). |
1454 | * Refresh ifindex and client_mac: | 1453 | * Refresh ifindex and client_mac: |
1455 | */ | 1454 | */ |
1456 | if (udhcp_read_interface(client_config.interface, | 1455 | if (udhcp_read_interface(client_data.interface, |
1457 | &client_config.ifindex, | 1456 | &client_data.ifindex, |
1458 | NULL, | 1457 | NULL, |
1459 | client_config.client_mac) | 1458 | client_data.client_mac) |
1460 | ) { | 1459 | ) { |
1461 | goto ret0; /* iface is gone? */ | 1460 | goto ret0; /* iface is gone? */ |
1462 | } | 1461 | } |
1463 | if (clientid_mac_ptr) | 1462 | if (clientid_mac_ptr) |
1464 | memcpy(clientid_mac_ptr, client_config.client_mac, 6); | 1463 | memcpy(clientid_mac_ptr, client_data.client_mac, 6); |
1465 | 1464 | ||
1466 | /* We will restart the wait in any case */ | 1465 | /* We will restart the wait in any case */ |
1467 | already_waited_sec = 0; | 1466 | already_waited_sec = 0; |
1468 | 1467 | ||
1469 | switch (state) { | 1468 | switch (client_data.state) { |
1470 | case INIT_SELECTING: | 1469 | case INIT_SELECTING: |
1471 | if (!discover_retries || packet_num < discover_retries) { | 1470 | if (!discover_retries || packet_num < discover_retries) { |
1472 | if (packet_num == 0) | 1471 | if (packet_num == 0) |
@@ -1481,7 +1480,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1481 | udhcp_run_script(NULL, "leasefail"); | 1480 | udhcp_run_script(NULL, "leasefail"); |
1482 | #if BB_MMU /* -b is not supported on NOMMU */ | 1481 | #if BB_MMU /* -b is not supported on NOMMU */ |
1483 | if (opt & OPT_b) { /* background if no lease */ | 1482 | if (opt & OPT_b) { /* background if no lease */ |
1484 | bb_error_msg("no lease, forking to background"); | 1483 | bb_info_msg("no lease, forking to background"); |
1485 | client_background(); | 1484 | client_background(); |
1486 | /* do not background again! */ | 1485 | /* do not background again! */ |
1487 | opt = ((opt & ~(OPT_b|OPT_n)) | OPT_f); | 1486 | opt = ((opt & ~(OPT_b|OPT_n)) | OPT_f); |
@@ -1494,7 +1493,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1494 | } else | 1493 | } else |
1495 | #endif | 1494 | #endif |
1496 | if (opt & OPT_n) { /* abort if no lease */ | 1495 | if (opt & OPT_n) { /* abort if no lease */ |
1497 | bb_error_msg("no lease, failing"); | 1496 | bb_info_msg("no lease, failing"); |
1498 | retval = 1; | 1497 | retval = 1; |
1499 | goto ret; | 1498 | goto ret; |
1500 | } | 1499 | } |
@@ -1515,12 +1514,12 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1515 | * were seen in the wild. Treat them similarly | 1514 | * were seen in the wild. Treat them similarly |
1516 | * to "no response to discover" case */ | 1515 | * to "no response to discover" case */ |
1517 | change_listen_mode(LISTEN_RAW); | 1516 | change_listen_mode(LISTEN_RAW); |
1518 | state = INIT_SELECTING; | 1517 | client_data.state = INIT_SELECTING; |
1519 | goto leasefail; | 1518 | goto leasefail; |
1520 | case BOUND: | 1519 | case BOUND: |
1521 | /* 1/2 lease passed, enter renewing state */ | 1520 | /* 1/2 lease passed, enter renewing state */ |
1522 | state = RENEWING; | 1521 | client_data.state = RENEWING; |
1523 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1522 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1524 | change_listen_mode(LISTEN_KERNEL); | 1523 | change_listen_mode(LISTEN_KERNEL); |
1525 | log1("entering renew state"); | 1524 | log1("entering renew state"); |
1526 | /* fall right through */ | 1525 | /* fall right through */ |
@@ -1556,7 +1555,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1556 | } | 1555 | } |
1557 | /* Timed out or error, enter rebinding state */ | 1556 | /* Timed out or error, enter rebinding state */ |
1558 | log1("entering rebinding state"); | 1557 | log1("entering rebinding state"); |
1559 | state = REBINDING; | 1558 | client_data.state = REBINDING; |
1560 | /* fall right through */ | 1559 | /* fall right through */ |
1561 | case REBINDING: | 1560 | case REBINDING: |
1562 | /* Switch to bcast receive */ | 1561 | /* Switch to bcast receive */ |
@@ -1570,10 +1569,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1570 | continue; | 1569 | continue; |
1571 | } | 1570 | } |
1572 | /* Timed out, enter init state */ | 1571 | /* Timed out, enter init state */ |
1573 | bb_error_msg("lease lost, entering init state"); | 1572 | bb_info_msg("lease lost, entering init state"); |
1574 | udhcp_run_script(NULL, "deconfig"); | 1573 | udhcp_run_script(NULL, "deconfig"); |
1575 | state = INIT_SELECTING; | 1574 | client_data.state = INIT_SELECTING; |
1576 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1575 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1577 | /*timeout = 0; - already is */ | 1576 | /*timeout = 0; - already is */ |
1578 | packet_num = 0; | 1577 | packet_num = 0; |
1579 | continue; | 1578 | continue; |
@@ -1589,10 +1588,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1589 | /* Is it a signal? */ | 1588 | /* Is it a signal? */ |
1590 | switch (udhcp_sp_read()) { | 1589 | switch (udhcp_sp_read()) { |
1591 | case SIGUSR1: | 1590 | case SIGUSR1: |
1592 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1591 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1593 | already_waited_sec = 0; | 1592 | already_waited_sec = 0; |
1594 | perform_renew(); | 1593 | perform_renew(); |
1595 | if (state == RENEW_REQUESTED) { | 1594 | if (client_data.state == RENEW_REQUESTED) { |
1596 | /* We might be either on the same network | 1595 | /* We might be either on the same network |
1597 | * (in which case renew might work), | 1596 | * (in which case renew might work), |
1598 | * or we might be on a completely different one | 1597 | * or we might be on a completely different one |
@@ -1615,7 +1614,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1615 | timeout = INT_MAX; | 1614 | timeout = INT_MAX; |
1616 | continue; | 1615 | continue; |
1617 | case SIGTERM: | 1616 | case SIGTERM: |
1618 | bb_error_msg("received %s", "SIGTERM"); | 1617 | bb_info_msg("received %s", "SIGTERM"); |
1619 | goto ret0; | 1618 | goto ret0; |
1620 | } | 1619 | } |
1621 | 1620 | ||
@@ -1627,15 +1626,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1627 | int len; | 1626 | int len; |
1628 | 1627 | ||
1629 | /* A packet is ready, read it */ | 1628 | /* A packet is ready, read it */ |
1630 | if (listen_mode == LISTEN_KERNEL) | 1629 | if (client_data.listen_mode == LISTEN_KERNEL) |
1631 | len = udhcp_recv_kernel_packet(&packet, sockfd); | 1630 | len = udhcp_recv_kernel_packet(&packet, client_data.sockfd); |
1632 | else | 1631 | else |
1633 | len = udhcp_recv_raw_packet(&packet, sockfd); | 1632 | len = udhcp_recv_raw_packet(&packet, client_data.sockfd); |
1634 | if (len == -1) { | 1633 | if (len == -1) { |
1635 | /* Error is severe, reopen socket */ | 1634 | /* Error is severe, reopen socket */ |
1636 | bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO); | 1635 | bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO); |
1637 | sleep(discover_timeout); /* 3 seconds by default */ | 1636 | sleep(discover_timeout); /* 3 seconds by default */ |
1638 | change_listen_mode(listen_mode); /* just close and reopen */ | 1637 | change_listen_mode(client_data.listen_mode); /* just close and reopen */ |
1639 | } | 1638 | } |
1640 | /* If this packet will turn out to be unrelated/bogus, | 1639 | /* If this packet will turn out to be unrelated/bogus, |
1641 | * we will go back and wait for next one. | 1640 | * we will go back and wait for next one. |
@@ -1653,7 +1652,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1653 | 1652 | ||
1654 | /* Ignore packets that aren't for us */ | 1653 | /* Ignore packets that aren't for us */ |
1655 | if (packet.hlen != 6 | 1654 | if (packet.hlen != 6 |
1656 | || memcmp(packet.chaddr, client_config.client_mac, 6) != 0 | 1655 | || memcmp(packet.chaddr, client_data.client_mac, 6) != 0 |
1657 | ) { | 1656 | ) { |
1658 | //FIXME: need to also check that last 10 bytes are zero | 1657 | //FIXME: need to also check that last 10 bytes are zero |
1659 | log1("chaddr does not match, ignoring packet"); // log2? | 1658 | log1("chaddr does not match, ignoring packet"); // log2? |
@@ -1662,11 +1661,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1662 | 1661 | ||
1663 | message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); | 1662 | message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); |
1664 | if (message == NULL) { | 1663 | if (message == NULL) { |
1665 | bb_error_msg("no message type option, ignoring packet"); | 1664 | bb_info_msg("no message type option, ignoring packet"); |
1666 | continue; | 1665 | continue; |
1667 | } | 1666 | } |
1668 | 1667 | ||
1669 | switch (state) { | 1668 | switch (client_data.state) { |
1670 | case INIT_SELECTING: | 1669 | case INIT_SELECTING: |
1671 | /* Must be a DHCPOFFER */ | 1670 | /* Must be a DHCPOFFER */ |
1672 | if (*message == DHCPOFFER) { | 1671 | if (*message == DHCPOFFER) { |
@@ -1691,7 +1690,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1691 | * might work too. | 1690 | * might work too. |
1692 | * "Next server" and router are definitely wrong ones to use, though... | 1691 | * "Next server" and router are definitely wrong ones to use, though... |
1693 | */ | 1692 | */ |
1694 | /* We used to ignore pcakets without DHCP_SERVER_ID. | 1693 | /* We used to ignore packets without DHCP_SERVER_ID. |
1695 | * I've got user reports from people who run "address-less" servers. | 1694 | * I've got user reports from people who run "address-less" servers. |
1696 | * They either supply DHCP_SERVER_ID of 0.0.0.0 or don't supply it at all. | 1695 | * They either supply DHCP_SERVER_ID of 0.0.0.0 or don't supply it at all. |
1697 | * They say ISC DHCP client supports this case. | 1696 | * They say ISC DHCP client supports this case. |
@@ -1699,7 +1698,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1699 | server_addr = 0; | 1698 | server_addr = 0; |
1700 | temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); | 1699 | temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); |
1701 | if (!temp) { | 1700 | if (!temp) { |
1702 | bb_error_msg("no server ID, using 0.0.0.0"); | 1701 | bb_info_msg("no server ID, using 0.0.0.0"); |
1703 | } else { | 1702 | } else { |
1704 | /* it IS unaligned sometimes, don't "optimize" */ | 1703 | /* it IS unaligned sometimes, don't "optimize" */ |
1705 | move_from_unaligned32(server_addr, temp); | 1704 | move_from_unaligned32(server_addr, temp); |
@@ -1708,7 +1707,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1708 | requested_ip = packet.yiaddr; | 1707 | requested_ip = packet.yiaddr; |
1709 | 1708 | ||
1710 | /* enter requesting state */ | 1709 | /* enter requesting state */ |
1711 | state = REQUESTING; | 1710 | client_data.state = REQUESTING; |
1712 | timeout = 0; | 1711 | timeout = 0; |
1713 | packet_num = 0; | 1712 | packet_num = 0; |
1714 | already_waited_sec = 0; | 1713 | already_waited_sec = 0; |
@@ -1726,7 +1725,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1726 | 1725 | ||
1727 | temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); | 1726 | temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); |
1728 | if (!temp) { | 1727 | if (!temp) { |
1729 | bb_error_msg("no lease time with ACK, using 1 hour lease"); | 1728 | bb_info_msg("no lease time with ACK, using 1 hour lease"); |
1730 | lease_seconds = 60 * 60; | 1729 | lease_seconds = 60 * 60; |
1731 | } else { | 1730 | } else { |
1732 | /* it IS unaligned sometimes, don't "optimize" */ | 1731 | /* it IS unaligned sometimes, don't "optimize" */ |
@@ -1755,19 +1754,19 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1755 | if (!arpping(packet.yiaddr, | 1754 | if (!arpping(packet.yiaddr, |
1756 | NULL, | 1755 | NULL, |
1757 | (uint32_t) 0, | 1756 | (uint32_t) 0, |
1758 | client_config.client_mac, | 1757 | client_data.client_mac, |
1759 | client_config.interface, | 1758 | client_data.interface, |
1760 | arpping_ms) | 1759 | arpping_ms) |
1761 | ) { | 1760 | ) { |
1762 | bb_error_msg("offered address is in use " | 1761 | bb_info_msg("offered address is in use " |
1763 | "(got ARP reply), declining"); | 1762 | "(got ARP reply), declining"); |
1764 | send_decline(/*xid,*/ server_addr, packet.yiaddr); | 1763 | send_decline(/*xid,*/ server_addr, packet.yiaddr); |
1765 | 1764 | ||
1766 | if (state != REQUESTING) | 1765 | if (client_data.state != REQUESTING) |
1767 | udhcp_run_script(NULL, "deconfig"); | 1766 | udhcp_run_script(NULL, "deconfig"); |
1768 | change_listen_mode(LISTEN_RAW); | 1767 | change_listen_mode(LISTEN_RAW); |
1769 | state = INIT_SELECTING; | 1768 | client_data.state = INIT_SELECTING; |
1770 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1769 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1771 | requested_ip = 0; | 1770 | requested_ip = 0; |
1772 | timeout = tryagain_timeout; | 1771 | timeout = tryagain_timeout; |
1773 | packet_num = 0; | 1772 | packet_num = 0; |
@@ -1778,12 +1777,12 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1778 | #endif | 1777 | #endif |
1779 | /* enter bound state */ | 1778 | /* enter bound state */ |
1780 | temp_addr.s_addr = packet.yiaddr; | 1779 | temp_addr.s_addr = packet.yiaddr; |
1781 | bb_error_msg("lease of %s obtained, lease time %u", | 1780 | bb_info_msg("lease of %s obtained, lease time %u", |
1782 | inet_ntoa(temp_addr), (unsigned)lease_seconds); | 1781 | inet_ntoa(temp_addr), (unsigned)lease_seconds); |
1783 | requested_ip = packet.yiaddr; | 1782 | requested_ip = packet.yiaddr; |
1784 | 1783 | ||
1785 | start = monotonic_sec(); | 1784 | start = monotonic_sec(); |
1786 | udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew"); | 1785 | udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew"); |
1787 | already_waited_sec = (unsigned)monotonic_sec() - start; | 1786 | already_waited_sec = (unsigned)monotonic_sec() - start; |
1788 | timeout = lease_seconds / 2; | 1787 | timeout = lease_seconds / 2; |
1789 | if ((unsigned)timeout < already_waited_sec) { | 1788 | if ((unsigned)timeout < already_waited_sec) { |
@@ -1791,7 +1790,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1791 | timeout = already_waited_sec = 0; | 1790 | timeout = already_waited_sec = 0; |
1792 | } | 1791 | } |
1793 | 1792 | ||
1794 | state = BOUND; | 1793 | client_data.state = BOUND; |
1795 | change_listen_mode(LISTEN_NONE); | 1794 | change_listen_mode(LISTEN_NONE); |
1796 | if (opt & OPT_q) { /* quit after lease */ | 1795 | if (opt & OPT_q) { /* quit after lease */ |
1797 | goto ret0; | 1796 | goto ret0; |
@@ -1831,14 +1830,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1831 | goto non_matching_svid; | 1830 | goto non_matching_svid; |
1832 | } | 1831 | } |
1833 | /* return to init state */ | 1832 | /* return to init state */ |
1834 | bb_error_msg("received %s", "DHCP NAK"); | 1833 | bb_info_msg("received %s", "DHCP NAK"); |
1835 | udhcp_run_script(&packet, "nak"); | 1834 | udhcp_run_script(&packet, "nak"); |
1836 | if (state != REQUESTING) | 1835 | if (client_data.state != REQUESTING) |
1837 | udhcp_run_script(NULL, "deconfig"); | 1836 | udhcp_run_script(NULL, "deconfig"); |
1838 | change_listen_mode(LISTEN_RAW); | 1837 | change_listen_mode(LISTEN_RAW); |
1839 | sleep(3); /* avoid excessive network traffic */ | 1838 | sleep(3); /* avoid excessive network traffic */ |
1840 | state = INIT_SELECTING; | 1839 | client_data.state = INIT_SELECTING; |
1841 | client_config.first_secs = 0; /* make secs field count from 0 */ | 1840 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1842 | requested_ip = 0; | 1841 | requested_ip = 0; |
1843 | timeout = 0; | 1842 | timeout = 0; |
1844 | packet_num = 0; | 1843 | packet_num = 0; |
@@ -1856,7 +1855,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1856 | perform_release(server_addr, requested_ip); | 1855 | perform_release(server_addr, requested_ip); |
1857 | retval = 0; | 1856 | retval = 0; |
1858 | ret: | 1857 | ret: |
1859 | /*if (client_config.pidfile) - remove_pidfile has its own check */ | 1858 | /*if (client_data.pidfile) - remove_pidfile has its own check */ |
1860 | remove_pidfile(client_config.pidfile); | 1859 | remove_pidfile(client_data.pidfile); |
1861 | return retval; | 1860 | return retval; |
1862 | } | 1861 | } |
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h index 7fdbc9a6c..42fe71a36 100644 --- a/networking/udhcp/dhcpc.h +++ b/networking/udhcp/dhcpc.h | |||
@@ -7,7 +7,7 @@ | |||
7 | 7 | ||
8 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 8 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
9 | 9 | ||
10 | struct client_config_t { | 10 | struct client_data_t { |
11 | uint8_t client_mac[6]; /* Our mac address */ | 11 | uint8_t client_mac[6]; /* Our mac address */ |
12 | IF_FEATURE_UDHCP_PORT(uint16_t port;) | 12 | IF_FEATURE_UDHCP_PORT(uint16_t port;) |
13 | int ifindex; /* Index number of the interface to use */ | 13 | int ifindex; /* Index number of the interface to use */ |
@@ -24,14 +24,18 @@ struct client_config_t { | |||
24 | 24 | ||
25 | uint16_t first_secs; | 25 | uint16_t first_secs; |
26 | uint16_t last_secs; | 26 | uint16_t last_secs; |
27 | |||
28 | int sockfd; | ||
29 | smallint listen_mode; | ||
30 | smallint state; | ||
27 | } FIX_ALIASING; | 31 | } FIX_ALIASING; |
28 | 32 | ||
29 | /* server_config sits in 1st half of bb_common_bufsiz1 */ | 33 | /* server_config sits in 1st half of bb_common_bufsiz1 */ |
30 | #define client_config (*(struct client_config_t*)(&bb_common_bufsiz1[COMMON_BUFSIZE / 2])) | 34 | #define client_data (*(struct client_data_t*)(&bb_common_bufsiz1[COMMON_BUFSIZE / 2])) |
31 | 35 | ||
32 | #if ENABLE_FEATURE_UDHCP_PORT | 36 | #if ENABLE_FEATURE_UDHCP_PORT |
33 | #define CLIENT_PORT (client_config.port) | 37 | #define CLIENT_PORT (client_data.port) |
34 | #define CLIENT_PORT6 (client_config.port) | 38 | #define CLIENT_PORT6 (client_data.port) |
35 | #else | 39 | #else |
36 | #define CLIENT_PORT 68 | 40 | #define CLIENT_PORT 68 |
37 | #define CLIENT_PORT6 546 | 41 | #define CLIENT_PORT6 546 |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 0c55fa5e4..058f86bca 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -48,14 +48,25 @@ | |||
48 | #define g_leases ((struct dyn_lease*)ptr_to_globals) | 48 | #define g_leases ((struct dyn_lease*)ptr_to_globals) |
49 | /* struct server_config_t server_config is in bb_common_bufsiz1 */ | 49 | /* struct server_config_t server_config is in bb_common_bufsiz1 */ |
50 | 50 | ||
51 | struct static_lease { | ||
52 | struct static_lease *next; | ||
53 | uint32_t nip; | ||
54 | uint8_t mac[6]; | ||
55 | uint8_t opt[1]; | ||
56 | }; | ||
57 | |||
51 | /* Takes the address of the pointer to the static_leases linked list, | 58 | /* Takes the address of the pointer to the static_leases linked list, |
52 | * address to a 6 byte mac address, | 59 | * address to a 6 byte mac address, |
53 | * 4 byte IP address */ | 60 | * 4 byte IP address */ |
54 | static void add_static_lease(struct static_lease **st_lease_pp, | 61 | static void add_static_lease(struct static_lease **st_lease_pp, |
55 | uint8_t *mac, | 62 | uint8_t *mac, |
56 | uint32_t nip) | 63 | uint32_t nip, |
64 | const char *opts) | ||
57 | { | 65 | { |
58 | struct static_lease *st_lease; | 66 | struct static_lease *st_lease; |
67 | unsigned optlen; | ||
68 | |||
69 | optlen = (opts ? 1+1+strnlen(opts, 120) : 0); | ||
59 | 70 | ||
60 | /* Find the tail of the list */ | 71 | /* Find the tail of the list */ |
61 | while ((st_lease = *st_lease_pp) != NULL) { | 72 | while ((st_lease = *st_lease_pp) != NULL) { |
@@ -63,15 +74,34 @@ static void add_static_lease(struct static_lease **st_lease_pp, | |||
63 | } | 74 | } |
64 | 75 | ||
65 | /* Add new node */ | 76 | /* Add new node */ |
66 | *st_lease_pp = st_lease = xzalloc(sizeof(*st_lease)); | 77 | *st_lease_pp = st_lease = xzalloc(sizeof(*st_lease) + optlen); |
67 | memcpy(st_lease->mac, mac, 6); | 78 | memcpy(st_lease->mac, mac, 6); |
68 | st_lease->nip = nip; | 79 | st_lease->nip = nip; |
69 | /*st_lease->next = NULL;*/ | 80 | /*st_lease->next = NULL;*/ |
81 | if (optlen) { | ||
82 | st_lease->opt[OPT_CODE] = DHCP_HOST_NAME; | ||
83 | optlen -= 2; | ||
84 | st_lease->opt[OPT_LEN] = optlen; | ||
85 | memcpy(&st_lease->opt[OPT_DATA], opts, optlen); | ||
86 | } | ||
87 | |||
88 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 | ||
89 | /* Print out static leases just to check what's going on */ | ||
90 | if (dhcp_verbose >= 2) { | ||
91 | bb_info_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x", | ||
92 | st_lease->mac[0], st_lease->mac[1], st_lease->mac[2], | ||
93 | st_lease->mac[3], st_lease->mac[4], st_lease->mac[5], | ||
94 | st_lease->nip | ||
95 | ); | ||
96 | } | ||
97 | #endif | ||
70 | } | 98 | } |
71 | 99 | ||
72 | /* Find static lease IP by mac */ | 100 | /* Find static lease IP by mac */ |
73 | static uint32_t get_static_nip_by_mac(struct static_lease *st_lease, void *mac) | 101 | static uint32_t get_static_nip_by_mac(void *mac) |
74 | { | 102 | { |
103 | struct static_lease *st_lease = server_config.static_leases; | ||
104 | |||
75 | while (st_lease) { | 105 | while (st_lease) { |
76 | if (memcmp(st_lease->mac, mac, 6) == 0) | 106 | if (memcmp(st_lease->mac, mac, 6) == 0) |
77 | return st_lease->nip; | 107 | return st_lease->nip; |
@@ -81,8 +111,10 @@ static uint32_t get_static_nip_by_mac(struct static_lease *st_lease, void *mac) | |||
81 | return 0; | 111 | return 0; |
82 | } | 112 | } |
83 | 113 | ||
84 | static int is_nip_reserved(struct static_lease *st_lease, uint32_t nip) | 114 | static int is_nip_reserved_as_static(uint32_t nip) |
85 | { | 115 | { |
116 | struct static_lease *st_lease = server_config.static_leases; | ||
117 | |||
86 | while (st_lease) { | 118 | while (st_lease) { |
87 | if (st_lease->nip == nip) | 119 | if (st_lease->nip == nip) |
88 | return 1; | 120 | return 1; |
@@ -92,30 +124,6 @@ static int is_nip_reserved(struct static_lease *st_lease, uint32_t nip) | |||
92 | return 0; | 124 | return 0; |
93 | } | 125 | } |
94 | 126 | ||
95 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 | ||
96 | /* Print out static leases just to check what's going on */ | ||
97 | /* Takes the address of the pointer to the static_leases linked list */ | ||
98 | static void log_static_leases(struct static_lease **st_lease_pp) | ||
99 | { | ||
100 | struct static_lease *cur; | ||
101 | |||
102 | if (dhcp_verbose < 2) | ||
103 | return; | ||
104 | |||
105 | cur = *st_lease_pp; | ||
106 | while (cur) { | ||
107 | bb_error_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x", | ||
108 | cur->mac[0], cur->mac[1], cur->mac[2], | ||
109 | cur->mac[3], cur->mac[4], cur->mac[5], | ||
110 | cur->nip | ||
111 | ); | ||
112 | cur = cur->next; | ||
113 | } | ||
114 | } | ||
115 | #else | ||
116 | # define log_static_leases(st_lease_pp) ((void)0) | ||
117 | #endif | ||
118 | |||
119 | /* Find the oldest expired lease, NULL if there are no expired leases */ | 127 | /* Find the oldest expired lease, NULL if there are no expired leases */ |
120 | static struct dyn_lease *oldest_expired_lease(void) | 128 | static struct dyn_lease *oldest_expired_lease(void) |
121 | { | 129 | { |
@@ -242,7 +250,7 @@ static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigne | |||
242 | return r; | 250 | return r; |
243 | 251 | ||
244 | temp.s_addr = nip; | 252 | temp.s_addr = nip; |
245 | bb_error_msg("%s belongs to someone, reserving it for %u seconds", | 253 | bb_info_msg("%s belongs to someone, reserving it for %u seconds", |
246 | inet_ntoa(temp), (unsigned)server_config.conflict_time); | 254 | inet_ntoa(temp), (unsigned)server_config.conflict_time); |
247 | add_lease(NULL, nip, server_config.conflict_time, NULL, 0); | 255 | add_lease(NULL, nip, server_config.conflict_time, NULL, 0); |
248 | return 0; | 256 | return 0; |
@@ -288,7 +296,7 @@ static uint32_t find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arppi | |||
288 | if (nip == server_config.server_nip) | 296 | if (nip == server_config.server_nip) |
289 | goto next_addr; | 297 | goto next_addr; |
290 | /* is this a static lease addr? */ | 298 | /* is this a static lease addr? */ |
291 | if (is_nip_reserved(server_config.static_leases, nip)) | 299 | if (is_nip_reserved_as_static(nip)) |
292 | goto next_addr; | 300 | goto next_addr; |
293 | 301 | ||
294 | lease = find_lease_by_nip(nip); | 302 | lease = find_lease_by_nip(nip); |
@@ -340,6 +348,7 @@ static int FAST_FUNC read_staticlease(const char *const_line, void *arg) | |||
340 | char *line; | 348 | char *line; |
341 | char *mac_string; | 349 | char *mac_string; |
342 | char *ip_string; | 350 | char *ip_string; |
351 | char *opts; | ||
343 | struct ether_addr mac_bytes; /* it's "struct { uint8_t mac[6]; }" */ | 352 | struct ether_addr mac_bytes; /* it's "struct { uint8_t mac[6]; }" */ |
344 | uint32_t nip; | 353 | uint32_t nip; |
345 | 354 | ||
@@ -354,14 +363,16 @@ static int FAST_FUNC read_staticlease(const char *const_line, void *arg) | |||
354 | if (!ip_string || !udhcp_str2nip(ip_string, &nip)) | 363 | if (!ip_string || !udhcp_str2nip(ip_string, &nip)) |
355 | return 0; | 364 | return 0; |
356 | 365 | ||
357 | add_static_lease(arg, (uint8_t*) &mac_bytes, nip); | 366 | opts = strtok_r(NULL, " \t", &line); |
367 | /* opts might be NULL, that's not an error */ | ||
358 | 368 | ||
359 | log_static_leases(arg); | 369 | add_static_lease(arg, (uint8_t*) &mac_bytes, nip, opts); |
360 | 370 | ||
361 | return 1; | 371 | return 1; |
362 | } | 372 | } |
363 | 373 | ||
364 | static int FAST_FUNC read_optset(const char *line, void *arg) { | 374 | static int FAST_FUNC read_optset(const char *line, void *arg) |
375 | { | ||
365 | return udhcp_str2optset(line, arg, | 376 | return udhcp_str2optset(line, arg, |
366 | dhcp_optflags, dhcp_option_strings, | 377 | dhcp_optflags, dhcp_option_strings, |
367 | /*dhcpv6:*/ 0 | 378 | /*dhcpv6:*/ 0 |
@@ -518,13 +529,13 @@ static NOINLINE void read_leases(const char *file) | |||
518 | expires = 0; | 529 | expires = 0; |
519 | 530 | ||
520 | /* Check if there is a different static lease for this IP or MAC */ | 531 | /* Check if there is a different static lease for this IP or MAC */ |
521 | static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac); | 532 | static_nip = get_static_nip_by_mac(lease.lease_mac); |
522 | if (static_nip) { | 533 | if (static_nip) { |
523 | /* NB: we do not add lease even if static_nip == lease.lease_nip. | 534 | /* NB: we do not add lease even if static_nip == lease.lease_nip. |
524 | */ | 535 | */ |
525 | continue; | 536 | continue; |
526 | } | 537 | } |
527 | if (is_nip_reserved(server_config.static_leases, lease.lease_nip)) | 538 | if (is_nip_reserved_as_static(lease.lease_nip)) |
528 | continue; | 539 | continue; |
529 | 540 | ||
530 | /* NB: add_lease takes "relative time", IOW, | 541 | /* NB: add_lease takes "relative time", IOW, |
@@ -602,6 +613,15 @@ static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) | |||
602 | send_packet_to_client(dhcp_pkt, force_broadcast); | 613 | send_packet_to_client(dhcp_pkt, force_broadcast); |
603 | } | 614 | } |
604 | 615 | ||
616 | static void send_packet_verbose(struct dhcp_packet *dhcp_pkt, const char *fmt) | ||
617 | { | ||
618 | struct in_addr addr; | ||
619 | addr.s_addr = dhcp_pkt->yiaddr; | ||
620 | bb_info_msg(fmt, inet_ntoa(addr)); | ||
621 | /* send_packet emits error message itself if it detects failure */ | ||
622 | send_packet(dhcp_pkt, /*force_bcast:*/ 0); | ||
623 | } | ||
624 | |||
605 | static void init_packet(struct dhcp_packet *packet, struct dhcp_packet *oldpacket, char type) | 625 | static void init_packet(struct dhcp_packet *packet, struct dhcp_packet *oldpacket, char type) |
606 | { | 626 | { |
607 | /* Sets op, htype, hlen, cookie fields | 627 | /* Sets op, htype, hlen, cookie fields |
@@ -621,14 +641,49 @@ static void init_packet(struct dhcp_packet *packet, struct dhcp_packet *oldpacke | |||
621 | */ | 641 | */ |
622 | static void add_server_options(struct dhcp_packet *packet) | 642 | static void add_server_options(struct dhcp_packet *packet) |
623 | { | 643 | { |
624 | struct option_set *curr = server_config.options; | 644 | struct option_set *config_opts; |
645 | uint8_t *client_hostname_opt; | ||
646 | |||
647 | client_hostname_opt = NULL; | ||
648 | if (packet->yiaddr) { /* if we aren't from send_inform()... */ | ||
649 | struct static_lease *st_lease = server_config.static_leases; | ||
650 | while (st_lease) { | ||
651 | if (st_lease->nip == packet->yiaddr) { | ||
652 | if (st_lease->opt[0] != 0) | ||
653 | client_hostname_opt = st_lease->opt; | ||
654 | break; | ||
655 | } | ||
656 | st_lease = st_lease->next; | ||
657 | } | ||
658 | } | ||
625 | 659 | ||
626 | while (curr) { | 660 | config_opts = server_config.options; |
627 | if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) | 661 | while (config_opts) { |
628 | udhcp_add_binary_option(packet, curr->data); | 662 | if (config_opts->data[OPT_CODE] != DHCP_LEASE_TIME) { |
629 | curr = curr->next; | 663 | /* ^^^^ |
664 | * DHCP_LEASE_TIME is already filled, or in case of | ||
665 | * send_inform(), should not be filled at all. | ||
666 | */ | ||
667 | if (config_opts->data[OPT_CODE] != DHCP_HOST_NAME | ||
668 | || !client_hostname_opt | ||
669 | ) { | ||
670 | /* Why "!client_hostname_opt": | ||
671 | * add hostname only if client has no hostname | ||
672 | * on its static lease line. | ||
673 | * (Not that "opt hostname HOST" | ||
674 | * makes much sense in udhcpd.conf, | ||
675 | * that'd give all clients the same hostname, | ||
676 | * but it's a valid configuration). | ||
677 | */ | ||
678 | udhcp_add_binary_option(packet, config_opts->data); | ||
679 | } | ||
680 | } | ||
681 | config_opts = config_opts->next; | ||
630 | } | 682 | } |
631 | 683 | ||
684 | if (client_hostname_opt) | ||
685 | udhcp_add_binary_option(packet, client_hostname_opt); | ||
686 | |||
632 | packet->siaddr_nip = server_config.siaddr_nip; | 687 | packet->siaddr_nip = server_config.siaddr_nip; |
633 | 688 | ||
634 | if (server_config.sname) | 689 | if (server_config.sname) |
@@ -657,12 +712,11 @@ static uint32_t select_lease_time(struct dhcp_packet *packet) | |||
657 | static NOINLINE void send_offer(struct dhcp_packet *oldpacket, | 712 | static NOINLINE void send_offer(struct dhcp_packet *oldpacket, |
658 | uint32_t static_lease_nip, | 713 | uint32_t static_lease_nip, |
659 | struct dyn_lease *lease, | 714 | struct dyn_lease *lease, |
660 | uint8_t *requested_ip_opt, | 715 | uint32_t requested_nip, |
661 | unsigned arpping_ms) | 716 | unsigned arpping_ms) |
662 | { | 717 | { |
663 | struct dhcp_packet packet; | 718 | struct dhcp_packet packet; |
664 | uint32_t lease_time_sec; | 719 | uint32_t lease_time_sec; |
665 | struct in_addr addr; | ||
666 | 720 | ||
667 | init_packet(&packet, oldpacket, DHCPOFFER); | 721 | init_packet(&packet, oldpacket, DHCPOFFER); |
668 | 722 | ||
@@ -671,7 +725,6 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, | |||
671 | /* Else: */ | 725 | /* Else: */ |
672 | if (!static_lease_nip) { | 726 | if (!static_lease_nip) { |
673 | /* We have no static lease for client's chaddr */ | 727 | /* We have no static lease for client's chaddr */ |
674 | uint32_t req_nip; | ||
675 | const char *p_host_name; | 728 | const char *p_host_name; |
676 | 729 | ||
677 | if (lease) { | 730 | if (lease) { |
@@ -682,18 +735,16 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, | |||
682 | packet.yiaddr = lease->lease_nip; | 735 | packet.yiaddr = lease->lease_nip; |
683 | } | 736 | } |
684 | /* Or: if client has requested an IP */ | 737 | /* Or: if client has requested an IP */ |
685 | else if (requested_ip_opt != NULL | 738 | else if (requested_nip != 0 |
686 | /* (read IP) */ | ||
687 | && (move_from_unaligned32(req_nip, requested_ip_opt), 1) | ||
688 | /* and the IP is in the lease range */ | 739 | /* and the IP is in the lease range */ |
689 | && ntohl(req_nip) >= server_config.start_ip | 740 | && ntohl(requested_nip) >= server_config.start_ip |
690 | && ntohl(req_nip) <= server_config.end_ip | 741 | && ntohl(requested_nip) <= server_config.end_ip |
691 | /* and */ | 742 | /* and */ |
692 | && ( !(lease = find_lease_by_nip(req_nip)) /* is not already taken */ | 743 | && ( !(lease = find_lease_by_nip(requested_nip)) /* is not already taken */ |
693 | || is_expired_lease(lease) /* or is taken, but expired */ | 744 | || is_expired_lease(lease) /* or is taken, but expired */ |
694 | ) | 745 | ) |
695 | ) { | 746 | ) { |
696 | packet.yiaddr = req_nip; | 747 | packet.yiaddr = requested_nip; |
697 | } | 748 | } |
698 | else { | 749 | else { |
699 | /* Otherwise, find a free IP */ | 750 | /* Otherwise, find a free IP */ |
@@ -721,10 +772,8 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, | |||
721 | udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); | 772 | udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); |
722 | add_server_options(&packet); | 773 | add_server_options(&packet); |
723 | 774 | ||
724 | addr.s_addr = packet.yiaddr; | ||
725 | bb_error_msg("sending OFFER of %s", inet_ntoa(addr)); | ||
726 | /* send_packet emits error message itself if it detects failure */ | 775 | /* send_packet emits error message itself if it detects failure */ |
727 | send_packet(&packet, /*force_bcast:*/ 0); | 776 | send_packet_verbose(&packet, "sending OFFER to %s"); |
728 | } | 777 | } |
729 | 778 | ||
730 | /* NOINLINE: limit stack usage in caller */ | 779 | /* NOINLINE: limit stack usage in caller */ |
@@ -743,7 +792,6 @@ static NOINLINE void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr) | |||
743 | { | 792 | { |
744 | struct dhcp_packet packet; | 793 | struct dhcp_packet packet; |
745 | uint32_t lease_time_sec; | 794 | uint32_t lease_time_sec; |
746 | struct in_addr addr; | ||
747 | const char *p_host_name; | 795 | const char *p_host_name; |
748 | 796 | ||
749 | init_packet(&packet, oldpacket, DHCPACK); | 797 | init_packet(&packet, oldpacket, DHCPACK); |
@@ -751,12 +799,9 @@ static NOINLINE void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr) | |||
751 | 799 | ||
752 | lease_time_sec = select_lease_time(oldpacket); | 800 | lease_time_sec = select_lease_time(oldpacket); |
753 | udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); | 801 | udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); |
754 | |||
755 | add_server_options(&packet); | 802 | add_server_options(&packet); |
756 | 803 | ||
757 | addr.s_addr = yiaddr; | 804 | send_packet_verbose(&packet, "sending ACK to %s"); |
758 | bb_error_msg("sending ACK to %s", inet_ntoa(addr)); | ||
759 | send_packet(&packet, /*force_bcast:*/ 0); | ||
760 | 805 | ||
761 | p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME); | 806 | p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME); |
762 | add_lease(packet.chaddr, packet.yiaddr, | 807 | add_lease(packet.chaddr, packet.yiaddr, |
@@ -796,6 +841,7 @@ static NOINLINE void send_inform(struct dhcp_packet *oldpacket) | |||
796 | add_server_options(&packet); | 841 | add_server_options(&packet); |
797 | 842 | ||
798 | send_packet(&packet, /*force_bcast:*/ 0); | 843 | send_packet(&packet, /*force_bcast:*/ 0); |
844 | // or maybe? send_packet_verbose(&packet, "sending ACK to %s"); | ||
799 | } | 845 | } |
800 | 846 | ||
801 | int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 847 | int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -865,7 +911,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
865 | write_pidfile(server_config.pidfile); | 911 | write_pidfile(server_config.pidfile); |
866 | /* if (!..) bb_perror_msg("can't create pidfile %s", pidfile); */ | 912 | /* if (!..) bb_perror_msg("can't create pidfile %s", pidfile); */ |
867 | 913 | ||
868 | bb_error_msg("started, v"BB_VER); | 914 | bb_info_msg("started, v"BB_VER); |
869 | 915 | ||
870 | option = udhcp_find_option(server_config.options, DHCP_LEASE_TIME); | 916 | option = udhcp_find_option(server_config.options, DHCP_LEASE_TIME); |
871 | server_config.max_lease_sec = DEFAULT_LEASE_TIME; | 917 | server_config.max_lease_sec = DEFAULT_LEASE_TIME; |
@@ -908,7 +954,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
908 | int tv; | 954 | int tv; |
909 | uint8_t *server_id_opt; | 955 | uint8_t *server_id_opt; |
910 | uint8_t *requested_ip_opt; | 956 | uint8_t *requested_ip_opt; |
911 | uint32_t requested_nip = requested_nip; /* for compiler */ | 957 | uint32_t requested_nip; |
912 | uint32_t static_lease_nip; | 958 | uint32_t static_lease_nip; |
913 | struct dyn_lease *lease, fake_lease; | 959 | struct dyn_lease *lease, fake_lease; |
914 | 960 | ||
@@ -944,12 +990,12 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
944 | 990 | ||
945 | if (pfds[0].revents) switch (udhcp_sp_read()) { | 991 | if (pfds[0].revents) switch (udhcp_sp_read()) { |
946 | case SIGUSR1: | 992 | case SIGUSR1: |
947 | bb_error_msg("received %s", "SIGUSR1"); | 993 | bb_info_msg("received %s", "SIGUSR1"); |
948 | write_leases(); | 994 | write_leases(); |
949 | /* why not just reset the timeout, eh */ | 995 | /* why not just reset the timeout, eh */ |
950 | goto continue_with_autotime; | 996 | goto continue_with_autotime; |
951 | case SIGTERM: | 997 | case SIGTERM: |
952 | bb_error_msg("received %s", "SIGTERM"); | 998 | bb_info_msg("received %s", "SIGTERM"); |
953 | write_leases(); | 999 | write_leases(); |
954 | goto ret0; | 1000 | goto ret0; |
955 | } | 1001 | } |
@@ -973,16 +1019,16 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
973 | continue; | 1019 | continue; |
974 | } | 1020 | } |
975 | if (packet.hlen != 6) { | 1021 | if (packet.hlen != 6) { |
976 | bb_error_msg("MAC length != 6, ignoring packet"); | 1022 | bb_info_msg("MAC length != 6, ignoring packet"); |
977 | continue; | 1023 | continue; |
978 | } | 1024 | } |
979 | if (packet.op != BOOTREQUEST) { | 1025 | if (packet.op != BOOTREQUEST) { |
980 | bb_error_msg("not a REQUEST, ignoring packet"); | 1026 | bb_info_msg("not a REQUEST, ignoring packet"); |
981 | continue; | 1027 | continue; |
982 | } | 1028 | } |
983 | state = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); | 1029 | state = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); |
984 | if (state == NULL || state[0] < DHCP_MINTYPE || state[0] > DHCP_MAXTYPE) { | 1030 | if (state == NULL || state[0] < DHCP_MINTYPE || state[0] > DHCP_MAXTYPE) { |
985 | bb_error_msg("no or bad message type option, ignoring packet"); | 1031 | bb_info_msg("no or bad message type option, ignoring packet"); |
986 | continue; | 1032 | continue; |
987 | } | 1033 | } |
988 | 1034 | ||
@@ -999,9 +1045,9 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
999 | } | 1045 | } |
1000 | 1046 | ||
1001 | /* Look for a static/dynamic lease */ | 1047 | /* Look for a static/dynamic lease */ |
1002 | static_lease_nip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr); | 1048 | static_lease_nip = get_static_nip_by_mac(&packet.chaddr); |
1003 | if (static_lease_nip) { | 1049 | if (static_lease_nip) { |
1004 | bb_error_msg("found static lease: %x", static_lease_nip); | 1050 | bb_info_msg("found static lease: %x", static_lease_nip); |
1005 | memcpy(&fake_lease.lease_mac, &packet.chaddr, 6); | 1051 | memcpy(&fake_lease.lease_mac, &packet.chaddr, 6); |
1006 | fake_lease.lease_nip = static_lease_nip; | 1052 | fake_lease.lease_nip = static_lease_nip; |
1007 | fake_lease.expires = 0; | 1053 | fake_lease.expires = 0; |
@@ -1011,6 +1057,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
1011 | } | 1057 | } |
1012 | 1058 | ||
1013 | /* Get REQUESTED_IP if present */ | 1059 | /* Get REQUESTED_IP if present */ |
1060 | requested_nip = 0; | ||
1014 | requested_ip_opt = udhcp_get_option32(&packet, DHCP_REQUESTED_IP); | 1061 | requested_ip_opt = udhcp_get_option32(&packet, DHCP_REQUESTED_IP); |
1015 | if (requested_ip_opt) { | 1062 | if (requested_ip_opt) { |
1016 | move_from_unaligned32(requested_nip, requested_ip_opt); | 1063 | move_from_unaligned32(requested_nip, requested_ip_opt); |
@@ -1021,7 +1068,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
1021 | case DHCPDISCOVER: | 1068 | case DHCPDISCOVER: |
1022 | log1("received %s", "DISCOVER"); | 1069 | log1("received %s", "DISCOVER"); |
1023 | 1070 | ||
1024 | send_offer(&packet, static_lease_nip, lease, requested_ip_opt, arpping_ms); | 1071 | send_offer(&packet, static_lease_nip, lease, requested_nip, arpping_ms); |
1025 | break; | 1072 | break; |
1026 | 1073 | ||
1027 | case DHCPREQUEST: | 1074 | case DHCPREQUEST: |
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h index b8f96b029..ba11d77e8 100644 --- a/networking/udhcp/dhcpd.h +++ b/networking/udhcp/dhcpd.h | |||
@@ -15,11 +15,7 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |||
15 | #define DHCPD_CONF_FILE "/etc/udhcpd.conf" | 15 | #define DHCPD_CONF_FILE "/etc/udhcpd.conf" |
16 | 16 | ||
17 | 17 | ||
18 | struct static_lease { | 18 | struct static_lease; |
19 | struct static_lease *next; | ||
20 | uint32_t nip; | ||
21 | uint8_t mac[6]; | ||
22 | }; | ||
23 | 19 | ||
24 | struct server_config_t { | 20 | struct server_config_t { |
25 | char *interface; /* interface to use */ | 21 | char *interface; /* interface to use */ |
@@ -58,7 +54,7 @@ struct server_config_t { | |||
58 | } FIX_ALIASING; | 54 | } FIX_ALIASING; |
59 | 55 | ||
60 | #define server_config (*(struct server_config_t*)bb_common_bufsiz1) | 56 | #define server_config (*(struct server_config_t*)bb_common_bufsiz1) |
61 | /* client_config sits in 2nd half of bb_common_bufsiz1 */ | 57 | /* client_data sits in 2nd half of bb_common_bufsiz1 */ |
62 | 58 | ||
63 | #if ENABLE_FEATURE_UDHCP_PORT | 59 | #if ENABLE_FEATURE_UDHCP_PORT |
64 | #define SERVER_PORT (server_config.port) | 60 | #define SERVER_PORT (server_config.port) |
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index ff16904f7..64af802a3 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c | |||
@@ -40,7 +40,7 @@ void FAST_FUNC udhcp_dump_packet(struct dhcp_packet *packet) | |||
40 | if (dhcp_verbose < 2) | 40 | if (dhcp_verbose < 2) |
41 | return; | 41 | return; |
42 | 42 | ||
43 | bb_error_msg( | 43 | bb_info_msg( |
44 | //" op %x" | 44 | //" op %x" |
45 | //" htype %x" | 45 | //" htype %x" |
46 | " hlen %x" | 46 | " hlen %x" |
@@ -73,7 +73,7 @@ void FAST_FUNC udhcp_dump_packet(struct dhcp_packet *packet) | |||
73 | //, packet->options[] | 73 | //, packet->options[] |
74 | ); | 74 | ); |
75 | *bin2hex(buf, (void *) packet->chaddr, sizeof(packet->chaddr)) = '\0'; | 75 | *bin2hex(buf, (void *) packet->chaddr, sizeof(packet->chaddr)) = '\0'; |
76 | bb_error_msg(" chaddr %s", buf); | 76 | bb_info_msg(" chaddr %s", buf); |
77 | } | 77 | } |
78 | #endif | 78 | #endif |
79 | 79 | ||
@@ -92,7 +92,7 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) | |||
92 | if (bytes < offsetof(struct dhcp_packet, options) | 92 | if (bytes < offsetof(struct dhcp_packet, options) |
93 | || packet->cookie != htonl(DHCP_MAGIC) | 93 | || packet->cookie != htonl(DHCP_MAGIC) |
94 | ) { | 94 | ) { |
95 | bb_error_msg("packet with bad magic, ignoring"); | 95 | bb_info_msg("packet with bad magic, ignoring"); |
96 | return -2; | 96 | return -2; |
97 | } | 97 | } |
98 | log1("received %s", "a packet"); | 98 | log1("received %s", "a packet"); |
diff --git a/networking/wget.c b/networking/wget.c index d907cee30..44cec2cb5 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -312,7 +312,7 @@ static void progress_meter(int flag) | |||
312 | } | 312 | } |
313 | } | 313 | } |
314 | #else | 314 | #else |
315 | static ALWAYS_INLINE void progress_meter(int flag UNUSED_PARAM) { } | 315 | static ALWAYS_INLINE void progress_meter(int flag UNUSED_PARAM) {} |
316 | #endif | 316 | #endif |
317 | 317 | ||
318 | 318 | ||
diff --git a/networking/zcip.c b/networking/zcip.c index 434762f12..f95b6f7fb 100644 --- a/networking/zcip.c +++ b/networking/zcip.c | |||
@@ -195,7 +195,7 @@ static int run(char *argv[3], const char *param, uint32_t nip) | |||
195 | putenv(env_ip); | 195 | putenv(env_ip); |
196 | fmt -= 3; | 196 | fmt -= 3; |
197 | } | 197 | } |
198 | bb_error_msg(fmt, argv[2], argv[0], addr); | 198 | bb_info_msg(fmt, argv[2], argv[0], addr); |
199 | status = spawn_and_wait(argv + 1); | 199 | status = spawn_and_wait(argv + 1); |
200 | if (nip != 0) | 200 | if (nip != 0) |
201 | bb_unsetenv_and_free(env_ip); | 201 | bb_unsetenv_and_free(env_ip); |
@@ -339,7 +339,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
339 | #if BB_MMU | 339 | #if BB_MMU |
340 | bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/); | 340 | bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/); |
341 | #endif | 341 | #endif |
342 | bb_error_msg("start, interface %s", argv_intf); | 342 | bb_info_msg("start, interface %s", argv_intf); |
343 | } | 343 | } |
344 | 344 | ||
345 | // Run the dynamic address negotiation protocol, | 345 | // Run the dynamic address negotiation protocol, |
diff --git a/procps/ps.c b/procps/ps.c index c08d03146..a4de11379 100644 --- a/procps/ps.c +++ b/procps/ps.c | |||
@@ -542,7 +542,7 @@ static void format_process(const procps_status_t *ps) | |||
542 | len = out[i].width - len + 1; | 542 | len = out[i].width - len + 1; |
543 | if (++i == out_cnt) /* do not pad last field */ | 543 | if (++i == out_cnt) /* do not pad last field */ |
544 | break; | 544 | break; |
545 | p += sprintf(p, "%*s", len, ""); | 545 | p += sprintf(p, "%*s", len, " "); /* " ", not "", to ensure separation of fields */ |
546 | } | 546 | } |
547 | printf("%.*s\n", terminal_width, buffer); | 547 | printf("%.*s\n", terminal_width, buffer); |
548 | } | 548 | } |
diff --git a/shell/Config.src b/shell/Config.src index bc7218fe5..d7623f774 100644 --- a/shell/Config.src +++ b/shell/Config.src | |||
@@ -99,6 +99,11 @@ config FEATURE_SH_MATH_64 | |||
99 | slightly larger, but will allow computation with very large numbers. | 99 | slightly larger, but will allow computation with very large numbers. |
100 | This is not in POSIX, so do not rely on this in portable code. | 100 | This is not in POSIX, so do not rely on this in portable code. |
101 | 101 | ||
102 | config FEATURE_SH_MATH_BASE | ||
103 | bool "Support BASE#nnnn literals" | ||
104 | default y | ||
105 | depends on FEATURE_SH_MATH | ||
106 | |||
102 | config FEATURE_SH_EXTRA_QUIET | 107 | config FEATURE_SH_EXTRA_QUIET |
103 | bool "Hide message on interactive shell startup" | 108 | bool "Hide message on interactive shell startup" |
104 | default y | 109 | default y |
diff --git a/shell/ash_test/ash-misc/export1.right b/shell/ash_test/ash-misc/export1.right new file mode 100644 index 000000000..56647af8e --- /dev/null +++ b/shell/ash_test/ash-misc/export1.right | |||
@@ -0,0 +1 @@ | |||
|\w \\ \ \| | |||
diff --git a/shell/ash_test/ash-misc/export1.tests b/shell/ash_test/ash-misc/export1.tests new file mode 100755 index 000000000..4ffb40bdc --- /dev/null +++ b/shell/ash_test/ash-misc/export1.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | export Z='\w \\ \ \' | ||
2 | echo "|$Z|" | ||
diff --git a/shell/ash_test/ash-vars/param_expand_default.right b/shell/ash_test/ash-vars/param_expand_default.right index 3eecd1375..7a42f67e8 100644 --- a/shell/ash_test/ash-vars/param_expand_default.right +++ b/shell/ash_test/ash-vars/param_expand_default.right | |||
@@ -5,3 +5,5 @@ _aaaa _aaaa _aaaa _aaaa _aaaa | |||
5 | _ _ _ _word _word | 5 | _ _ _ _word _word |
6 | _ _ _ _ _word | 6 | _ _ _ _ _word |
7 | _fff _fff _fff _fff _fff | 7 | _fff _fff _fff _fff _fff |
8 | 1:1 | ||
9 | 0:0 | ||
diff --git a/shell/ash_test/ash-vars/param_expand_default.tests b/shell/ash_test/ash-vars/param_expand_default.tests index 5e42d30e3..dbd3e2218 100755 --- a/shell/ash_test/ash-vars/param_expand_default.tests +++ b/shell/ash_test/ash-vars/param_expand_default.tests | |||
@@ -1,6 +1,5 @@ | |||
1 | # first try some invalid patterns (do in subshell due to parsing error) | 1 | # first try some invalid patterns (do in subshell due to parsing error) |
2 | # (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages) | 2 | # (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages) |
3 | # valid in bash and ash (same as $-): "$THIS_SH" -c 'echo ${-}' SHELL | ||
4 | "$THIS_SH" -c 'echo ${:-}' SHELL | 3 | "$THIS_SH" -c 'echo ${:-}' SHELL |
5 | 4 | ||
6 | # now some funky ones | 5 | # now some funky ones |
@@ -21,3 +20,8 @@ echo _$f _${f-} _${f:-} _${f-word} _${f:-word} | |||
21 | 20 | ||
22 | f=fff | 21 | f=fff |
23 | echo _$f _${f-} _${f:-} _${f-word} _${f:-word} | 22 | echo _$f _${f-} _${f:-} _${f-word} _${f:-word} |
23 | |||
24 | set -- | ||
25 | set -- "${1-}"; echo 1:$# | ||
26 | set -- | ||
27 | set -- ${1-}; echo 0:$# | ||
diff --git a/shell/hush.c b/shell/hush.c index b3ae73b9b..4b08232a4 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -466,9 +466,9 @@ | |||
466 | 466 | ||
467 | #define JOB_STATUS_FORMAT "[%u] %-22s %.40s\n" | 467 | #define JOB_STATUS_FORMAT "[%u] %-22s %.40s\n" |
468 | 468 | ||
469 | #define _SPECIAL_VARS_STR "_*@$!?#" | 469 | #define _SPECIAL_VARS_STR "_*@$!?#-" |
470 | #define SPECIAL_VARS_STR ("_*@$!?#" + 1) | 470 | #define SPECIAL_VARS_STR ("_*@$!?#-" + 1) |
471 | #define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3) | 471 | #define NUMERIC_SPECVARS_STR ("_*@$!?#-" + 3) |
472 | #if BASH_PATTERN_SUBST | 472 | #if BASH_PATTERN_SUBST |
473 | /* Support / and // replace ops */ | 473 | /* Support / and // replace ops */ |
474 | /* Note that // is stored as \ in "encoded" string representation */ | 474 | /* Note that // is stored as \ in "encoded" string representation */ |
@@ -854,8 +854,7 @@ struct globals { | |||
854 | /* 'interactive_fd' is a fd# open to ctty, if we have one | 854 | /* 'interactive_fd' is a fd# open to ctty, if we have one |
855 | * _AND_ if we decided to act interactively */ | 855 | * _AND_ if we decided to act interactively */ |
856 | int interactive_fd; | 856 | int interactive_fd; |
857 | const char *PS1; | 857 | IF_NOT_FEATURE_EDITING_FANCY_PROMPT(char *PS1;) |
858 | IF_FEATURE_EDITING_FANCY_PROMPT(const char *PS2;) | ||
859 | # define G_interactive_fd (G.interactive_fd) | 858 | # define G_interactive_fd (G.interactive_fd) |
860 | #else | 859 | #else |
861 | # define G_interactive_fd 0 | 860 | # define G_interactive_fd 0 |
@@ -903,6 +902,7 @@ struct globals { | |||
903 | #else | 902 | #else |
904 | # define G_x_mode 0 | 903 | # define G_x_mode 0 |
905 | #endif | 904 | #endif |
905 | char opt_s; | ||
906 | #if ENABLE_HUSH_INTERACTIVE | 906 | #if ENABLE_HUSH_INTERACTIVE |
907 | smallint promptmode; /* 0: PS1, 1: PS2 */ | 907 | smallint promptmode; /* 0: PS1, 1: PS2 */ |
908 | #endif | 908 | #endif |
@@ -968,8 +968,8 @@ struct globals { | |||
968 | smallint we_have_children; | 968 | smallint we_have_children; |
969 | #endif | 969 | #endif |
970 | #if ENABLE_HUSH_LINENO_VAR | 970 | #if ENABLE_HUSH_LINENO_VAR |
971 | unsigned lineno; | 971 | unsigned parse_lineno; |
972 | char *lineno_var; | 972 | unsigned execute_lineno; |
973 | #endif | 973 | #endif |
974 | HFILE *HFILE_list; | 974 | HFILE *HFILE_list; |
975 | /* Which signals have non-DFL handler (even with no traps set)? | 975 | /* Which signals have non-DFL handler (even with no traps set)? |
@@ -1009,6 +1009,7 @@ struct globals { | |||
1009 | int debug_indent; | 1009 | int debug_indent; |
1010 | #endif | 1010 | #endif |
1011 | struct sigaction sa; | 1011 | struct sigaction sa; |
1012 | char optstring_buf[sizeof("eixs")]; | ||
1012 | #if BASH_EPOCH_VARS | 1013 | #if BASH_EPOCH_VARS |
1013 | char epoch_buf[sizeof("%lu.nnnnnn") + sizeof(long)*3]; | 1014 | char epoch_buf[sizeof("%lu.nnnnnn") + sizeof(long)*3]; |
1014 | #endif | 1015 | #endif |
@@ -1448,13 +1449,6 @@ static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch) | |||
1448 | #endif | 1449 | #endif |
1449 | 1450 | ||
1450 | 1451 | ||
1451 | #if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT | ||
1452 | static void cmdedit_update_prompt(void); | ||
1453 | #else | ||
1454 | # define cmdedit_update_prompt() ((void)0) | ||
1455 | #endif | ||
1456 | |||
1457 | |||
1458 | /* Utility functions | 1452 | /* Utility functions |
1459 | */ | 1453 | */ |
1460 | /* Replace each \x with x in place, return ptr past NUL. */ | 1454 | /* Replace each \x with x in place, return ptr past NUL. */ |
@@ -2039,7 +2033,8 @@ static sighandler_t pick_sighandler(unsigned sig) | |||
2039 | static void hush_exit(int exitcode) | 2033 | static void hush_exit(int exitcode) |
2040 | { | 2034 | { |
2041 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | 2035 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT |
2042 | save_history(G.line_input_state); | 2036 | if (G.line_input_state) |
2037 | save_history(G.line_input_state); | ||
2043 | #endif | 2038 | #endif |
2044 | 2039 | ||
2045 | fflush_all(); | 2040 | fflush_all(); |
@@ -2229,6 +2224,10 @@ static const char* FAST_FUNC get_local_var_value(const char *name) | |||
2229 | if (strcmp(name, "RANDOM") == 0) | 2224 | if (strcmp(name, "RANDOM") == 0) |
2230 | return utoa(next_random(&G.random_gen)); | 2225 | return utoa(next_random(&G.random_gen)); |
2231 | #endif | 2226 | #endif |
2227 | #if ENABLE_HUSH_LINENO_VAR | ||
2228 | if (strcmp(name, "LINENO") == 0) | ||
2229 | return utoa(G.execute_lineno); | ||
2230 | #endif | ||
2232 | #if BASH_EPOCH_VARS | 2231 | #if BASH_EPOCH_VARS |
2233 | { | 2232 | { |
2234 | const char *fmt = NULL; | 2233 | const char *fmt = NULL; |
@@ -2248,32 +2247,20 @@ static const char* FAST_FUNC get_local_var_value(const char *name) | |||
2248 | return NULL; | 2247 | return NULL; |
2249 | } | 2248 | } |
2250 | 2249 | ||
2250 | #if ENABLE_HUSH_GETOPTS | ||
2251 | static void handle_changed_special_names(const char *name, unsigned name_len) | 2251 | static void handle_changed_special_names(const char *name, unsigned name_len) |
2252 | { | 2252 | { |
2253 | if (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT | 2253 | if (name_len == 6) { |
2254 | && name_len == 3 && name[0] == 'P' && name[1] == 'S' | ||
2255 | ) { | ||
2256 | cmdedit_update_prompt(); | ||
2257 | return; | ||
2258 | } | ||
2259 | |||
2260 | if ((ENABLE_HUSH_LINENO_VAR || ENABLE_HUSH_GETOPTS) | ||
2261 | && name_len == 6 | ||
2262 | ) { | ||
2263 | #if ENABLE_HUSH_LINENO_VAR | ||
2264 | if (strncmp(name, "LINENO", 6) == 0) { | ||
2265 | G.lineno_var = NULL; | ||
2266 | return; | ||
2267 | } | ||
2268 | #endif | ||
2269 | #if ENABLE_HUSH_GETOPTS | ||
2270 | if (strncmp(name, "OPTIND", 6) == 0) { | 2254 | if (strncmp(name, "OPTIND", 6) == 0) { |
2271 | G.getopt_count = 0; | 2255 | G.getopt_count = 0; |
2272 | return; | 2256 | return; |
2273 | } | 2257 | } |
2274 | #endif | ||
2275 | } | 2258 | } |
2276 | } | 2259 | } |
2260 | #else | ||
2261 | /* Do not even bother evaluating arguments */ | ||
2262 | # define handle_changed_special_names(...) ((void)0) | ||
2263 | #endif | ||
2277 | 2264 | ||
2278 | /* str holds "NAME=VAL" and is expected to be malloced. | 2265 | /* str holds "NAME=VAL" and is expected to be malloced. |
2279 | * We take ownership of it. | 2266 | * We take ownership of it. |
@@ -2289,6 +2276,7 @@ static int set_local_var(char *str, unsigned flags) | |||
2289 | char *free_me = NULL; | 2276 | char *free_me = NULL; |
2290 | char *eq_sign; | 2277 | char *eq_sign; |
2291 | int name_len; | 2278 | int name_len; |
2279 | int retval; | ||
2292 | unsigned local_lvl = (flags >> SETFLAG_VARLVL_SHIFT); | 2280 | unsigned local_lvl = (flags >> SETFLAG_VARLVL_SHIFT); |
2293 | 2281 | ||
2294 | eq_sign = strchr(str, '='); | 2282 | eq_sign = strchr(str, '='); |
@@ -2402,24 +2390,24 @@ static int set_local_var(char *str, unsigned flags) | |||
2402 | #endif | 2390 | #endif |
2403 | if (flags & SETFLAG_EXPORT) | 2391 | if (flags & SETFLAG_EXPORT) |
2404 | cur->flg_export = 1; | 2392 | cur->flg_export = 1; |
2393 | retval = 0; | ||
2405 | if (cur->flg_export) { | 2394 | if (cur->flg_export) { |
2406 | if (flags & SETFLAG_UNEXPORT) { | 2395 | if (flags & SETFLAG_UNEXPORT) { |
2407 | cur->flg_export = 0; | 2396 | cur->flg_export = 0; |
2408 | /* unsetenv was already done */ | 2397 | /* unsetenv was already done */ |
2409 | } else { | 2398 | } else { |
2410 | int i; | ||
2411 | debug_printf_env("%s: putenv '%s'/%u\n", __func__, cur->varstr, cur->var_nest_level); | 2399 | debug_printf_env("%s: putenv '%s'/%u\n", __func__, cur->varstr, cur->var_nest_level); |
2412 | i = putenv(cur->varstr); | 2400 | retval = putenv(cur->varstr); |
2413 | /* only now we can free old exported malloced string */ | 2401 | /* fall through to "free(free_me)" - |
2414 | free(free_me); | 2402 | * only now we can free old exported malloced string |
2415 | return i; | 2403 | */ |
2416 | } | 2404 | } |
2417 | } | 2405 | } |
2418 | free(free_me); | 2406 | free(free_me); |
2419 | 2407 | ||
2420 | handle_changed_special_names(cur->varstr, name_len - 1); | 2408 | handle_changed_special_names(cur->varstr, name_len - 1); |
2421 | 2409 | ||
2422 | return 0; | 2410 | return retval; |
2423 | } | 2411 | } |
2424 | 2412 | ||
2425 | static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) | 2413 | static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) |
@@ -2462,7 +2450,7 @@ static int unset_local_var_len(const char *name, int name_len) | |||
2462 | cur_pp = &cur->next; | 2450 | cur_pp = &cur->next; |
2463 | } | 2451 | } |
2464 | 2452 | ||
2465 | /* Handle "unset PS1" et al even if did not find the variable to unset */ | 2453 | /* Handle "unset LINENO" et al even if did not find the variable to unset */ |
2466 | handle_changed_special_names(name, name_len); | 2454 | handle_changed_special_names(name, name_len); |
2467 | 2455 | ||
2468 | return EXIT_SUCCESS; | 2456 | return EXIT_SUCCESS; |
@@ -2581,36 +2569,27 @@ static void reinit_unicode_for_hush(void) | |||
2581 | * \ | 2569 | * \ |
2582 | * It exercises a lot of corner cases. | 2570 | * It exercises a lot of corner cases. |
2583 | */ | 2571 | */ |
2584 | # if ENABLE_FEATURE_EDITING_FANCY_PROMPT | ||
2585 | static void cmdedit_update_prompt(void) | ||
2586 | { | ||
2587 | G.PS1 = get_local_var_value("PS1"); | ||
2588 | if (G.PS1 == NULL) | ||
2589 | G.PS1 = ""; | ||
2590 | G.PS2 = get_local_var_value("PS2"); | ||
2591 | if (G.PS2 == NULL) | ||
2592 | G.PS2 = ""; | ||
2593 | } | ||
2594 | # endif | ||
2595 | static const char *setup_prompt_string(void) | 2572 | static const char *setup_prompt_string(void) |
2596 | { | 2573 | { |
2597 | const char *prompt_str; | 2574 | const char *prompt_str; |
2598 | 2575 | ||
2599 | debug_printf_prompt("%s promptmode:%d\n", __func__, G.promptmode); | 2576 | debug_printf_prompt("%s promptmode:%d\n", __func__, G.promptmode); |
2600 | 2577 | ||
2601 | IF_FEATURE_EDITING_FANCY_PROMPT( prompt_str = G.PS2;) | 2578 | # if ENABLE_FEATURE_EDITING_FANCY_PROMPT |
2602 | IF_NOT_FEATURE_EDITING_FANCY_PROMPT(prompt_str = "> ";) | 2579 | prompt_str = get_local_var_value(G.promptmode == 0 ? "PS1" : "PS2"); |
2580 | if (!prompt_str) | ||
2581 | prompt_str = ""; | ||
2582 | # else | ||
2583 | prompt_str = "> "; /* if PS2, else... */ | ||
2603 | if (G.promptmode == 0) { /* PS1 */ | 2584 | if (G.promptmode == 0) { /* PS1 */ |
2604 | if (!ENABLE_FEATURE_EDITING_FANCY_PROMPT) { | 2585 | /* No fancy prompts supported, (re)generate "CURDIR $ " by hand */ |
2605 | /* No fancy prompts supported, (re)generate "CURDIR $ " by hand */ | 2586 | free(G.PS1); |
2606 | free((char*)G.PS1); | 2587 | /* bash uses $PWD value, even if it is set by user. |
2607 | /* bash uses $PWD value, even if it is set by user. | 2588 | * It uses current dir only if PWD is unset. |
2608 | * It uses current dir only if PWD is unset. | 2589 | * We always use current dir. */ |
2609 | * We always use current dir. */ | 2590 | G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#'); |
2610 | G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#'); | ||
2611 | } | ||
2612 | prompt_str = G.PS1; | ||
2613 | } | 2591 | } |
2592 | # endif | ||
2614 | debug_printf("prompt_str '%s'\n", prompt_str); | 2593 | debug_printf("prompt_str '%s'\n", prompt_str); |
2615 | return prompt_str; | 2594 | return prompt_str; |
2616 | } | 2595 | } |
@@ -2747,8 +2726,8 @@ static int i_getch(struct in_str *i) | |||
2747 | i->last_char = ch; | 2726 | i->last_char = ch; |
2748 | #if ENABLE_HUSH_LINENO_VAR | 2727 | #if ENABLE_HUSH_LINENO_VAR |
2749 | if (ch == '\n') { | 2728 | if (ch == '\n') { |
2750 | G.lineno++; | 2729 | G.parse_lineno++; |
2751 | debug_printf_parse("G.lineno++ = %u\n", G.lineno); | 2730 | debug_printf_parse("G.parse_lineno++ = %u\n", G.parse_lineno); |
2752 | } | 2731 | } |
2753 | #endif | 2732 | #endif |
2754 | return ch; | 2733 | return ch; |
@@ -3750,8 +3729,8 @@ static int done_command(struct parse_context *ctx) | |||
3750 | clear_and_ret: | 3729 | clear_and_ret: |
3751 | memset(command, 0, sizeof(*command)); | 3730 | memset(command, 0, sizeof(*command)); |
3752 | #if ENABLE_HUSH_LINENO_VAR | 3731 | #if ENABLE_HUSH_LINENO_VAR |
3753 | command->lineno = G.lineno; | 3732 | command->lineno = G.parse_lineno; |
3754 | debug_printf_parse("command->lineno = G.lineno (%u)\n", G.lineno); | 3733 | debug_printf_parse("command->lineno = G.parse_lineno (%u)\n", G.parse_lineno); |
3755 | #endif | 3734 | #endif |
3756 | return pi->num_cmds; /* used only for 0/nonzero check */ | 3735 | return pi->num_cmds; /* used only for 0/nonzero check */ |
3757 | } | 3736 | } |
@@ -4198,7 +4177,7 @@ static int done_word(struct parse_context *ctx) | |||
4198 | #if ENABLE_HUSH_LOOPS | 4177 | #if ENABLE_HUSH_LOOPS |
4199 | if (ctx->ctx_res_w == RES_FOR) { | 4178 | if (ctx->ctx_res_w == RES_FOR) { |
4200 | if (ctx->word.has_quoted_part | 4179 | if (ctx->word.has_quoted_part |
4201 | || !is_well_formed_var_name(command->argv[0], '\0') | 4180 | || endofname(command->argv[0])[0] != '\0' |
4202 | ) { | 4181 | ) { |
4203 | /* bash says just "not a valid identifier" */ | 4182 | /* bash says just "not a valid identifier" */ |
4204 | syntax_error("not a valid identifier in for"); | 4183 | syntax_error("not a valid identifier in for"); |
@@ -4912,6 +4891,7 @@ static int parse_dollar(o_string *as_string, | |||
4912 | case '#': /* number of args */ | 4891 | case '#': /* number of args */ |
4913 | case '*': /* args */ | 4892 | case '*': /* args */ |
4914 | case '@': /* args */ | 4893 | case '@': /* args */ |
4894 | case '-': /* $- option flags set by set builtin or shell options (-i etc) */ | ||
4915 | goto make_one_char_var; | 4895 | goto make_one_char_var; |
4916 | case '{': { | 4896 | case '{': { |
4917 | char len_single_ch; | 4897 | char len_single_ch; |
@@ -5086,11 +5066,10 @@ static int parse_dollar(o_string *as_string, | |||
5086 | case '_': | 5066 | case '_': |
5087 | goto make_var; | 5067 | goto make_var; |
5088 | #if 0 | 5068 | #if 0 |
5089 | /* TODO: $_ and $-: */ | 5069 | /* TODO: $_: */ |
5090 | /* $_ Shell or shell script name; or last argument of last command | 5070 | /* $_ Shell or shell script name; or last argument of last command |
5091 | * (if last command wasn't a pipe; if it was, bash sets $_ to ""); | 5071 | * (if last command wasn't a pipe; if it was, bash sets $_ to ""); |
5092 | * but in command's env, set to full pathname used to invoke it */ | 5072 | * but in command's env, set to full pathname used to invoke it */ |
5093 | /* $- Option flags set by set builtin or shell options (-i etc) */ | ||
5094 | ch = i_getch(input); | 5073 | ch = i_getch(input); |
5095 | nommu_addchr(as_string, ch); | 5074 | nommu_addchr(as_string, ch); |
5096 | ch = i_peek_and_eat_bkslash_nl(input); | 5075 | ch = i_peek_and_eat_bkslash_nl(input); |
@@ -5372,7 +5351,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5372 | if ((ctx.is_assignment == MAYBE_ASSIGNMENT | 5351 | if ((ctx.is_assignment == MAYBE_ASSIGNMENT |
5373 | || ctx.is_assignment == WORD_IS_KEYWORD) | 5352 | || ctx.is_assignment == WORD_IS_KEYWORD) |
5374 | && ch == '=' | 5353 | && ch == '=' |
5375 | && is_well_formed_var_name(ctx.word.data, '=') | 5354 | && endofname(ctx.word.data)[0] == '=' |
5376 | ) { | 5355 | ) { |
5377 | ctx.is_assignment = DEFINITELY_ASSIGNMENT; | 5356 | ctx.is_assignment = DEFINITELY_ASSIGNMENT; |
5378 | debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]); | 5357 | debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]); |
@@ -6119,6 +6098,12 @@ static int encode_then_append_var_plusminus(o_string *output, int n, | |||
6119 | /* string has no special chars | 6098 | /* string has no special chars |
6120 | * && string has no $IFS chars | 6099 | * && string has no $IFS chars |
6121 | */ | 6100 | */ |
6101 | if (dquoted) { | ||
6102 | /* Prints 1 (quoted expansion is a "" word, not nothing): | ||
6103 | * set -- "${notexist-}"; echo $# | ||
6104 | */ | ||
6105 | output->has_quoted_part = 1; | ||
6106 | } | ||
6122 | return expand_vars_to_list(output, n, str); | 6107 | return expand_vars_to_list(output, n, str); |
6123 | } | 6108 | } |
6124 | 6109 | ||
@@ -6415,6 +6400,26 @@ static NOINLINE int expand_one_var(o_string *output, int n, | |||
6415 | case '#': /* argc */ | 6400 | case '#': /* argc */ |
6416 | val = utoa(G.global_argc ? G.global_argc-1 : 0); | 6401 | val = utoa(G.global_argc ? G.global_argc-1 : 0); |
6417 | break; | 6402 | break; |
6403 | case '-': { /* active options */ | ||
6404 | /* Check set_mode() to see what option chars we support */ | ||
6405 | char *cp; | ||
6406 | val = cp = G.optstring_buf; | ||
6407 | if (G.o_opt[OPT_O_ERREXIT]) | ||
6408 | *cp++ = 'e'; | ||
6409 | if (G_interactive_fd) | ||
6410 | *cp++ = 'i'; | ||
6411 | if (G_x_mode) | ||
6412 | *cp++ = 'x'; | ||
6413 | /* If G.o_opt[OPT_O_NOEXEC] is true, | ||
6414 | * commands read but are not executed, | ||
6415 | * so $- can not execute too, 'n' is never seen in $-. | ||
6416 | */ | ||
6417 | if (G.opt_s) | ||
6418 | *cp++ = 's'; | ||
6419 | //TODO: show 'c' if executed via "hush -c 'CMDS'" (bash only, not ash) | ||
6420 | *cp = '\0'; | ||
6421 | break; | ||
6422 | } | ||
6418 | default: | 6423 | default: |
6419 | val = get_local_var_value(var); | 6424 | val = get_local_var_value(var); |
6420 | } | 6425 | } |
@@ -7275,22 +7280,22 @@ static void parse_and_run_stream(struct in_str *inp, int end_trigger) | |||
7275 | static void parse_and_run_string(const char *s) | 7280 | static void parse_and_run_string(const char *s) |
7276 | { | 7281 | { |
7277 | struct in_str input; | 7282 | struct in_str input; |
7278 | //IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;) | 7283 | //IF_HUSH_LINENO_VAR(unsigned sv = G.parse_lineno;) |
7279 | 7284 | ||
7280 | setup_string_in_str(&input, s); | 7285 | setup_string_in_str(&input, s); |
7281 | parse_and_run_stream(&input, '\0'); | 7286 | parse_and_run_stream(&input, '\0'); |
7282 | //IF_HUSH_LINENO_VAR(G.lineno = sv;) | 7287 | //IF_HUSH_LINENO_VAR(G.parse_lineno = sv;) |
7283 | } | 7288 | } |
7284 | 7289 | ||
7285 | static void parse_and_run_file(HFILE *fp) | 7290 | static void parse_and_run_file(HFILE *fp) |
7286 | { | 7291 | { |
7287 | struct in_str input; | 7292 | struct in_str input; |
7288 | IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;) | 7293 | IF_HUSH_LINENO_VAR(unsigned sv = G.parse_lineno;) |
7289 | 7294 | ||
7290 | IF_HUSH_LINENO_VAR(G.lineno = 1;) | 7295 | IF_HUSH_LINENO_VAR(G.parse_lineno = 1;) |
7291 | setup_file_in_str(&input, fp); | 7296 | setup_file_in_str(&input, fp); |
7292 | parse_and_run_stream(&input, ';'); | 7297 | parse_and_run_stream(&input, ';'); |
7293 | IF_HUSH_LINENO_VAR(G.lineno = sv;) | 7298 | IF_HUSH_LINENO_VAR(G.parse_lineno = sv;) |
7294 | } | 7299 | } |
7295 | 7300 | ||
7296 | #if ENABLE_HUSH_TICK | 7301 | #if ENABLE_HUSH_TICK |
@@ -7598,10 +7603,10 @@ static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp) | |||
7598 | avoid_fd = 9; | 7603 | avoid_fd = 9; |
7599 | 7604 | ||
7600 | #if ENABLE_HUSH_INTERACTIVE | 7605 | #if ENABLE_HUSH_INTERACTIVE |
7601 | if (fd == G.interactive_fd) { | 7606 | if (fd == G_interactive_fd) { |
7602 | /* Testcase: "ls -l /proc/$$/fd 255>&-" should work */ | 7607 | /* Testcase: "ls -l /proc/$$/fd 255>&-" should work */ |
7603 | G.interactive_fd = xdup_CLOEXEC_and_close(G.interactive_fd, avoid_fd); | 7608 | G_interactive_fd = xdup_CLOEXEC_and_close(G_interactive_fd, avoid_fd); |
7604 | debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G.interactive_fd); | 7609 | debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G_interactive_fd); |
7605 | return 1; /* "we closed fd" */ | 7610 | return 1; /* "we closed fd" */ |
7606 | } | 7611 | } |
7607 | #endif | 7612 | #endif |
@@ -7677,7 +7682,7 @@ static void restore_redirects(struct squirrel *sq) | |||
7677 | free(sq); | 7682 | free(sq); |
7678 | } | 7683 | } |
7679 | 7684 | ||
7680 | /* If moved, G.interactive_fd stays on new fd, not restoring it */ | 7685 | /* If moved, G_interactive_fd stays on new fd, not restoring it */ |
7681 | } | 7686 | } |
7682 | 7687 | ||
7683 | #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU | 7688 | #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU |
@@ -7694,7 +7699,7 @@ static int internally_opened_fd(int fd, struct squirrel *sq) | |||
7694 | int i; | 7699 | int i; |
7695 | 7700 | ||
7696 | #if ENABLE_HUSH_INTERACTIVE | 7701 | #if ENABLE_HUSH_INTERACTIVE |
7697 | if (fd == G.interactive_fd) | 7702 | if (fd == G_interactive_fd) |
7698 | return 1; | 7703 | return 1; |
7699 | #endif | 7704 | #endif |
7700 | /* If this one of script's fds? */ | 7705 | /* If this one of script's fds? */ |
@@ -8989,8 +8994,7 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8989 | struct variable *old_vars; | 8994 | struct variable *old_vars; |
8990 | 8995 | ||
8991 | #if ENABLE_HUSH_LINENO_VAR | 8996 | #if ENABLE_HUSH_LINENO_VAR |
8992 | if (G.lineno_var) | 8997 | G.execute_lineno = command->lineno; |
8993 | strcpy(G.lineno_var + sizeof("LINENO=")-1, utoa(command->lineno)); | ||
8994 | #endif | 8998 | #endif |
8995 | 8999 | ||
8996 | if (argv[command->assignment_cnt] == NULL) { | 9000 | if (argv[command->assignment_cnt] == NULL) { |
@@ -9223,8 +9227,7 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
9223 | xpiped_pair(pipefds); | 9227 | xpiped_pair(pipefds); |
9224 | 9228 | ||
9225 | #if ENABLE_HUSH_LINENO_VAR | 9229 | #if ENABLE_HUSH_LINENO_VAR |
9226 | if (G.lineno_var) | 9230 | G.execute_lineno = command->lineno; |
9227 | strcpy(G.lineno_var + sizeof("LINENO=")-1, utoa(command->lineno)); | ||
9228 | #endif | 9231 | #endif |
9229 | 9232 | ||
9230 | command->pid = BB_MMU ? fork() : vfork(); | 9233 | command->pid = BB_MMU ? fork() : vfork(); |
@@ -9908,14 +9911,6 @@ int hush_main(int argc, char **argv) | |||
9908 | /* Export PWD */ | 9911 | /* Export PWD */ |
9909 | set_pwd_var(SETFLAG_EXPORT); | 9912 | set_pwd_var(SETFLAG_EXPORT); |
9910 | 9913 | ||
9911 | #if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT | ||
9912 | /* Set (but not export) PS1/2 unless already set */ | ||
9913 | if (!get_local_var_value("PS1")) | ||
9914 | set_local_var_from_halves("PS1", "\\w \\$ "); | ||
9915 | if (!get_local_var_value("PS2")) | ||
9916 | set_local_var_from_halves("PS2", "> "); | ||
9917 | #endif | ||
9918 | |||
9919 | #if BASH_HOSTNAME_VAR | 9914 | #if BASH_HOSTNAME_VAR |
9920 | /* Set (but not export) HOSTNAME unless already set */ | 9915 | /* Set (but not export) HOSTNAME unless already set */ |
9921 | if (!get_local_var_value("HOSTNAME")) { | 9916 | if (!get_local_var_value("HOSTNAME")) { |
@@ -9927,6 +9922,11 @@ int hush_main(int argc, char **argv) | |||
9927 | /* IFS is not inherited from the parent environment */ | 9922 | /* IFS is not inherited from the parent environment */ |
9928 | set_local_var_from_halves("IFS", defifs); | 9923 | set_local_var_from_halves("IFS", defifs); |
9929 | 9924 | ||
9925 | if (!get_local_var_value("PATH")) | ||
9926 | set_local_var_from_halves("PATH", bb_default_root_path); | ||
9927 | |||
9928 | /* PS1/PS2 are set later, if we determine that we are interactive */ | ||
9929 | |||
9930 | /* bash also exports SHLVL and _, | 9930 | /* bash also exports SHLVL and _, |
9931 | * and sets (but doesn't export) the following variables: | 9931 | * and sets (but doesn't export) the following variables: |
9932 | * BASH=/bin/bash | 9932 | * BASH=/bin/bash |
@@ -9960,21 +9960,7 @@ int hush_main(int argc, char **argv) | |||
9960 | * PS4='+ ' | 9960 | * PS4='+ ' |
9961 | */ | 9961 | */ |
9962 | 9962 | ||
9963 | #if ENABLE_HUSH_LINENO_VAR | ||
9964 | if (ENABLE_HUSH_LINENO_VAR) { | ||
9965 | char *p = xasprintf("LINENO=%*s", (int)(sizeof(int)*3), ""); | ||
9966 | set_local_var(p, /*flags*/ 0); | ||
9967 | G.lineno_var = p; /* can't assign before set_local_var("LINENO=...") */ | ||
9968 | } | ||
9969 | #endif | ||
9970 | |||
9971 | #if ENABLE_FEATURE_EDITING | ||
9972 | G.line_input_state = new_line_input_t(FOR_SHELL); | ||
9973 | #endif | ||
9974 | |||
9975 | /* Initialize some more globals to non-zero values */ | 9963 | /* Initialize some more globals to non-zero values */ |
9976 | cmdedit_update_prompt(); | ||
9977 | |||
9978 | die_func = restore_ttypgrp_and__exit; | 9964 | die_func = restore_ttypgrp_and__exit; |
9979 | 9965 | ||
9980 | /* Shell is non-interactive at first. We need to call | 9966 | /* Shell is non-interactive at first. We need to call |
@@ -10192,6 +10178,7 @@ int hush_main(int argc, char **argv) | |||
10192 | #endif | 10178 | #endif |
10193 | goto final_return; | 10179 | goto final_return; |
10194 | } | 10180 | } |
10181 | G.opt_s = 1; | ||
10195 | 10182 | ||
10196 | /* Up to here, shell was non-interactive. Now it may become one. | 10183 | /* Up to here, shell was non-interactive. Now it may become one. |
10197 | * NB: don't forget to (re)run install_special_sighandlers() as needed. | 10184 | * NB: don't forget to (re)run install_special_sighandlers() as needed. |
@@ -10260,6 +10247,9 @@ int hush_main(int argc, char **argv) | |||
10260 | } | 10247 | } |
10261 | enable_restore_tty_pgrp_on_exit(); | 10248 | enable_restore_tty_pgrp_on_exit(); |
10262 | 10249 | ||
10250 | # if ENABLE_FEATURE_EDITING | ||
10251 | G.line_input_state = new_line_input_t(FOR_SHELL); | ||
10252 | # endif | ||
10263 | # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 | 10253 | # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 |
10264 | { | 10254 | { |
10265 | const char *hp = get_local_var_value("HISTFILE"); | 10255 | const char *hp = get_local_var_value("HISTFILE"); |
@@ -10308,14 +10298,23 @@ int hush_main(int argc, char **argv) | |||
10308 | * (--norc turns this off, --rcfile <file> overrides) | 10298 | * (--norc turns this off, --rcfile <file> overrides) |
10309 | */ | 10299 | */ |
10310 | 10300 | ||
10311 | if (!ENABLE_FEATURE_SH_EXTRA_QUIET && G_interactive_fd) { | 10301 | if (G_interactive_fd) { |
10312 | /* note: ash and hush share this string */ | 10302 | #if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT |
10313 | printf("\n\n%s %s\n" | 10303 | /* Set (but not export) PS1/2 unless already set */ |
10314 | IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n") | 10304 | if (!get_local_var_value("PS1")) |
10315 | "\n", | 10305 | set_local_var_from_halves("PS1", "\\w \\$ "); |
10316 | bb_banner, | 10306 | if (!get_local_var_value("PS2")) |
10317 | "hush - the humble shell" | 10307 | set_local_var_from_halves("PS2", "> "); |
10318 | ); | 10308 | #endif |
10309 | if (!ENABLE_FEATURE_SH_EXTRA_QUIET) { | ||
10310 | /* note: ash and hush share this string */ | ||
10311 | printf("\n\n%s %s\n" | ||
10312 | IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n") | ||
10313 | "\n", | ||
10314 | bb_banner, | ||
10315 | "hush - the humble shell" | ||
10316 | ); | ||
10317 | } | ||
10319 | } | 10318 | } |
10320 | 10319 | ||
10321 | parse_and_run_file(hfopen(NULL)); /* stdin */ | 10320 | parse_and_run_file(hfopen(NULL)); /* stdin */ |
@@ -10378,7 +10377,8 @@ static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) | |||
10378 | #if MAX_HISTORY && ENABLE_FEATURE_EDITING | 10377 | #if MAX_HISTORY && ENABLE_FEATURE_EDITING |
10379 | static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM) | 10378 | static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM) |
10380 | { | 10379 | { |
10381 | show_history(G.line_input_state); | 10380 | if (G.line_input_state) |
10381 | show_history(G.line_input_state); | ||
10382 | return EXIT_SUCCESS; | 10382 | return EXIT_SUCCESS; |
10383 | } | 10383 | } |
10384 | #endif | 10384 | #endif |
@@ -10687,9 +10687,7 @@ static int helper_export_local(char **argv, unsigned flags) | |||
10687 | { | 10687 | { |
10688 | do { | 10688 | do { |
10689 | char *name = *argv; | 10689 | char *name = *argv; |
10690 | char *name_end = strchrnul(name, '='); | 10690 | const char *name_end = endofname(name); |
10691 | |||
10692 | /* So far we do not check that name is valid (TODO?) */ | ||
10693 | 10691 | ||
10694 | if (*name_end == '\0') { | 10692 | if (*name_end == '\0') { |
10695 | struct variable *var, **vpp; | 10693 | struct variable *var, **vpp; |
@@ -10747,8 +10745,15 @@ static int helper_export_local(char **argv, unsigned flags) | |||
10747 | */ | 10745 | */ |
10748 | name = xasprintf("%s=", name); | 10746 | name = xasprintf("%s=", name); |
10749 | } else { | 10747 | } else { |
10748 | if (*name_end != '=') { | ||
10749 | bb_error_msg("'%s': bad variable name", name); | ||
10750 | /* do not parse following argv[]s: */ | ||
10751 | return 1; | ||
10752 | } | ||
10750 | /* (Un)exporting/making local NAME=VALUE */ | 10753 | /* (Un)exporting/making local NAME=VALUE */ |
10751 | name = xstrdup(name); | 10754 | name = xstrdup(name); |
10755 | /* Testcase: export PS1='\w \$ ' */ | ||
10756 | unbackslash(name); | ||
10752 | } | 10757 | } |
10753 | debug_printf_env("%s: set_local_var('%s')\n", __func__, name); | 10758 | debug_printf_env("%s: set_local_var('%s')\n", __func__, name); |
10754 | if (set_local_var(name, flags)) | 10759 | if (set_local_var(name, flags)) |
diff --git a/shell/hush_test/hush-misc/export1.right b/shell/hush_test/hush-misc/export1.right new file mode 100644 index 000000000..56647af8e --- /dev/null +++ b/shell/hush_test/hush-misc/export1.right | |||
@@ -0,0 +1 @@ | |||
|\w \\ \ \| | |||
diff --git a/shell/hush_test/hush-misc/export1.tests b/shell/hush_test/hush-misc/export1.tests new file mode 100755 index 000000000..4ffb40bdc --- /dev/null +++ b/shell/hush_test/hush-misc/export1.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | export Z='\w \\ \ \' | ||
2 | echo "|$Z|" | ||
diff --git a/shell/hush_test/hush-vars/param_expand_default.right b/shell/hush_test/hush-vars/param_expand_default.right index acc717205..8bd0814b0 100644 --- a/shell/hush_test/hush-vars/param_expand_default.right +++ b/shell/hush_test/hush-vars/param_expand_default.right | |||
@@ -1,8 +1,9 @@ | |||
1 | hush: syntax error: unterminated ${name} | 1 | hush: syntax error: unterminated ${name} |
2 | hush: syntax error: unterminated ${name} | ||
3 | _0 _0 | 2 | _0 _0 |
4 | _ _ _ _word _word | 3 | _ _ _ _word _word |
5 | _aaaa _aaaa _aaaa _aaaa _aaaa | 4 | _aaaa _aaaa _aaaa _aaaa _aaaa |
6 | _ _ _ _word _word | 5 | _ _ _ _word _word |
7 | _ _ _ _ _word | 6 | _ _ _ _ _word |
8 | _fff _fff _fff _fff _fff | 7 | _fff _fff _fff _fff _fff |
8 | 1:1 | ||
9 | 0:0 | ||
diff --git a/shell/hush_test/hush-vars/param_expand_default.tests b/shell/hush_test/hush-vars/param_expand_default.tests index 16e5f8efe..dbd3e2218 100755 --- a/shell/hush_test/hush-vars/param_expand_default.tests +++ b/shell/hush_test/hush-vars/param_expand_default.tests | |||
@@ -1,7 +1,5 @@ | |||
1 | # first try some invalid patterns (do in subshell due to parsing error) | 1 | # first try some invalid patterns (do in subshell due to parsing error) |
2 | # (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages) | 2 | # (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages) |
3 | # valid in bash and ash (same as $-), not supported in hush (yet?): | ||
4 | "$THIS_SH" -c 'echo ${-}' SHELL | ||
5 | "$THIS_SH" -c 'echo ${:-}' SHELL | 3 | "$THIS_SH" -c 'echo ${:-}' SHELL |
6 | 4 | ||
7 | # now some funky ones | 5 | # now some funky ones |
@@ -22,3 +20,8 @@ echo _$f _${f-} _${f:-} _${f-word} _${f:-word} | |||
22 | 20 | ||
23 | f=fff | 21 | f=fff |
24 | echo _$f _${f-} _${f:-} _${f-word} _${f:-word} | 22 | echo _$f _${f-} _${f:-} _${f-word} _${f:-word} |
23 | |||
24 | set -- | ||
25 | set -- "${1-}"; echo 1:$# | ||
26 | set -- | ||
27 | set -- ${1-}; echo 0:$# | ||
diff --git a/shell/math.c b/shell/math.c index 611b3beab..eaf4f2453 100644 --- a/shell/math.c +++ b/shell/math.c | |||
@@ -513,6 +513,46 @@ static const char op_tokens[] ALIGN1 = { | |||
513 | }; | 513 | }; |
514 | #define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7]) | 514 | #define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7]) |
515 | 515 | ||
516 | #if ENABLE_FEATURE_SH_MATH_BASE | ||
517 | static arith_t strto_arith_t(const char *nptr, char **endptr) | ||
518 | { | ||
519 | unsigned base; | ||
520 | arith_t n; | ||
521 | |||
522 | # if ENABLE_FEATURE_SH_MATH_64 | ||
523 | n = strtoull(nptr, endptr, 0); | ||
524 | # else | ||
525 | n = strtoul(nptr, endptr, 0); | ||
526 | # endif | ||
527 | if (**endptr != '#' | ||
528 | || (*nptr < '1' || *nptr > '9') | ||
529 | || (n < 2 || n > 64) | ||
530 | ) { | ||
531 | return n; | ||
532 | } | ||
533 | |||
534 | /* It's "N#nnnn" or "NN#nnnn" syntax, NN can't start with 0, | ||
535 | * NN is in 2..64 range. | ||
536 | */ | ||
537 | base = (unsigned)n; | ||
538 | n = 0; | ||
539 | nptr = *endptr + 1; | ||
540 | /* bash allows "N#" (empty "nnnn" part) */ | ||
541 | while (isdigit(*nptr)) { | ||
542 | /* bash does not check for overflows */ | ||
543 | n = n * base + (*nptr++ - '0'); | ||
544 | } | ||
545 | *endptr = (char*)nptr; | ||
546 | return n; | ||
547 | } | ||
548 | #else /* !ENABLE_FEATURE_SH_MATH_BASE */ | ||
549 | # if ENABLE_FEATURE_SH_MATH_64 | ||
550 | # define strto_arith_t(nptr, endptr) strtoull(nptr, endptr, 0) | ||
551 | # else | ||
552 | # define strto_arith_t(nptr, endptr) strtoul(nptr, endptr, 0) | ||
553 | # endif | ||
554 | #endif | ||
555 | |||
516 | static arith_t FAST_FUNC | 556 | static arith_t FAST_FUNC |
517 | evaluate_string(arith_state_t *math_state, const char *expr) | 557 | evaluate_string(arith_state_t *math_state, const char *expr) |
518 | { | 558 | { |
@@ -591,7 +631,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
591 | /* Number */ | 631 | /* Number */ |
592 | numstackptr->var = NULL; | 632 | numstackptr->var = NULL; |
593 | errno = 0; | 633 | errno = 0; |
594 | numstackptr->val = strto_arith_t(expr, (char**) &expr, 0); | 634 | numstackptr->val = strto_arith_t(expr, (char**) &expr); |
595 | if (errno) | 635 | if (errno) |
596 | numstackptr->val = 0; /* bash compat */ | 636 | numstackptr->val = 0; /* bash compat */ |
597 | goto num; | 637 | goto num; |
diff --git a/shell/math.h b/shell/math.h index 90eb49144..a3fe51b6b 100644 --- a/shell/math.h +++ b/shell/math.h | |||
@@ -66,11 +66,9 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |||
66 | #if ENABLE_FEATURE_SH_MATH_64 | 66 | #if ENABLE_FEATURE_SH_MATH_64 |
67 | typedef long long arith_t; | 67 | typedef long long arith_t; |
68 | #define ARITH_FMT "%"LL_FMT"d" | 68 | #define ARITH_FMT "%"LL_FMT"d" |
69 | #define strto_arith_t strtoull | ||
70 | #else | 69 | #else |
71 | typedef long arith_t; | 70 | typedef long arith_t; |
72 | #define ARITH_FMT "%ld" | 71 | # define ARITH_FMT "%ld" |
73 | #define strto_arith_t strtoul | ||
74 | #endif | 72 | #endif |
75 | 73 | ||
76 | typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); | 74 | typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); |
diff --git a/shell/shell_common.c b/shell/shell_common.c index 70ecf2095..d1df5888c 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
@@ -26,19 +26,6 @@ const char defifsvar[] ALIGN1 = "IFS= \t\n\r"; | |||
26 | #endif | 26 | #endif |
27 | const char defoptindvar[] ALIGN1 = "OPTIND=1"; | 27 | const char defoptindvar[] ALIGN1 = "OPTIND=1"; |
28 | 28 | ||
29 | |||
30 | int FAST_FUNC is_well_formed_var_name(const char *s, char terminator) | ||
31 | { | ||
32 | if (!s || !(isalpha(*s) || *s == '_')) | ||
33 | return 0; | ||
34 | |||
35 | do | ||
36 | s++; | ||
37 | while (isalnum(*s) || *s == '_'); | ||
38 | |||
39 | return *s == terminator; | ||
40 | } | ||
41 | |||
42 | /* read builtin */ | 29 | /* read builtin */ |
43 | 30 | ||
44 | /* Needs to be interruptible: shell must handle traps and shell-special signals | 31 | /* Needs to be interruptible: shell must handle traps and shell-special signals |
@@ -76,7 +63,7 @@ shell_builtin_read(struct builtin_read_params *params) | |||
76 | argv = params->argv; | 63 | argv = params->argv; |
77 | pp = argv; | 64 | pp = argv; |
78 | while (*pp) { | 65 | while (*pp) { |
79 | if (!is_well_formed_var_name(*pp, '\0')) { | 66 | if (endofname(*pp)[0] != '\0') { |
80 | /* Mimic bash message */ | 67 | /* Mimic bash message */ |
81 | bb_error_msg("read: '%s': not a valid identifier", *pp); | 68 | bb_error_msg("read: '%s': not a valid identifier", *pp); |
82 | return (const char *)(uintptr_t)1; | 69 | return (const char *)(uintptr_t)1; |
@@ -384,99 +371,138 @@ shell_builtin_read(struct builtin_read_params *params) | |||
384 | struct limits { | 371 | struct limits { |
385 | uint8_t cmd; /* RLIMIT_xxx fit into it */ | 372 | uint8_t cmd; /* RLIMIT_xxx fit into it */ |
386 | uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */ | 373 | uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */ |
387 | char option; | ||
388 | const char *name; | 374 | const char *name; |
389 | }; | 375 | }; |
390 | 376 | ||
391 | static const struct limits limits_tbl[] = { | 377 | static const struct limits limits_tbl[] = { |
392 | #ifdef RLIMIT_FSIZE | 378 | { RLIMIT_CORE, 9, "core file size (blocks)" }, // -c |
393 | { RLIMIT_FSIZE, 9, 'f', "file size (blocks)" }, | 379 | { RLIMIT_DATA, 10, "data seg size (kb)" }, // -d |
380 | { RLIMIT_NICE, 0, "scheduling priority" }, // -e | ||
381 | { RLIMIT_FSIZE, 9, "file size (blocks)" }, // -f | ||
382 | #define LIMIT_F_IDX 3 | ||
383 | #ifdef RLIMIT_SIGPENDING | ||
384 | { RLIMIT_SIGPENDING, 0, "pending signals" }, // -i | ||
394 | #endif | 385 | #endif |
395 | #ifdef RLIMIT_CPU | 386 | #ifdef RLIMIT_MEMLOCK |
396 | { RLIMIT_CPU, 0, 't', "cpu time (seconds)" }, | 387 | { RLIMIT_MEMLOCK, 10, "max locked memory (kb)" }, // -l |
397 | #endif | 388 | #endif |
398 | #ifdef RLIMIT_DATA | 389 | #ifdef RLIMIT_RSS |
399 | { RLIMIT_DATA, 10, 'd', "data seg size (kb)" }, | 390 | { RLIMIT_RSS, 10, "max memory size (kb)" }, // -m |
400 | #endif | 391 | #endif |
401 | #ifdef RLIMIT_STACK | 392 | #ifdef RLIMIT_NOFILE |
402 | { RLIMIT_STACK, 10, 's', "stack size (kb)" }, | 393 | { RLIMIT_NOFILE, 0, "open files" }, // -n |
403 | #endif | 394 | #endif |
404 | #ifdef RLIMIT_CORE | 395 | #ifdef RLIMIT_MSGQUEUE |
405 | { RLIMIT_CORE, 9, 'c', "core file size (blocks)" }, | 396 | { RLIMIT_MSGQUEUE, 0, "POSIX message queues (bytes)" }, // -q |
406 | #endif | 397 | #endif |
407 | #ifdef RLIMIT_RSS | 398 | #ifdef RLIMIT_RTPRIO |
408 | { RLIMIT_RSS, 10, 'm', "resident set size (kb)" }, | 399 | { RLIMIT_RTPRIO, 0, "real-time priority" }, // -r |
409 | #endif | 400 | #endif |
410 | #ifdef RLIMIT_MEMLOCK | 401 | #ifdef RLIMIT_STACK |
411 | { RLIMIT_MEMLOCK, 10, 'l', "locked memory (kb)" }, | 402 | { RLIMIT_STACK, 10, "stack size (kb)" }, // -s |
412 | #endif | 403 | #endif |
413 | #ifdef RLIMIT_NPROC | 404 | #ifdef RLIMIT_CPU |
414 | { RLIMIT_NPROC, 0, 'p', "processes" }, | 405 | { RLIMIT_CPU, 0, "cpu time (seconds)" }, // -t |
415 | #endif | 406 | #endif |
416 | #ifdef RLIMIT_NOFILE | 407 | #ifdef RLIMIT_NPROC |
417 | { RLIMIT_NOFILE, 0, 'n', "file descriptors" }, | 408 | { RLIMIT_NPROC, 0, "max user processes" }, // -u |
418 | #endif | 409 | #endif |
419 | #ifdef RLIMIT_AS | 410 | #ifdef RLIMIT_AS |
420 | { RLIMIT_AS, 10, 'v', "address space (kb)" }, | 411 | { RLIMIT_AS, 10, "virtual memory (kb)" }, // -v |
421 | #endif | 412 | #endif |
422 | #ifdef RLIMIT_LOCKS | 413 | #ifdef RLIMIT_LOCKS |
423 | { RLIMIT_LOCKS, 0, 'w', "locks" }, | 414 | { RLIMIT_LOCKS, 0, "file locks" }, // -x |
415 | #endif | ||
416 | }; | ||
417 | // bash also shows: | ||
418 | //pipe size (512 bytes, -p) 8 | ||
419 | |||
420 | static const char limit_chars[] ALIGN1 = | ||
421 | "c" | ||
422 | "d" | ||
423 | "e" | ||
424 | "f" | ||
425 | #ifdef RLIMIT_SIGPENDING | ||
426 | "i" | ||
427 | #endif | ||
428 | #ifdef RLIMIT_MEMLOCK | ||
429 | "l" | ||
430 | #endif | ||
431 | #ifdef RLIMIT_RSS | ||
432 | "m" | ||
433 | #endif | ||
434 | #ifdef RLIMIT_NOFILE | ||
435 | "n" | ||
424 | #endif | 436 | #endif |
425 | #ifdef RLIMIT_NICE | 437 | #ifdef RLIMIT_MSGQUEUE |
426 | { RLIMIT_NICE, 0, 'e', "scheduling priority" }, | 438 | "q" |
427 | #endif | 439 | #endif |
428 | #ifdef RLIMIT_RTPRIO | 440 | #ifdef RLIMIT_RTPRIO |
429 | { RLIMIT_RTPRIO, 0, 'r', "real-time priority" }, | 441 | "r" |
430 | #endif | 442 | #endif |
431 | }; | 443 | #ifdef RLIMIT_STACK |
432 | 444 | "s" | |
433 | enum { | ||
434 | OPT_hard = (1 << 0), | ||
435 | OPT_soft = (1 << 1), | ||
436 | }; | ||
437 | |||
438 | /* "-": treat args as parameters of option with ASCII code 1 */ | ||
439 | static const char ulimit_opt_string[] ALIGN1 = "-HSa" | ||
440 | #ifdef RLIMIT_FSIZE | ||
441 | "f::" | ||
442 | #endif | 445 | #endif |
443 | #ifdef RLIMIT_CPU | 446 | #ifdef RLIMIT_CPU |
444 | "t::" | 447 | "t" |
445 | #endif | 448 | #endif |
446 | #ifdef RLIMIT_DATA | 449 | #ifdef RLIMIT_NPROC |
447 | "d::" | 450 | "u" |
448 | #endif | 451 | #endif |
449 | #ifdef RLIMIT_STACK | 452 | #ifdef RLIMIT_AS |
450 | "s::" | 453 | "v" |
451 | #endif | 454 | #endif |
452 | #ifdef RLIMIT_CORE | 455 | #ifdef RLIMIT_LOCKS |
453 | "c::" | 456 | "x" |
454 | #endif | 457 | #endif |
455 | #ifdef RLIMIT_RSS | 458 | ; |
456 | "m::" | 459 | |
460 | /* "-": treat args as parameters of option with ASCII code 1 */ | ||
461 | static const char ulimit_opt_string[] ALIGN1 = "-HSa" | ||
462 | "c::" | ||
463 | "d::" | ||
464 | "e::" | ||
465 | "f::" | ||
466 | #ifdef RLIMIT_SIGPENDING | ||
467 | "i::" | ||
457 | #endif | 468 | #endif |
458 | #ifdef RLIMIT_MEMLOCK | 469 | #ifdef RLIMIT_MEMLOCK |
459 | "l::" | 470 | "l::" |
460 | #endif | 471 | #endif |
461 | #ifdef RLIMIT_NPROC | 472 | #ifdef RLIMIT_RSS |
462 | "p::" | 473 | "m::" |
463 | #endif | 474 | #endif |
464 | #ifdef RLIMIT_NOFILE | 475 | #ifdef RLIMIT_NOFILE |
465 | "n::" | 476 | "n::" |
466 | #endif | 477 | #endif |
478 | #ifdef RLIMIT_MSGQUEUE | ||
479 | "q::" | ||
480 | #endif | ||
481 | #ifdef RLIMIT_RTPRIO | ||
482 | "r::" | ||
483 | #endif | ||
484 | #ifdef RLIMIT_STACK | ||
485 | "s::" | ||
486 | #endif | ||
487 | #ifdef RLIMIT_CPU | ||
488 | "t::" | ||
489 | #endif | ||
490 | #ifdef RLIMIT_NPROC | ||
491 | "u::" | ||
492 | #endif | ||
467 | #ifdef RLIMIT_AS | 493 | #ifdef RLIMIT_AS |
468 | "v::" | 494 | "v::" |
469 | #endif | 495 | #endif |
470 | #ifdef RLIMIT_LOCKS | 496 | #ifdef RLIMIT_LOCKS |
471 | "w::" | 497 | "x::" |
472 | #endif | ||
473 | #ifdef RLIMIT_NICE | ||
474 | "e::" | ||
475 | #endif | ||
476 | #ifdef RLIMIT_RTPRIO | ||
477 | "r::" | ||
478 | #endif | 498 | #endif |
479 | ; | 499 | ; |
500 | |||
501 | enum { | ||
502 | OPT_hard = (1 << 0), | ||
503 | OPT_soft = (1 << 1), | ||
504 | OPT_all = (1 << 2), | ||
505 | }; | ||
480 | 506 | ||
481 | static void printlim(unsigned opts, const struct rlimit *limit, | 507 | static void printlim(unsigned opts, const struct rlimit *limit, |
482 | const struct limits *l) | 508 | const struct limits *l) |
@@ -484,7 +510,7 @@ static void printlim(unsigned opts, const struct rlimit *limit, | |||
484 | rlim_t val; | 510 | rlim_t val; |
485 | 511 | ||
486 | val = limit->rlim_max; | 512 | val = limit->rlim_max; |
487 | if (!(opts & OPT_hard)) | 513 | if (opts & OPT_soft) |
488 | val = limit->rlim_cur; | 514 | val = limit->rlim_cur; |
489 | 515 | ||
490 | if (val == RLIM_INFINITY) | 516 | if (val == RLIM_INFINITY) |
@@ -498,8 +524,11 @@ static void printlim(unsigned opts, const struct rlimit *limit, | |||
498 | int FAST_FUNC | 524 | int FAST_FUNC |
499 | shell_builtin_ulimit(char **argv) | 525 | shell_builtin_ulimit(char **argv) |
500 | { | 526 | { |
527 | struct rlimit limit; | ||
528 | unsigned opt_cnt; | ||
501 | unsigned opts; | 529 | unsigned opts; |
502 | unsigned argc; | 530 | unsigned argc; |
531 | unsigned i; | ||
503 | 532 | ||
504 | /* We can't use getopt32: need to handle commands like | 533 | /* We can't use getopt32: need to handle commands like |
505 | * ulimit 123 -c2 -l 456 | 534 | * ulimit 123 -c2 -l 456 |
@@ -510,12 +539,48 @@ shell_builtin_ulimit(char **argv) | |||
510 | */ | 539 | */ |
511 | GETOPT_RESET(); | 540 | GETOPT_RESET(); |
512 | 541 | ||
542 | // bash 4.4.23: | ||
543 | // | ||
544 | // -H and/or -S change meaning even of options *before* them: ulimit -f 2000 -H | ||
545 | // sets hard limit, ulimit -a -H prints hard limits. | ||
546 | // | ||
547 | // -a is equivalent for requesting all limits to be shown. | ||
548 | // | ||
549 | // If -a is specified, attempts to set limits are ignored: | ||
550 | // ulimit -m 1000; ulimit -m 2000 -a | ||
551 | // shows 1000, not 2000. HOWEVER, *implicit* -f form "ulimit 2000 -a" | ||
552 | // DOES set -f limit [we don't implement this quirk], "ulimit -a 2000" does not. | ||
553 | // Options are still parsed: ulimit -az complains about unknown -z opt. | ||
554 | // | ||
555 | // -a is not cumulative: "ulimit -a -a" = "ulimit -a -f -m" = "ulimit -a" | ||
556 | // | ||
557 | // -HSa can be combined in one argument and with one other option (example: -Sm), | ||
558 | // but other options can't: limit value is an optional argument, | ||
559 | // thus "-mf" means "-m f", f is the parameter of -m. | ||
560 | // | ||
561 | // Limit can be set and then printed: ulimit -m 2000 -m | ||
562 | // If set more than once, they are set and printed in order: | ||
563 | // try ulimit -m -m 1000 -m -m 2000 -m -m 3000 -m | ||
564 | // | ||
565 | // Limits are shown in the order of options given: | ||
566 | // ulimit -m -f is not the same as ulimit -f -m. | ||
567 | // | ||
568 | // If both -S and -H are given, show soft limit. | ||
569 | // | ||
570 | // Short printout (limit value only) is printed only if just one option | ||
571 | // is given: ulimit -m. ulimit -f -m prints verbose lines. | ||
572 | // ulimit -f -f prints same verbose line twice. | ||
573 | // ulimit -m 10000 -f prints verbose line for -f. | ||
574 | |||
513 | argc = string_array_len(argv); | 575 | argc = string_array_len(argv); |
514 | 576 | ||
577 | /* First pass over options: detect -H/-S/-a status, | ||
578 | * and "bare ulimit" and "only one option" cases | ||
579 | * by counting other opts. | ||
580 | */ | ||
581 | opt_cnt = 0; | ||
515 | opts = 0; | 582 | opts = 0; |
516 | while (1) { | 583 | while (1) { |
517 | struct rlimit limit; | ||
518 | const struct limits *l; | ||
519 | int opt_char = getopt(argc, argv, ulimit_opt_string); | 584 | int opt_char = getopt(argc, argv, ulimit_opt_string); |
520 | 585 | ||
521 | if (opt_char == -1) | 586 | if (opt_char == -1) |
@@ -528,74 +593,94 @@ shell_builtin_ulimit(char **argv) | |||
528 | opts |= OPT_soft; | 593 | opts |= OPT_soft; |
529 | continue; | 594 | continue; |
530 | } | 595 | } |
531 | |||
532 | if (opt_char == 'a') { | 596 | if (opt_char == 'a') { |
533 | for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) { | 597 | opts |= OPT_all; |
534 | getrlimit(l->cmd, &limit); | ||
535 | printf("-%c: %-30s ", l->option, l->name); | ||
536 | printlim(opts, &limit, l); | ||
537 | } | ||
538 | continue; | 598 | continue; |
539 | } | 599 | } |
600 | if (opt_char == '?') { | ||
601 | /* bad option. getopt already complained. */ | ||
602 | return EXIT_FAILURE; | ||
603 | } | ||
604 | opt_cnt++; | ||
605 | } /* while (there are options) */ | ||
606 | |||
607 | if (!(opts & (OPT_hard | OPT_soft))) | ||
608 | opts |= (OPT_hard | OPT_soft); | ||
609 | if (opts & OPT_all) { | ||
610 | for (i = 0; i < ARRAY_SIZE(limits_tbl); i++) { | ||
611 | getrlimit(limits_tbl[i].cmd, &limit); | ||
612 | printf("%-32s(-%c) ", limits_tbl[i].name, limit_chars[i]); | ||
613 | printlim(opts, &limit, &limits_tbl[i]); | ||
614 | } | ||
615 | return EXIT_SUCCESS; | ||
616 | } | ||
540 | 617 | ||
541 | if (opt_char == 1) | 618 | /* Second pass: set or print limits, in order */ |
619 | GETOPT_RESET(); | ||
620 | while (1) { | ||
621 | char *val_str; | ||
622 | int opt_char = getopt(argc, argv, ulimit_opt_string); | ||
623 | |||
624 | if (opt_char == -1) | ||
625 | break; | ||
626 | if (opt_char == 'H') | ||
627 | continue; | ||
628 | if (opt_char == 'S') | ||
629 | continue; | ||
630 | //if (opt_char == 'a') - impossible | ||
631 | |||
632 | if (opt_char == 1) /* if "ulimit NNN", -f is assumed */ | ||
542 | opt_char = 'f'; | 633 | opt_char = 'f'; |
543 | for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) { | 634 | i = strchrnul(limit_chars, opt_char) - limit_chars; |
544 | if (opt_char == l->option) { | 635 | //if (i >= ARRAY_SIZE(limits_tbl)) - bad option, impossible |
545 | char *val_str; | 636 | |
546 | 637 | val_str = optarg; | |
547 | getrlimit(l->cmd, &limit); | 638 | if (!val_str && argv[optind] && argv[optind][0] != '-') |
548 | 639 | val_str = argv[optind++]; /* ++ skips NN in "-c NN" case */ | |
549 | val_str = optarg; | 640 | |
550 | if (!val_str && argv[optind] && argv[optind][0] != '-') | 641 | getrlimit(limits_tbl[i].cmd, &limit); |
551 | val_str = argv[optind++]; /* ++ skips NN in "-c NN" case */ | 642 | if (!val_str) { |
552 | if (val_str) { | 643 | if (opt_cnt > 1) |
553 | rlim_t val; | 644 | printf("%-32s(-%c) ", limits_tbl[i].name, limit_chars[i]); |
554 | 645 | printlim(opts, &limit, &limits_tbl[i]); | |
555 | if (strcmp(val_str, "unlimited") == 0) | 646 | } else { |
556 | val = RLIM_INFINITY; | 647 | rlim_t val = RLIM_INFINITY; |
557 | else { | 648 | if (strcmp(val_str, "unlimited") != 0) { |
558 | if (sizeof(val) == sizeof(int)) | 649 | if (sizeof(val) == sizeof(int)) |
559 | val = bb_strtou(val_str, NULL, 10); | 650 | val = bb_strtou(val_str, NULL, 10); |
560 | else if (sizeof(val) == sizeof(long)) | 651 | else if (sizeof(val) == sizeof(long)) |
561 | val = bb_strtoul(val_str, NULL, 10); | 652 | val = bb_strtoul(val_str, NULL, 10); |
562 | else | 653 | else |
563 | val = bb_strtoull(val_str, NULL, 10); | 654 | val = bb_strtoull(val_str, NULL, 10); |
564 | if (errno) { | 655 | if (errno) { |
565 | bb_error_msg("invalid number '%s'", val_str); | 656 | bb_error_msg("invalid number '%s'", val_str); |
566 | return EXIT_FAILURE; | 657 | return EXIT_FAILURE; |
567 | } | ||
568 | val <<= l->factor_shift; | ||
569 | } | ||
570 | //bb_error_msg("opt %c val_str:'%s' val:%lld", opt_char, val_str, (long long)val); | ||
571 | /* from man bash: "If neither -H nor -S | ||
572 | * is specified, both the soft and hard | ||
573 | * limits are set. */ | ||
574 | if (!opts) | ||
575 | opts = OPT_hard + OPT_soft; | ||
576 | if (opts & OPT_hard) | ||
577 | limit.rlim_max = val; | ||
578 | if (opts & OPT_soft) | ||
579 | limit.rlim_cur = val; | ||
580 | //bb_error_msg("setrlimit(%d, %lld, %lld)", l->cmd, (long long)limit.rlim_cur, (long long)limit.rlim_max); | ||
581 | if (setrlimit(l->cmd, &limit) < 0) { | ||
582 | bb_perror_msg("error setting limit"); | ||
583 | return EXIT_FAILURE; | ||
584 | } | ||
585 | } else { | ||
586 | printlim(opts, &limit, l); | ||
587 | } | 658 | } |
588 | break; | 659 | val <<= limits_tbl[i].factor_shift; |
660 | } | ||
661 | //bb_error_msg("opt %c val_str:'%s' val:%lld", opt_char, val_str, (long long)val); | ||
662 | /* from man bash: "If neither -H nor -S | ||
663 | * is specified, both the soft and hard | ||
664 | * limits are set. */ | ||
665 | if (opts & OPT_hard) | ||
666 | limit.rlim_max = val; | ||
667 | if (opts & OPT_soft) | ||
668 | limit.rlim_cur = val; | ||
669 | //bb_error_msg("setrlimit(%d, %lld, %lld)", limits_tbl[i].cmd, (long long)limit.rlim_cur, (long long)limit.rlim_max); | ||
670 | if (setrlimit(limits_tbl[i].cmd, &limit) < 0) { | ||
671 | bb_perror_msg("error setting limit"); | ||
672 | return EXIT_FAILURE; | ||
589 | } | 673 | } |
590 | } /* for (every possible opt) */ | ||
591 | |||
592 | if (l == &limits_tbl[ARRAY_SIZE(limits_tbl)]) { | ||
593 | /* bad option. getopt already complained. */ | ||
594 | break; | ||
595 | } | 674 | } |
596 | } /* while (there are options) */ | 675 | } /* while (there are options) */ |
597 | 676 | ||
598 | return 0; | 677 | if (opt_cnt == 0) { |
678 | /* "bare ulimit": treat it as if it was -f */ | ||
679 | getrlimit(limits_tbl[LIMIT_F_IDX].cmd, &limit); | ||
680 | printlim(opts, &limit, &limits_tbl[LIMIT_F_IDX]); | ||
681 | } | ||
682 | |||
683 | return EXIT_SUCCESS; | ||
599 | } | 684 | } |
600 | #else | 685 | #else |
601 | int FAST_FUNC shell_builtin_ulimit(char **argv UNUSED_PARAM) | 686 | int FAST_FUNC shell_builtin_ulimit(char **argv UNUSED_PARAM) |
diff --git a/shell/shell_common.h b/shell/shell_common.h index a1323021d..7b478f1df 100644 --- a/shell/shell_common.h +++ b/shell/shell_common.h | |||
@@ -26,8 +26,6 @@ extern const char defifsvar[] ALIGN1; /* "IFS= \t\n" */ | |||
26 | 26 | ||
27 | extern const char defoptindvar[] ALIGN1; /* "OPTIND=1" */ | 27 | extern const char defoptindvar[] ALIGN1; /* "OPTIND=1" */ |
28 | 28 | ||
29 | int FAST_FUNC is_well_formed_var_name(const char *s, char terminator); | ||
30 | |||
31 | /* Builtins */ | 29 | /* Builtins */ |
32 | 30 | ||
33 | struct builtin_read_params { | 31 | struct builtin_read_params { |
diff --git a/testsuite/bunzip2.tests b/testsuite/bunzip2.tests index edb332748..69e34dfd0 100755 --- a/testsuite/bunzip2.tests +++ b/testsuite/bunzip2.tests | |||
@@ -562,7 +562,7 @@ if test "${0##*/}" = "bunzip2.tests"; then | |||
562 | fi | 562 | fi |
563 | 563 | ||
564 | errout="`${bb}bunzip2 <bz2_issue_12.bz2 2>&1 >/dev/null`" | 564 | errout="`${bb}bunzip2 <bz2_issue_12.bz2 2>&1 >/dev/null`" |
565 | if test x"$errout:$?" = x"bunzip2: bunzip error -3:1"; then | 565 | if test x"$errout:$?" = x"bunzip2: bunzip error -5:1"; then |
566 | echo "PASS: $unpack: bz2_issue_12.bz2 corrupted example" | 566 | echo "PASS: $unpack: bz2_issue_12.bz2 corrupted example" |
567 | else | 567 | else |
568 | echo "FAIL: $unpack: bz2_issue_12.bz2 corrupted example" | 568 | echo "FAIL: $unpack: bz2_issue_12.bz2 corrupted example" |
diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 675cb4f10..67ff87e93 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests | |||
@@ -361,6 +361,12 @@ testing "sed /regex/,+N{...} addresses work" \ | |||
361 | "" \ | 361 | "" \ |
362 | "1\n2\n3\n4\n5\n" | 362 | "1\n2\n3\n4\n5\n" |
363 | 363 | ||
364 | testing "sed /regex/,+N{...} addresses work 2" \ | ||
365 | "sed -n '/a/,+1 p'" \ | ||
366 | "a\n1\na\n2\na\n3\n" \ | ||
367 | "" \ | ||
368 | "a\n1\nc\nc\na\n2\na\n3\n" | ||
369 | |||
364 | testing "sed /regex/,+N{...} -i works" \ | 370 | testing "sed /regex/,+N{...} -i works" \ |
365 | "cat - >input2; sed /^4/,+2{d} -i input input2; echo \$?; cat input input2; rm input2" \ | 371 | "cat - >input2; sed /^4/,+2{d} -i input input2; echo \$?; cat input input2; rm input2" \ |
366 | "0\n""1\n2\n3\n7\n8\n""1\n2\n7\n8\n" \ | 372 | "0\n""1\n2\n3\n7\n8\n""1\n2\n7\n8\n" \ |
diff --git a/util-linux/losetup.c b/util-linux/losetup.c index bf480e9bf..2248f2cba 100644 --- a/util-linux/losetup.c +++ b/util-linux/losetup.c | |||
@@ -20,10 +20,11 @@ | |||
20 | //kbuild:lib-$(CONFIG_LOSETUP) += losetup.o | 20 | //kbuild:lib-$(CONFIG_LOSETUP) += losetup.o |
21 | 21 | ||
22 | //usage:#define losetup_trivial_usage | 22 | //usage:#define losetup_trivial_usage |
23 | //usage: "[-r] [-o OFS] {-f|LOOPDEV} FILE - associate loop devices\n" | 23 | //usage: "[-r] [-o OFS] {-f|LOOPDEV} FILE: associate loop devices\n" |
24 | //usage: " losetup -d LOOPDEV - disassociate\n" | 24 | //usage: " losetup -c LOOPDEV: reread file size\n" |
25 | //usage: " losetup -a - show status\n" | 25 | //usage: " losetup -d LOOPDEV: disassociate\n" |
26 | //usage: " losetup -f - show next free loop device" | 26 | //usage: " losetup -a: show status\n" |
27 | //usage: " losetup -f: show next free loop device" | ||
27 | //usage:#define losetup_full_usage "\n\n" | 28 | //usage:#define losetup_full_usage "\n\n" |
28 | //usage: " -o OFS Start OFS bytes into FILE" | 29 | //usage: " -o OFS Start OFS bytes into FILE" |
29 | //usage: "\n -r Read-only" | 30 | //usage: "\n -r Read-only" |
@@ -50,14 +51,15 @@ int losetup_main(int argc UNUSED_PARAM, char **argv) | |||
50 | char *opt_o; | 51 | char *opt_o; |
51 | char dev[LOOP_NAMESIZE]; | 52 | char dev[LOOP_NAMESIZE]; |
52 | enum { | 53 | enum { |
53 | OPT_d = (1 << 0), | 54 | OPT_c = (1 << 0), |
54 | OPT_o = (1 << 1), | 55 | OPT_d = (1 << 1), |
55 | OPT_f = (1 << 2), | 56 | OPT_o = (1 << 2), |
56 | OPT_a = (1 << 3), | 57 | OPT_f = (1 << 3), |
57 | OPT_r = (1 << 4), /* must be last */ | 58 | OPT_a = (1 << 4), |
59 | OPT_r = (1 << 5), | ||
58 | }; | 60 | }; |
59 | 61 | ||
60 | opt = getopt32(argv, "^" "do:far" "\0" "?2:d--ofar:a--ofr", &opt_o); | 62 | opt = getopt32(argv, "^" "cdo:far" "\0" "?2:d--ofar:a--ofr", &opt_o); |
61 | argv += optind; | 63 | argv += optind; |
62 | 64 | ||
63 | /* LOOPDEV */ | 65 | /* LOOPDEV */ |
@@ -73,6 +75,16 @@ int losetup_main(int argc UNUSED_PARAM, char **argv) | |||
73 | return EXIT_SUCCESS; | 75 | return EXIT_SUCCESS; |
74 | } | 76 | } |
75 | 77 | ||
78 | /* -c LOOPDEV */ | ||
79 | if (opt == OPT_c && argv[0]) { | ||
80 | int fd = xopen(argv[0], O_RDONLY); | ||
81 | #ifndef LOOP_SET_CAPACITY | ||
82 | # define LOOP_SET_CAPACITY 0x4C07 | ||
83 | #endif | ||
84 | xioctl(fd, LOOP_SET_CAPACITY, /*ignored:*/0); | ||
85 | return EXIT_SUCCESS; | ||
86 | } | ||
87 | |||
76 | /* -d LOOPDEV */ | 88 | /* -d LOOPDEV */ |
77 | if (opt == OPT_d && argv[0]) { | 89 | if (opt == OPT_d && argv[0]) { |
78 | if (del_loop(argv[0])) | 90 | if (del_loop(argv[0])) |
diff --git a/util-linux/mount.c b/util-linux/mount.c index 526b4130c..e6bad7c2c 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c | |||
@@ -1194,7 +1194,10 @@ static int daemonize(void) | |||
1194 | return 1; | 1194 | return 1; |
1195 | } | 1195 | } |
1196 | #else | 1196 | #else |
1197 | static inline int daemonize(void) { return -ENOSYS; } | 1197 | static inline int daemonize(void) |
1198 | { | ||
1199 | return -ENOSYS; | ||
1200 | } | ||
1198 | #endif | 1201 | #endif |
1199 | 1202 | ||
1200 | /* TODO */ | 1203 | /* TODO */ |