aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-02-15 13:25:04 +0000
committerRon Yorston <rmy@pobox.com>2020-02-15 13:25:04 +0000
commit0abe89bc214c9d1f16f32c4339792066b875b7c6 (patch)
tree3748f654565bd08513093ebfbb68487f612b5e3f
parent6885083a7e4f94938ca0a98e2c6c69a84eb08a1f (diff)
parenta6e48dead331c3c19e070992d2d571e74a1d9a8d (diff)
downloadbusybox-w32-0abe89bc214c9d1f16f32c4339792066b875b7c6.tar.gz
busybox-w32-0abe89bc214c9d1f16f32c4339792066b875b7c6.tar.bz2
busybox-w32-0abe89bc214c9d1f16f32c4339792066b875b7c6.zip
Merge branch 'busybox' into merge
-rw-r--r--editors/awk.c22
-rw-r--r--editors/vi.c13
-rw-r--r--findutils/xargs.c27
-rw-r--r--include/libbb.h13
-rw-r--r--libbb/lineedit.c17
-rw-r--r--networking/tftp.c87
-rw-r--r--networking/udhcp/dhcpd.c2
-rw-r--r--shell/ash.c60
-rw-r--r--shell/hush.c17
-rw-r--r--sysklogd/syslogd.c24
-rwxr-xr-xtestsuite/awk.tests23
-rwxr-xr-xtestsuite/xargs.tests9
-rw-r--r--util-linux/fdisk.c10
13 files changed, 234 insertions, 90 deletions
diff --git a/editors/awk.c b/editors/awk.c
index d1fedb572..76385f33b 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -272,7 +272,8 @@ typedef struct tsplitter_s {
272/* if previous token class is CONCAT1 and next is CONCAT2, concatenation */ 272/* if previous token class is CONCAT1 and next is CONCAT2, concatenation */
273/* operator is inserted between them */ 273/* operator is inserted between them */
274#define TC_CONCAT1 (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM \ 274#define TC_CONCAT1 (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM \
275 | TC_STRING | TC_NUMBER | TC_UOPPOST) 275 | TC_STRING | TC_NUMBER | TC_UOPPOST \
276 | TC_LENGTH)
276#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE) 277#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE)
277 278
278#define OF_RES1 0x010000 279#define OF_RES1 0x010000
@@ -1074,8 +1075,10 @@ static uint32_t next_token(uint32_t expected)
1074 const uint32_t *ti; 1075 const uint32_t *ti;
1075 1076
1076 if (t_rollback) { 1077 if (t_rollback) {
1078 debug_printf_parse("%s: using rolled-back token\n", __func__);
1077 t_rollback = FALSE; 1079 t_rollback = FALSE;
1078 } else if (concat_inserted) { 1080 } else if (concat_inserted) {
1081 debug_printf_parse("%s: using concat-inserted token\n", __func__);
1079 concat_inserted = FALSE; 1082 concat_inserted = FALSE;
1080 t_tclass = save_tclass; 1083 t_tclass = save_tclass;
1081 t_info = save_info; 1084 t_info = save_info;
@@ -1204,7 +1207,11 @@ static uint32_t next_token(uint32_t expected)
1204 goto readnext; 1207 goto readnext;
1205 1208
1206 /* insert concatenation operator when needed */ 1209 /* insert concatenation operator when needed */
1207 if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)) { 1210 debug_printf_parse("%s: %x %x %x concat_inserted?\n", __func__,
1211 (ltclass & TC_CONCAT1), (tc & TC_CONCAT2), (expected & TC_BINOP));
1212 if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)
1213 && !(ltclass == TC_LENGTH && tc == TC_SEQSTART) /* but not for "length(..." */
1214 ) {
1208 concat_inserted = TRUE; 1215 concat_inserted = TRUE;
1209 save_tclass = tc; 1216 save_tclass = tc;
1210 save_info = t_info; 1217 save_info = t_info;
@@ -1212,6 +1219,7 @@ static uint32_t next_token(uint32_t expected)
1212 t_info = OC_CONCAT | SS | P(35); 1219 t_info = OC_CONCAT | SS | P(35);
1213 } 1220 }
1214 1221
1222 debug_printf_parse("%s: t_tclass=tc=%x\n", __func__, t_tclass);
1215 t_tclass = tc; 1223 t_tclass = tc;
1216 } 1224 }
1217 ltclass = t_tclass; 1225 ltclass = t_tclass;
@@ -1222,6 +1230,7 @@ static uint32_t next_token(uint32_t expected)
1222 EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN); 1230 EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
1223 } 1231 }
1224 1232
1233 debug_printf_parse("%s: returning, ltclass:%x t_double:%f\n", __func__, ltclass, t_double);
1225 return ltclass; 1234 return ltclass;
1226#undef concat_inserted 1235#undef concat_inserted
1227#undef save_tclass 1236#undef save_tclass
@@ -1286,7 +1295,7 @@ static node *parse_expr(uint32_t iexp)
1286 glptr = NULL; 1295 glptr = NULL;
1287 1296
1288 } else if (tc & (TC_BINOP | TC_UOPPOST)) { 1297 } else if (tc & (TC_BINOP | TC_UOPPOST)) {
1289 debug_printf_parse("%s: TC_BINOP | TC_UOPPOST\n", __func__); 1298 debug_printf_parse("%s: TC_BINOP | TC_UOPPOST tc:%x\n", __func__, tc);
1290 /* for binary and postfix-unary operators, jump back over 1299 /* for binary and postfix-unary operators, jump back over
1291 * previous operators with higher priority */ 1300 * previous operators with higher priority */
1292 vn = cn; 1301 vn = cn;
@@ -1391,7 +1400,12 @@ static node *parse_expr(uint32_t iexp)
1391 1400
1392 case TC_LENGTH: 1401 case TC_LENGTH:
1393 debug_printf_parse("%s: TC_LENGTH\n", __func__); 1402 debug_printf_parse("%s: TC_LENGTH\n", __func__);
1394 next_token(TC_SEQSTART | TC_OPTERM | TC_GRPTERM); 1403 next_token(TC_SEQSTART /* length(...) */
1404 | TC_OPTERM /* length; (or newline)*/
1405 | TC_GRPTERM /* length } */
1406 | TC_BINOPX /* length <op> NUM */
1407 | TC_COMMA /* print length, 1 */
1408 );
1395 rollback_token(); 1409 rollback_token();
1396 if (t_tclass & TC_SEQSTART) { 1410 if (t_tclass & TC_SEQSTART) {
1397 /* It was a "(" token. Handle just like TC_BUILTIN */ 1411 /* It was a "(" token. Handle just like TC_BUILTIN */
diff --git a/editors/vi.c b/editors/vi.c
index 948b95ae6..131c018a2 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2317,7 +2317,6 @@ static char *get_one_address(char *p, int *addr) // get colon addr, if present
2317 int st; 2317 int st;
2318 char *q; 2318 char *q;
2319 IF_FEATURE_VI_YANKMARK(char c;) 2319 IF_FEATURE_VI_YANKMARK(char c;)
2320 IF_FEATURE_VI_SEARCH(char *pat;)
2321 2320
2322 *addr = -1; // assume no addr 2321 *addr = -1; // assume no addr
2323 if (*p == '.') { // the current line 2322 if (*p == '.') { // the current line
@@ -2342,16 +2341,20 @@ static char *get_one_address(char *p, int *addr) // get colon addr, if present
2342#endif 2341#endif
2343#if ENABLE_FEATURE_VI_SEARCH 2342#if ENABLE_FEATURE_VI_SEARCH
2344 else if (*p == '/') { // a search pattern 2343 else if (*p == '/') { // a search pattern
2345 q = strchrnul(++p, '/'); 2344 q = strchrnul(p + 1, '/');
2346 pat = xstrndup(p, q - p); // save copy of pattern 2345 if (p + 1 != q) {
2346 // save copy of new pattern
2347 free(last_search_pattern);
2348 last_search_pattern = xstrndup(p, q - p);
2349 }
2347 p = q; 2350 p = q;
2348 if (*p == '/') 2351 if (*p == '/')
2349 p++; 2352 p++;
2350 q = char_search(dot, pat, (FORWARD << 1) | FULL); 2353 q = char_search(next_line(dot), last_search_pattern + 1,
2354 (FORWARD << 1) | FULL);
2351 if (q != NULL) { 2355 if (q != NULL) {
2352 *addr = count_lines(text, q); 2356 *addr = count_lines(text, q);
2353 } 2357 }
2354 free(pat);
2355 } 2358 }
2356#endif 2359#endif
2357 else if (*p == '$') { // the last line in file 2360 else if (*p == '$') { // the last line in file
diff --git a/findutils/xargs.c b/findutils/xargs.c
index e0dbcbc7a..8d3a0027c 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -120,18 +120,29 @@ struct globals {
120#endif 120#endif
121#endif 121#endif
122 smalluint xargs_exitcode; 122 smalluint xargs_exitcode;
123#if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES
124#define NORM 0
125#define QUOTE 1
126#define BACKSLASH 2
127#define SPACE 4
128 smalluint process_stdin__state;
129 char process_stdin__q;
130#endif
123} FIX_ALIASING; 131} FIX_ALIASING;
124#define G (*(struct globals*)bb_common_bufsiz1) 132#define G (*(struct globals*)bb_common_bufsiz1)
125#define INIT_G() do { \ 133#define INIT_G() do { \
126 setup_common_bufsiz(); \ 134 setup_common_bufsiz(); \
127 G.eof_str = NULL; /* need to clear by hand because we are NOEXEC applet */ \ 135 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.repl_str = "{}";) \
136 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.eol_ch = '\n';) \
137 /* Even zero values are set because we are NOEXEC applet */ \
138 G.eof_str = NULL; \
128 G.idx = 0; \ 139 G.idx = 0; \
129 IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.running_procs = 0;) \ 140 IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.running_procs = 0;) \
130 IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.max_procs = 1;) \ 141 IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.max_procs = 1;) \
131 IF_FEATURE_XARGS_SUPPORT_PARALLEL(IF_PLATFORM_MINGW32(G.procs = NULL;)) \ 142 IF_FEATURE_XARGS_SUPPORT_PARALLEL(IF_PLATFORM_MINGW32(G.procs = NULL;)) \
132 G.xargs_exitcode = 0; \ 143 G.xargs_exitcode = 0; \
133 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.repl_str = "{}";) \ 144 IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__state = NORM;) \
134 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.eol_ch = '\n';) \ 145 IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__q = '\0';) \
135} while (0) 146} while (0)
136 147
137 148
@@ -330,12 +341,8 @@ static void store_param(char *s)
330#if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES 341#if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES
331static char* FAST_FUNC process_stdin(int n_max_chars, int n_max_arg, char *buf) 342static char* FAST_FUNC process_stdin(int n_max_chars, int n_max_arg, char *buf)
332{ 343{
333#define NORM 0 344#define q G.process_stdin__q
334#define QUOTE 1 345#define state G.process_stdin__state
335#define BACKSLASH 2
336#define SPACE 4
337 char q = '\0'; /* quote char */
338 char state = NORM;
339 char *s = buf; /* start of the word */ 346 char *s = buf; /* start of the word */
340 char *p = s + strlen(buf); /* end of the word */ 347 char *p = s + strlen(buf); /* end of the word */
341 348
@@ -412,6 +419,8 @@ static char* FAST_FUNC process_stdin(int n_max_chars, int n_max_arg, char *buf)
412 /* store_param(NULL) - caller will do it */ 419 /* store_param(NULL) - caller will do it */
413 dbg_msg("return:'%s'", s); 420 dbg_msg("return:'%s'", s);
414 return s; 421 return s;
422#undef q
423#undef state
415} 424}
416#else 425#else
417/* The variant does not support single quotes, double quotes or backslash */ 426/* The variant does not support single quotes, double quotes or backslash */
diff --git a/include/libbb.h b/include/libbb.h
index 0aa44eb37..cbb178c0b 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1867,10 +1867,19 @@ unsigned size_from_HISTFILESIZE(const char *hp) FAST_FUNC;
1867# else 1867# else
1868# define MAX_HISTORY 0 1868# define MAX_HISTORY 0
1869# endif 1869# endif
1870typedef const char *get_exe_name_t(int i) FAST_FUNC;
1870typedef struct line_input_t { 1871typedef struct line_input_t {
1871 int flags; 1872 int flags;
1872 int timeout; 1873 int timeout;
1873 const char *path_lookup; 1874 const char *path_lookup;
1875# if ENABLE_FEATURE_TAB_COMPLETION \
1876&& (ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \
1877|| ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH \
1878)
1879 /* function to fetch additional application-specific names to match */
1880 get_exe_name_t *get_exe_name;
1881# define EDITING_HAS_get_exe_name 1
1882# endif
1874# if MAX_HISTORY 1883# if MAX_HISTORY
1875 int cnt_history; 1884 int cnt_history;
1876 int cur_history; 1885 int cur_history;
@@ -1917,6 +1926,10 @@ int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC;
1917 read_line_input(prompt, command, maxsize) 1926 read_line_input(prompt, command, maxsize)
1918#endif 1927#endif
1919 1928
1929#ifndef EDITING_HAS_get_exe_name
1930# define EDITING_HAS_get_exe_name 0
1931#endif
1932
1920 1933
1921#ifndef COMM_LEN 1934#ifndef COMM_LEN
1922# ifdef TASK_COMM_LEN 1935# ifdef TASK_COMM_LEN
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 9bb3ea98b..14eb16873 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -884,18 +884,29 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
884 } 884 }
885 pf_len = strlen(pfind); 885 pf_len = strlen(pfind);
886 886
887# if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1
888 if (type == FIND_EXE_ONLY && !dirbuf) { 887 if (type == FIND_EXE_ONLY && !dirbuf) {
888# if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1
889 const char *p = applet_names; 889 const char *p = applet_names;
890
891 while (*p) { 890 while (*p) {
892 if (strncmp(pfind, p, pf_len) == 0) 891 if (strncmp(pfind, p, pf_len) == 0)
893 add_match(xstrdup(p)); 892 add_match(xstrdup(p));
894 while (*p++ != '\0') 893 while (*p++ != '\0')
895 continue; 894 continue;
896 } 895 }
897 }
898# endif 896# endif
897# if EDITING_HAS_get_exe_name
898 if (state->get_exe_name) {
899 i = 0;
900 for (;;) {
901 const char *b = state->get_exe_name(i++);
902 if (!b)
903 break;
904 if (strncmp(pfind, b, pf_len) == 0)
905 add_match(xstrdup(b));
906 }
907 }
908# endif
909 }
899 910
900 for (i = 0; i < npaths; i++) { 911 for (i = 0; i < npaths; i++) {
901 DIR *dir; 912 DIR *dir;
diff --git a/networking/tftp.c b/networking/tftp.c
index 04bfe844f..60fdff232 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -319,7 +319,7 @@ static int tftp_protocol(
319 uint16_t opcode; 319 uint16_t opcode;
320 uint16_t block_nr; 320 uint16_t block_nr;
321 uint16_t recv_blk; 321 uint16_t recv_blk;
322 int open_mode, local_fd; 322 int local_fd = -1;
323 int retries, waittime_ms; 323 int retries, waittime_ms;
324 int io_bufsize = blksize + 4; 324 int io_bufsize = blksize + 4;
325 char *cp; 325 char *cp;
@@ -354,19 +354,6 @@ static int tftp_protocol(
354 } 354 }
355 } 355 }
356 356
357 /* Prepare open mode */
358 if (CMD_PUT(option_mask32)) {
359 open_mode = O_RDONLY;
360 } else {
361 open_mode = O_WRONLY | O_TRUNC | O_CREAT;
362#if ENABLE_TFTPD
363 if ((option_mask32 & (TFTPD_OPT+TFTPD_OPT_c)) == TFTPD_OPT) {
364 /* tftpd without -c */
365 open_mode = O_WRONLY | O_TRUNC;
366 }
367#endif
368 }
369
370 /* Examples of network traffic. 357 /* Examples of network traffic.
371 * Note two cases when ACKs with block# of 0 are sent. 358 * Note two cases when ACKs with block# of 0 are sent.
372 * 359 *
@@ -400,12 +387,29 @@ static int tftp_protocol(
400 387
401 if (!ENABLE_TFTP || our_lsa) { /* tftpd */ 388 if (!ENABLE_TFTP || our_lsa) { /* tftpd */
402 /* Open file (must be after changing user) */ 389 /* Open file (must be after changing user) */
390 int open_mode = O_RDONLY;
391 if (CMD_GET(option_mask32)) {
392 open_mode = O_WRONLY | O_TRUNC | O_CREAT;
393 if ((option_mask32 & (TFTPD_OPT+TFTPD_OPT_c)) == TFTPD_OPT) {
394 /* tftpd without -c */
395 open_mode = O_WRONLY | O_TRUNC;
396 }
397 }
403 local_fd = open(local_file, open_mode, 0666); 398 local_fd = open(local_file, open_mode, 0666);
404 if (local_fd < 0) { 399 if (local_fd < 0) {
400 /* sanitize name, it came from untrusted remote side */
401 unsigned char *p = (void *) local_file;
402 while (*p) {
403 if (*p < ' ')
404 *p = '?';
405 p++;
406 }
407 bb_perror_msg("can't open '%s'", local_file);
405 G_error_pkt_reason = ERR_NOFILE; 408 G_error_pkt_reason = ERR_NOFILE;
406 strcpy(G_error_pkt_str, "can't open file"); 409 strcpy(G_error_pkt_str, "can't open file");
407 goto send_err_pkt; 410 goto send_err_pkt_nomsg;
408 } 411 }
412
409/* gcc 4.3.1 would NOT optimize it out as it should! */ 413/* gcc 4.3.1 would NOT optimize it out as it should! */
410#if ENABLE_FEATURE_TFTP_BLOCKSIZE 414#if ENABLE_FEATURE_TFTP_BLOCKSIZE
411 if (blksize != TFTP_BLKSIZE_DEFAULT || want_transfer_size) { 415 if (blksize != TFTP_BLKSIZE_DEFAULT || want_transfer_size) {
@@ -424,10 +428,11 @@ static int tftp_protocol(
424 block_nr = 0; 428 block_nr = 0;
425 } 429 }
426 } else { /* tftp */ 430 } else { /* tftp */
427 /* Open file (must be after changing user) */ 431 if (CMD_PUT(option_mask32)) {
428 local_fd = CMD_GET(option_mask32) ? STDOUT_FILENO : STDIN_FILENO; 432 local_fd = STDIN_FILENO;
429 if (NOT_LONE_DASH(local_file)) 433 if (local_file)
430 local_fd = xopen(local_file, open_mode); 434 local_fd = xopen(local_file, O_RDONLY);
435 }
431/* Removing #if, or using if() statement instead of #if may lead to 436/* Removing #if, or using if() statement instead of #if may lead to
432 * "warning: null argument where non-null required": */ 437 * "warning: null argument where non-null required": */
433#if ENABLE_TFTP 438#if ENABLE_TFTP
@@ -451,16 +456,14 @@ static int tftp_protocol(
451 } 456 }
452 /* add filename and mode */ 457 /* add filename and mode */
453 /* fill in packet if the filename fits into xbuf */ 458 /* fill in packet if the filename fits into xbuf */
454 len = strlen(remote_file) + 1; 459 len = strlen(remote_file);
455 if (2 + len + sizeof("octet") >= io_bufsize) { 460 if (len + 3 + sizeof("octet") >= io_bufsize) {
456 bb_simple_error_msg("remote filename is too long"); 461 bb_simple_error_msg("remote filename is too long");
457 goto ret; 462 goto ret;
458 } 463 }
459 strcpy(cp, remote_file); 464 cp = stpcpy(cp, remote_file) + 1;
460 cp += len;
461 /* add "mode" part of the packet */ 465 /* add "mode" part of the packet */
462 strcpy(cp, "octet"); 466 cp = stpcpy(cp, "octet") + 1;
463 cp += sizeof("octet");
464 467
465# if ENABLE_FEATURE_TFTP_BLOCKSIZE 468# if ENABLE_FEATURE_TFTP_BLOCKSIZE
466 if (blksize == TFTP_BLKSIZE_DEFAULT && !want_transfer_size) 469 if (blksize == TFTP_BLKSIZE_DEFAULT && !want_transfer_size)
@@ -485,7 +488,7 @@ static int tftp_protocol(
485 } 488 }
486 if (want_transfer_size) { 489 if (want_transfer_size) {
487 /* add "tsize", <nul>, size, <nul> (see RFC2349) */ 490 /* add "tsize", <nul>, size, <nul> (see RFC2349) */
488 /* if tftp and downloading, we send "0" (since we opened local_fd with O_TRUNC) 491 /* if tftp and downloading, we send "0" (local_fd is not open yet)
489 * and this makes server to send "tsize" option with the size */ 492 * and this makes server to send "tsize" option with the size */
490 /* if tftp and uploading, we send file size (maybe dont, to not confuse old servers???) */ 493 /* if tftp and uploading, we send file size (maybe dont, to not confuse old servers???) */
491 /* if tftpd and downloading, we are answering to client's request */ 494 /* if tftpd and downloading, we are answering to client's request */
@@ -494,7 +497,8 @@ static int tftp_protocol(
494 strcpy(cp, "tsize"); 497 strcpy(cp, "tsize");
495 cp += sizeof("tsize"); 498 cp += sizeof("tsize");
496 st.st_size = 0; 499 st.st_size = 0;
497 fstat(local_fd, &st); 500 if (local_fd >= 0)
501 fstat(local_fd, &st);
498 cp += sprintf(cp, "%"OFF_FMT"u", (off_t)st.st_size) + 1; 502 cp += sprintf(cp, "%"OFF_FMT"u", (off_t)st.st_size) + 1;
499# if ENABLE_FEATURE_TFTP_PROGRESS_BAR 503# if ENABLE_FEATURE_TFTP_PROGRESS_BAR
500 /* Save for progress bar. If 0 (tftp downloading), 504 /* Save for progress bar. If 0 (tftp downloading),
@@ -684,7 +688,13 @@ static int tftp_protocol(
684 688
685 if (CMD_GET(option_mask32) && (opcode == TFTP_DATA)) { 689 if (CMD_GET(option_mask32) && (opcode == TFTP_DATA)) {
686 if (recv_blk == block_nr) { 690 if (recv_blk == block_nr) {
687 int sz = full_write(local_fd, &rbuf[4], len - 4); 691 int sz;
692 if (local_fd == -1) {
693 local_fd = STDOUT_FILENO;
694 if (local_file)
695 local_fd = xopen(local_file, O_WRONLY | O_TRUNC | O_CREAT);
696 }
697 sz = full_write(local_fd, &rbuf[4], len - 4);
688 if (sz != len - 4) { 698 if (sz != len - 4) {
689 strcpy(G_error_pkt_str, bb_msg_write_error); 699 strcpy(G_error_pkt_str, bb_msg_write_error);
690 G_error_pkt_reason = ERR_WRITE; 700 G_error_pkt_reason = ERR_WRITE;
@@ -721,7 +731,7 @@ static int tftp_protocol(
721 * must never resend the current DATA packet on receipt 731 * must never resend the current DATA packet on receipt
722 * of a duplicate ACK". 732 * of a duplicate ACK".
723 * DATA pkts are resent ONLY on timeout. 733 * DATA pkts are resent ONLY on timeout.
724 * Thus "goto send_again" will ba a bad mistake above. 734 * Thus "goto send_again" will be a bad mistake above.
725 * See: 735 * See:
726 * http://en.wikipedia.org/wiki/Sorcerer's_Apprentice_Syndrome 736 * http://en.wikipedia.org/wiki/Sorcerer's_Apprentice_Syndrome
727 */ 737 */
@@ -733,22 +743,27 @@ static int tftp_protocol(
733 free(xbuf); 743 free(xbuf);
734 free(rbuf); 744 free(rbuf);
735 } 745 }
736 return finished == 0; /* returns 1 on failure */ 746 if (!finished)
747 goto err;
748 return EXIT_SUCCESS;
737 749
738 send_read_err_pkt: 750 send_read_err_pkt:
739 strcpy(G_error_pkt_str, bb_msg_read_error); 751 strcpy(G_error_pkt_str, bb_msg_read_error);
740 send_err_pkt: 752 send_err_pkt:
741 if (G_error_pkt_str[0]) 753 if (G_error_pkt_str[0])
742 bb_simple_error_msg(G_error_pkt_str); 754 bb_simple_error_msg(G_error_pkt_str);
755 send_err_pkt_nomsg:
743 G.error_pkt[1] = TFTP_ERROR; 756 G.error_pkt[1] = TFTP_ERROR;
744 xsendto(socket_fd, G.error_pkt, 4 + 1 + strlen(G_error_pkt_str), 757 xsendto(socket_fd, G.error_pkt, 4 + 1 + strlen(G_error_pkt_str),
745 &peer_lsa->u.sa, peer_lsa->len); 758 &peer_lsa->u.sa, peer_lsa->len);
759 err:
760 if (local_fd >= 0 && CMD_GET(option_mask32) && local_file)
761 unlink(local_file);
746 return EXIT_FAILURE; 762 return EXIT_FAILURE;
747#undef remote_file 763#undef remote_file
748} 764}
749 765
750#if ENABLE_TFTP 766#if ENABLE_TFTP
751
752int tftp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 767int tftp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
753int tftp_main(int argc UNUSED_PARAM, char **argv) 768int tftp_main(int argc UNUSED_PARAM, char **argv)
754{ 769{
@@ -761,7 +776,6 @@ int tftp_main(int argc UNUSED_PARAM, char **argv)
761# endif 776# endif
762 int result; 777 int result;
763 int port; 778 int port;
764 IF_GETPUT(int opt;)
765 779
766 INIT_G(); 780 INIT_G();
767 781
@@ -802,7 +816,7 @@ int tftp_main(int argc UNUSED_PARAM, char **argv)
802 } 816 }
803 } 817 }
804 818
805 IF_GETPUT(opt =) getopt32(argv, "^" 819 getopt32(argv, "^"
806 IF_FEATURE_TFTP_GET("g") IF_FEATURE_TFTP_PUT("p") 820 IF_FEATURE_TFTP_GET("g") IF_FEATURE_TFTP_PUT("p")
807 "l:r:" IF_FEATURE_TFTP_BLOCKSIZE("b:") 821 "l:r:" IF_FEATURE_TFTP_BLOCKSIZE("b:")
808 IF_FEATURE_TFTP_HPA_COMPAT("m:") 822 IF_FEATURE_TFTP_HPA_COMPAT("m:")
@@ -853,18 +867,14 @@ int tftp_main(int argc UNUSED_PARAM, char **argv)
853# endif 867# endif
854 result = tftp_protocol( 868 result = tftp_protocol(
855 NULL /*our_lsa*/, peer_lsa, 869 NULL /*our_lsa*/, peer_lsa,
856 local_file, remote_file 870 (LONE_DASH(local_file) ? NULL : local_file), remote_file
857 IF_FEATURE_TFTP_BLOCKSIZE(, 1 /* want_transfer_size */) 871 IF_FEATURE_TFTP_BLOCKSIZE(, 1 /* want_transfer_size */)
858 IF_FEATURE_TFTP_BLOCKSIZE(, blksize) 872 IF_FEATURE_TFTP_BLOCKSIZE(, blksize)
859 ); 873 );
860 tftp_progress_done(); 874 tftp_progress_done();
861 875
862 if (result != EXIT_SUCCESS && NOT_LONE_DASH(local_file) && CMD_GET(opt)) {
863 unlink(local_file);
864 }
865 return result; 876 return result;
866} 877}
867
868#endif /* ENABLE_TFTP */ 878#endif /* ENABLE_TFTP */
869 879
870#if ENABLE_TFTPD 880#if ENABLE_TFTPD
@@ -1001,7 +1011,6 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
1001 strcpy(G_error_pkt_str, error_msg); 1011 strcpy(G_error_pkt_str, error_msg);
1002 goto do_proto; 1012 goto do_proto;
1003} 1013}
1004
1005#endif /* ENABLE_TFTPD */ 1014#endif /* ENABLE_TFTPD */
1006 1015
1007#endif /* ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT */ 1016#endif /* ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT */
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 3e08ec011..9d6604943 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -192,6 +192,8 @@ static struct dyn_lease *add_lease(
192 * but merely make dumpleases output safe for shells to use. 192 * but merely make dumpleases output safe for shells to use.
193 * We accept "0-9A-Za-z._-", all other chars turn to dots. 193 * We accept "0-9A-Za-z._-", all other chars turn to dots.
194 */ 194 */
195 if (*p == '-')
196 *p = '.'; /* defeat "-option" attacks too */
195 while (*p) { 197 while (*p) {
196 if (!isalnum(*p) && *p != '-' && *p != '_') 198 if (!isalnum(*p) && *p != '-' && *p != '_')
197 *p = '.'; 199 *p = '.';
diff --git a/shell/ash.c b/shell/ash.c
index 1b7fa9849..29cdd38f6 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -10190,6 +10190,11 @@ evalpipe(union node *n, int flags)
10190 return status; 10190 return status;
10191} 10191}
10192 10192
10193/* setinteractive needs this forward reference */
10194#if EDITING_HAS_get_exe_name
10195static const char *get_builtin_name(int i) FAST_FUNC;
10196#endif
10197
10193/* 10198/*
10194 * Controls whether the shell is interactive or not. 10199 * Controls whether the shell is interactive or not.
10195 */ 10200 */
@@ -10221,8 +10226,12 @@ setinteractive(int on)
10221 } 10226 }
10222#endif 10227#endif
10223#if ENABLE_FEATURE_EDITING 10228#if ENABLE_FEATURE_EDITING
10224 if (!line_input_state) 10229 if (!line_input_state) {
10225 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); 10230 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
10231# if EDITING_HAS_get_exe_name
10232 line_input_state->get_exe_name = get_builtin_name;
10233# endif
10234 }
10226#endif 10235#endif
10227 } 10236 }
10228} 10237}
@@ -10690,6 +10699,14 @@ find_builtin(const char *name)
10690 return bp; 10699 return bp;
10691} 10700}
10692 10701
10702#if EDITING_HAS_get_exe_name
10703static const char * FAST_FUNC
10704get_builtin_name(int i)
10705{
10706 return /*i >= 0 &&*/ i < ARRAY_SIZE(builtintab) ? builtintab[i].name + 1 : NULL;
10707}
10708#endif
10709
10693/* 10710/*
10694 * Execute a simple command. 10711 * Execute a simple command.
10695 */ 10712 */
@@ -13834,29 +13851,27 @@ expandstr(const char *ps, int syntax_type)
13834 volatile int saveint; 13851 volatile int saveint;
13835 struct jmploc *volatile savehandler = exception_handler; 13852 struct jmploc *volatile savehandler = exception_handler;
13836 struct jmploc jmploc; 13853 struct jmploc jmploc;
13854 const char *volatile result;
13855 int err;
13837 13856
13838 /* XXX Fix (char *) cast. */ 13857 /* XXX Fix (char *) cast. */
13839 setinputstring((char *)ps); 13858 setinputstring((char *)ps);
13840 13859
13841 saveprompt = doprompt; 13860 saveprompt = doprompt;
13842 doprompt = 0; 13861 doprompt = 0;
13862 result = ps;
13863
13864 SAVE_INT(saveint);
13865 err = setjmp(jmploc.loc);
13866 if (err)
13867 goto out;
13843 13868
13844 /* readtoken1() might die horribly. 13869 /* readtoken1() might die horribly.
13845 * Try a prompt with syntactically wrong command: 13870 * Try a prompt with syntactically wrong command:
13846 * PS1='$(date "+%H:%M:%S) > ' 13871 * PS1='$(date "+%H:%M:%S) > '
13847 */ 13872 */
13848 SAVE_INT(saveint); 13873 exception_handler = &jmploc;
13849 if (setjmp(jmploc.loc) == 0) { 13874 readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
13850 exception_handler = &jmploc;
13851 readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
13852 }
13853 exception_handler = savehandler;
13854 RESTORE_INT(saveint);
13855
13856 doprompt = saveprompt;
13857
13858 /* Try: PS1='`xxx(`' */
13859 unwindfiles(file_stop);
13860 13875
13861 n.narg.type = NARG; 13876 n.narg.type = NARG;
13862 n.narg.next = NULL; 13877 n.narg.next = NULL;
@@ -13866,17 +13881,20 @@ expandstr(const char *ps, int syntax_type)
13866 /* expandarg() might fail too: 13881 /* expandarg() might fail too:
13867 * PS1='$((123+))' 13882 * PS1='$((123+))'
13868 */ 13883 */
13869 SAVE_INT(saveint); 13884 expandarg(&n, NULL, EXP_QUOTED);
13870 if (setjmp(jmploc.loc) == 0) { 13885 result = stackblock();
13871 exception_handler = &jmploc; 13886
13872 expandarg(&n, NULL, EXP_QUOTED); 13887out:
13873 } else if (exception_type == EXEXIT) {
13874 exitshell();
13875 }
13876 exception_handler = savehandler; 13888 exception_handler = savehandler;
13889 if (err && exception_type != EXERROR)
13890 longjmp(exception_handler->loc, 1);
13877 RESTORE_INT(saveint); 13891 RESTORE_INT(saveint);
13878 13892
13879 return stackblock(); 13893 doprompt = saveprompt;
13894 /* Try: PS1='`xxx(`' */
13895 unwindfiles(file_stop);
13896
13897 return result;
13880} 13898}
13881 13899
13882static inline int 13900static inline int
diff --git a/shell/hush.c b/shell/hush.c
index 97202b953..6e44d4e11 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -7889,6 +7889,20 @@ static const struct built_in_command *find_builtin(const char *name)
7889 return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); 7889 return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
7890} 7890}
7891 7891
7892#if EDITING_HAS_get_exe_name
7893static const char * FAST_FUNC get_builtin_name(int i)
7894{
7895 if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) {
7896 return bltins1[i].b_cmd;
7897 }
7898 i -= ARRAY_SIZE(bltins1);
7899 if (i < ARRAY_SIZE(bltins2)) {
7900 return bltins2[i].b_cmd;
7901 }
7902 return NULL;
7903}
7904#endif
7905
7892static void remove_nested_vars(void) 7906static void remove_nested_vars(void)
7893{ 7907{
7894 struct variable *cur; 7908 struct variable *cur;
@@ -10268,6 +10282,9 @@ int hush_main(int argc, char **argv)
10268 10282
10269# if ENABLE_FEATURE_EDITING 10283# if ENABLE_FEATURE_EDITING
10270 G.line_input_state = new_line_input_t(FOR_SHELL); 10284 G.line_input_state = new_line_input_t(FOR_SHELL);
10285# if EDITING_HAS_get_exe_name
10286 G.line_input_state->get_exe_name = get_builtin_name;
10287# endif
10271# endif 10288# endif
10272# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 10289# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
10273 { 10290 {
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 0e226124a..ab50f4a28 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -64,6 +64,14 @@
64//config: help 64//config: help
65//config: Supports restricted syslogd config. See docs/syslog.conf.txt 65//config: Supports restricted syslogd config. See docs/syslog.conf.txt
66//config: 66//config:
67//config:config FEATURE_SYSLOGD_PRECISE_TIMESTAMPS
68//config: bool "Include milliseconds in timestamps"
69//config: default n
70//config: depends on SYSLOGD
71//config: help
72//config: Includes milliseconds (HH:MM:SS.mmm) in timestamp when
73//config: timestamps are added.
74//config:
67//config:config FEATURE_SYSLOGD_READ_BUFFER_SIZE 75//config:config FEATURE_SYSLOGD_READ_BUFFER_SIZE
68//config: int "Read buffer size in bytes" 76//config: int "Read buffer size in bytes"
69//config: default 256 77//config: default 256
@@ -276,7 +284,7 @@ struct globals {
276 /* ...then copy to parsebuf, escaping control chars */ 284 /* ...then copy to parsebuf, escaping control chars */
277 /* (can grow x2 max) */ 285 /* (can grow x2 max) */
278 char parsebuf[MAX_READ*2]; 286 char parsebuf[MAX_READ*2];
279 /* ...then sprintf into printbuf, adding timestamp (15 chars), 287 /* ...then sprintf into printbuf, adding timestamp (15 or 19 chars),
280 * host (64), fac.prio (20) to the message */ 288 * host (64), fac.prio (20) to the message */
281 /* (growth by: 15 + 64 + 20 + delims = ~110) */ 289 /* (growth by: 15 + 64 + 20 + delims = ~110) */
282 char printbuf[MAX_READ*2 + 128]; 290 char printbuf[MAX_READ*2 + 128];
@@ -832,12 +840,24 @@ static void timestamp_and_log(int pri, char *msg, int len)
832 msg += 16; 840 msg += 16;
833 } 841 }
834 842
843#if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS
844 if (!timestamp) {
845 struct timeval tv;
846 gettimeofday(&tv, NULL);
847 now = tv.tv_sec;
848 timestamp = ctime(&now) + 4; /* skip day of week */
849 /* overwrite year by milliseconds, zero terminate */
850 sprintf(timestamp + 15, ".%03u", (unsigned)tv.tv_usec / 1000u);
851 } else {
852 timestamp[15] = '\0';
853 }
854#else
835 if (!timestamp) { 855 if (!timestamp) {
836 time(&now); 856 time(&now);
837 timestamp = ctime(&now) + 4; /* skip day of week */ 857 timestamp = ctime(&now) + 4; /* skip day of week */
838 } 858 }
839
840 timestamp[15] = '\0'; 859 timestamp[15] = '\0';
860#endif
841 861
842 if (option_mask32 & OPT_kmsg) { 862 if (option_mask32 & OPT_kmsg) {
843 log_to_kmsg(pri, msg); 863 log_to_kmsg(pri, msg);
diff --git a/testsuite/awk.tests b/testsuite/awk.tests
index a7a533ba0..b5008290f 100755
--- a/testsuite/awk.tests
+++ b/testsuite/awk.tests
@@ -85,7 +85,8 @@ testing "awk floating const with leading zeroes" \
85 "" "\n" 85 "" "\n"
86 86
87# long field seps requiring regex 87# long field seps requiring regex
88testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ 88testing "awk long field sep" \
89 "awk -F-- '{ print NF, length(\$NF), \$NF }'" \
89 "2 0 \n3 0 \n4 0 \n5 0 \n" \ 90 "2 0 \n3 0 \n4 0 \n5 0 \n" \
90 "" \ 91 "" \
91 "a--\na--b--\na--b--c--\na--b--c--d--" 92 "a--\na--b--\na--b--c--\na--b--c--d--"
@@ -317,6 +318,26 @@ testing "awk length()" \
317 "3\n3\n3\n3\n" \ 318 "3\n3\n3\n3\n" \
318 "" "qwe" 319 "" "qwe"
319 320
321testing "awk print length, 1" \
322 "awk '{ print length, 1 }'" \
323 "0 1\n" \
324 "" "\n"
325
326testing "awk print length 1" \
327 "awk '{ print length 1 }'" \
328 "01\n" \
329 "" "\n"
330
331testing "awk length == 0" \
332 "awk 'length == 0 { print \"foo\" }'" \
333 "foo\n" \
334 "" "\n"
335
336testing "awk if (length == 0)" \
337 "awk '{ if (length == 0) { print \"bar\" } }'" \
338 "bar\n" \
339 "" "\n"
340
320testing "awk -f and ARGC" \ 341testing "awk -f and ARGC" \
321 "awk -f - input" \ 342 "awk -f - input" \
322 "re\n2\n" \ 343 "re\n2\n" \
diff --git a/testsuite/xargs.tests b/testsuite/xargs.tests
index 2d0a201b7..855b33bc2 100755
--- a/testsuite/xargs.tests
+++ b/testsuite/xargs.tests
@@ -41,4 +41,13 @@ testing "xargs -sNUM test 2" \
41 "echo 1 2 3 4 5 6 7 8 9 0\n""echo 1 2 3 4 5 6 7 8 9\n""echo 1 00\n" \ 41 "echo 1 2 3 4 5 6 7 8 9 0\n""echo 1 2 3 4 5 6 7 8 9\n""echo 1 00\n" \
42 "" "2 3 4 5 6 7 8 9 0 2 3 4 5 6 7 8 9 00\n" 42 "" "2 3 4 5 6 7 8 9 0 2 3 4 5 6 7 8 9 00\n"
43 43
44# see that we don't get "argument line too long",
45# but do see the last word, 99999, instead
46optional FEATURE_XARGS_SUPPORT_QUOTES
47testing "xargs argument line too long" \
48 "seq 10000 99999 | sed -e 's/^/\"/' -e 's/$/\"/' | xargs echo | grep -o 99999; echo \$?" \
49 "99999\n0\n" \
50 "" ""
51SKIP=
52
44exit $FAILCOUNT 53exit $FAILCOUNT
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index e58cb0fd1..f568fe92c 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -344,6 +344,7 @@ static const char *const i386_sys_types[] = {
344 "\xa8" "Darwin UFS", 344 "\xa8" "Darwin UFS",
345 "\xa9" "NetBSD", 345 "\xa9" "NetBSD",
346 "\xab" "Darwin boot", 346 "\xab" "Darwin boot",
347 "\xaf" "HFS / HFS+",
347 "\xb7" "BSDI fs", 348 "\xb7" "BSDI fs",
348 "\xb8" "BSDI swap", 349 "\xb8" "BSDI swap",
349 "\xbe" "Solaris boot", 350 "\xbe" "Solaris boot",
@@ -390,15 +391,12 @@ static const char *const i386_sys_types[] = {
390 "\xc6" "DRDOS/sec (FAT-16)", 391 "\xc6" "DRDOS/sec (FAT-16)",
391 "\xc7" "Syrinx", 392 "\xc7" "Syrinx",
392 "\xda" "Non-FS data", 393 "\xda" "Non-FS data",
393 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or 394 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */
394 Concurrent DOS or CTOS */
395 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */ 395 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
396 "\xdf" "BootIt", /* BootIt EMBRM */ 396 "\xdf" "BootIt", /* BootIt EMBRM */
397 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT 397 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT extended partition */
398 extended partition */
399 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */ 398 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
400 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended 399 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended partition <1024 cyl. */
401 partition < 1024 cyl. */
402 "\xf1" "SpeedStor", 400 "\xf1" "SpeedStor",
403 "\xf4" "SpeedStor", /* SpeedStor large partition */ 401 "\xf4" "SpeedStor", /* SpeedStor large partition */
404 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */ 402 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */