diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-12 17:12:28 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-12 17:12:28 +0000 |
commit | a68cb75a2e72303ef4a609cab28d25ccc789d685 (patch) | |
tree | c9f1fd8ef0c1d50341c4377ce467c94ec6944881 | |
parent | 0b18cd3d04b17acec73af3d2cafd00c59a3f807f (diff) | |
download | busybox-w32-a68cb75a2e72303ef4a609cab28d25ccc789d685.tar.gz busybox-w32-a68cb75a2e72303ef4a609cab28d25ccc789d685.tar.bz2 busybox-w32-a68cb75a2e72303ef4a609cab28d25ccc789d685.zip |
Applied post 1.9.0 fixes
-rw-r--r-- | Makefile.help | 1 | ||||
-rw-r--r-- | applets/applet_tables.c | 2 | ||||
-rw-r--r-- | coreutils/stty.c | 24 | ||||
-rw-r--r-- | coreutils/test.c | 49 | ||||
-rw-r--r-- | e2fsprogs/fsck.c | 6 | ||||
-rw-r--r-- | include/libbb.h | 8 | ||||
-rw-r--r-- | libbb/lineedit.c | 4 | ||||
-rw-r--r-- | networking/libiproute/iproute.c | 10 | ||||
-rw-r--r-- | networking/nameif.c | 22 | ||||
-rw-r--r-- | networking/zcip.c | 24 | ||||
-rw-r--r-- | shell/hush.c | 256 | ||||
-rw-r--r-- | shell/msh.c | 17 | ||||
-rw-r--r-- | util-linux/mkswap.c | 5 |
13 files changed, 221 insertions, 207 deletions
diff --git a/Makefile.help b/Makefile.help index 513c10c4e..f95740365 100644 --- a/Makefile.help +++ b/Makefile.help | |||
@@ -16,7 +16,6 @@ help: | |||
16 | @echo 'Configuration:' | 16 | @echo 'Configuration:' |
17 | @echo ' allnoconfig - disable all symbols in .config' | 17 | @echo ' allnoconfig - disable all symbols in .config' |
18 | @echo ' allyesconfig - enable all symbols in .config (see defconfig)' | 18 | @echo ' allyesconfig - enable all symbols in .config (see defconfig)' |
19 | @echo ' allbareconfig - enable all applets without any sub-features' | ||
20 | @echo ' config - text based configurator (of last resort)' | 19 | @echo ' config - text based configurator (of last resort)' |
21 | @echo ' defconfig - set .config to largest generic configuration' | 20 | @echo ' defconfig - set .config to largest generic configuration' |
22 | @echo ' menuconfig - interactive curses-based configurator' | 21 | @echo ' menuconfig - interactive curses-based configurator' |
diff --git a/applets/applet_tables.c b/applets/applet_tables.c index c16df06a7..3945f7c51 100644 --- a/applets/applet_tables.c +++ b/applets/applet_tables.c | |||
@@ -71,7 +71,7 @@ int main(int argc, char **argv) | |||
71 | 71 | ||
72 | puts("/* This is a generated file, don't edit */"); | 72 | puts("/* This is a generated file, don't edit */"); |
73 | 73 | ||
74 | puts("const char applet_names[] ALIGN1 ="); | 74 | puts("const char applet_names[] ALIGN1 = \"\" \n"); |
75 | for (i = 0; i < NUM_APPLETS; i++) { | 75 | for (i = 0; i < NUM_APPLETS; i++) { |
76 | printf("\"%s\" \"\\0\"\n", applets[i].name); | 76 | printf("\"%s\" \"\\0\"\n", applets[i].name); |
77 | } | 77 | } |
diff --git a/coreutils/stty.c b/coreutils/stty.c index ade2468a8..298fb5b70 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c | |||
@@ -780,30 +780,14 @@ static const struct suffix_mult stty_suffixes[] = { | |||
780 | 780 | ||
781 | static const struct mode_info *find_mode(const char *name) | 781 | static const struct mode_info *find_mode(const char *name) |
782 | { | 782 | { |
783 | int i = 0; | 783 | int i = index_in_strings(mode_name, name); |
784 | const char *m = mode_name; | 784 | return i >= 0 ? &mode_info[i] : NULL; |
785 | |||
786 | while (*m) { | ||
787 | if (strcmp(name, m) == 0) | ||
788 | return &mode_info[i]; | ||
789 | m += strlen(m) + 1; | ||
790 | i++; | ||
791 | } | ||
792 | return NULL; | ||
793 | } | 785 | } |
794 | 786 | ||
795 | static const struct control_info *find_control(const char *name) | 787 | static const struct control_info *find_control(const char *name) |
796 | { | 788 | { |
797 | int i = 0; | 789 | int i = index_in_strings(control_name, name); |
798 | const char *m = mode_name; | 790 | return i >= 0 ? &control_info[i] : NULL; |
799 | |||
800 | while (*m) { | ||
801 | if (strcmp(name, m) == 0) | ||
802 | return &control_info[i]; | ||
803 | m += strlen(m) + 1; | ||
804 | i++; | ||
805 | } | ||
806 | return NULL; | ||
807 | } | 791 | } |
808 | 792 | ||
809 | enum { | 793 | enum { |
diff --git a/coreutils/test.c b/coreutils/test.c index a30a5087d..22dadac0e 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
@@ -555,7 +555,7 @@ int test_main(int argc, char **argv) | |||
555 | { | 555 | { |
556 | int res; | 556 | int res; |
557 | const char *arg0; | 557 | const char *arg0; |
558 | bool _off; | 558 | bool negate = 0; |
559 | 559 | ||
560 | arg0 = bb_basename(argv[0]); | 560 | arg0 = bb_basename(argv[0]); |
561 | if (arg0[0] == '[') { | 561 | if (arg0[0] == '[') { |
@@ -578,9 +578,8 @@ int test_main(int argc, char **argv) | |||
578 | INIT_S(); | 578 | INIT_S(); |
579 | 579 | ||
580 | res = setjmp(leaving); | 580 | res = setjmp(leaving); |
581 | if (res) { | 581 | if (res) |
582 | goto ret; | 582 | goto ret; |
583 | } | ||
584 | 583 | ||
585 | /* resetting ngroups is probably unnecessary. it will | 584 | /* resetting ngroups is probably unnecessary. it will |
586 | * force a new call to getgroups(), which prevents using | 585 | * force a new call to getgroups(), which prevents using |
@@ -592,34 +591,40 @@ int test_main(int argc, char **argv) | |||
592 | */ | 591 | */ |
593 | ngroups = 0; | 592 | ngroups = 0; |
594 | 593 | ||
594 | //argc--; | ||
595 | argv++; | ||
596 | |||
595 | /* Implement special cases from POSIX.2, section 4.62.4 */ | 597 | /* Implement special cases from POSIX.2, section 4.62.4 */ |
596 | if (argc == 1) { | 598 | if (!argv[0]) { /* "test" */ |
597 | res = 1; | 599 | res = 1; |
598 | goto ret; | 600 | goto ret; |
599 | } | 601 | } |
600 | if (argc == 2) { | 602 | if (LONE_CHAR(argv[0], '!') && argv[1]) { |
601 | res = (*argv[1] == '\0'); | 603 | negate = 1; |
604 | //argc--; | ||
605 | argv++; | ||
606 | } | ||
607 | if (!argv[1]) { /* "test [!] arg" */ | ||
608 | res = (*argv[0] == '\0'); | ||
602 | goto ret; | 609 | goto ret; |
603 | } | 610 | } |
604 | 611 | if (argv[2] && !argv[3]) { | |
605 | /* remember if we saw argc==4 which wants *no* '!' test */ | 612 | t_lex(argv[1]); |
606 | _off = argc - 4; | ||
607 | if (_off ? (LONE_CHAR(argv[1], '!')) | ||
608 | : (argv[1][0] != '!' || argv[1][1] != '\0') | ||
609 | ) { | ||
610 | if (argc == 3) { | ||
611 | res = (*argv[2] != '\0'); | ||
612 | goto ret; | ||
613 | } | ||
614 | |||
615 | t_lex(argv[2 + _off]); | ||
616 | if (t_wp_op && t_wp_op->op_type == BINOP) { | 613 | if (t_wp_op && t_wp_op->op_type == BINOP) { |
617 | t_wp = &argv[1 + _off]; | 614 | /* "test [!] arg1 <binary_op> arg2" */ |
618 | res = (binop() == _off); | 615 | t_wp = &argv[0]; |
616 | res = (binop() == 0); | ||
619 | goto ret; | 617 | goto ret; |
620 | } | 618 | } |
621 | } | 619 | } |
622 | t_wp = &argv[1]; | 620 | |
621 | /* Some complex expression. Undo '!' removal */ | ||
622 | if (negate) { | ||
623 | negate = 0; | ||
624 | //argc++; | ||
625 | argv--; | ||
626 | } | ||
627 | t_wp = &argv[0]; | ||
623 | res = !oexpr(t_lex(*t_wp)); | 628 | res = !oexpr(t_lex(*t_wp)); |
624 | 629 | ||
625 | if (*t_wp != NULL && *++t_wp != NULL) { | 630 | if (*t_wp != NULL && *++t_wp != NULL) { |
@@ -628,5 +633,5 @@ int test_main(int argc, char **argv) | |||
628 | } | 633 | } |
629 | ret: | 634 | ret: |
630 | DEINIT_S(); | 635 | DEINIT_S(); |
631 | return res; | 636 | return negate ? !res : res; |
632 | } | 637 | } |
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index f80de8178..ef0e80d60 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c | |||
@@ -665,6 +665,12 @@ static void execute(const char *type, const char *device, const char *mntpt, | |||
665 | for (i = num_args+1; i < argc; i++) | 665 | for (i = num_args+1; i < argc; i++) |
666 | free(argv[i]); | 666 | free(argv[i]); |
667 | 667 | ||
668 | /* No pid, so don't record an instance */ | ||
669 | if (pid < 0) { | ||
670 | free(inst); | ||
671 | return; | ||
672 | } | ||
673 | |||
668 | inst->pid = pid; | 674 | inst->pid = pid; |
669 | inst->prog = argv[0]; | 675 | inst->prog = argv[0]; |
670 | inst->type = xstrdup(type); | 676 | inst->type = xstrdup(type); |
diff --git a/include/libbb.h b/include/libbb.h index 2b928215f..8f6643767 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -641,6 +641,9 @@ enum { | |||
641 | void re_exec(char **argv) ATTRIBUTE_NORETURN; | 641 | void re_exec(char **argv) ATTRIBUTE_NORETURN; |
642 | void forkexit_or_rexec(char **argv); | 642 | void forkexit_or_rexec(char **argv); |
643 | extern bool re_execed; | 643 | extern bool re_execed; |
644 | int BUG_fork_is_unavailable_on_nommu(void); | ||
645 | int BUG_daemon_is_unavailable_on_nommu(void); | ||
646 | void BUG_bb_daemonize_is_unavailable_on_nommu(void); | ||
644 | # define fork() BUG_fork_is_unavailable_on_nommu() | 647 | # define fork() BUG_fork_is_unavailable_on_nommu() |
645 | # define daemon(a,b) BUG_daemon_is_unavailable_on_nommu() | 648 | # define daemon(a,b) BUG_daemon_is_unavailable_on_nommu() |
646 | # define bb_daemonize(a) BUG_bb_daemonize_is_unavailable_on_nommu() | 649 | # define bb_daemonize(a) BUG_bb_daemonize_is_unavailable_on_nommu() |
@@ -950,10 +953,9 @@ enum { | |||
950 | }; | 953 | }; |
951 | line_input_t *new_line_input_t(int flags); | 954 | line_input_t *new_line_input_t(int flags); |
952 | /* Returns: | 955 | /* Returns: |
953 | * -1 on read errors or EOF, or on bare Ctrl-D. | 956 | * -1 on read errors or EOF, or on bare Ctrl-D, |
954 | * 0 on ctrl-C, | 957 | * 0 on ctrl-C (the line entered is still returned in 'command'), |
955 | * >0 length of input string, including terminating '\n' | 958 | * >0 length of input string, including terminating '\n' |
956 | * [is this true? stores "" in 'command' if return value is 0 or -1] | ||
957 | */ | 959 | */ |
958 | int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state); | 960 | int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state); |
959 | #else | 961 | #else |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 69768da30..c23fe3107 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -1315,8 +1315,8 @@ static void win_changed(int nsig) | |||
1315 | #define CTRL(a) ((a) & ~0x40) | 1315 | #define CTRL(a) ((a) & ~0x40) |
1316 | 1316 | ||
1317 | /* Returns: | 1317 | /* Returns: |
1318 | * -1 on read errors or EOF, or on bare Ctrl-D. | 1318 | * -1 on read errors or EOF, or on bare Ctrl-D, |
1319 | * 0 on ctrl-C, | 1319 | * 0 on ctrl-C (the line entered is still returned in 'command'), |
1320 | * >0 length of input string, including terminating '\n' | 1320 | * >0 length of input string, including terminating '\n' |
1321 | */ | 1321 | */ |
1322 | int read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st) | 1322 | int read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st) |
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index ce2cd8b39..5ded99b2e 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c | |||
@@ -841,15 +841,17 @@ int do_iproute(char **argv) | |||
841 | /*0-3*/ "add\0""append\0""change\0""chg\0" | 841 | /*0-3*/ "add\0""append\0""change\0""chg\0" |
842 | /*4-7*/ "delete\0""get\0""list\0""show\0" | 842 | /*4-7*/ "delete\0""get\0""list\0""show\0" |
843 | /*8..*/ "prepend\0""replace\0""test\0""flush\0"; | 843 | /*8..*/ "prepend\0""replace\0""test\0""flush\0"; |
844 | int command_num = 6; | 844 | int command_num; |
845 | unsigned flags = 0; | 845 | unsigned flags = 0; |
846 | int cmd = RTM_NEWROUTE; | 846 | int cmd = RTM_NEWROUTE; |
847 | 847 | ||
848 | if (!*argv) | ||
849 | return iproute_list_or_flush(argv, 0); | ||
850 | |||
848 | /* "Standard" 'ip r a' treats 'a' as 'add', not 'append' */ | 851 | /* "Standard" 'ip r a' treats 'a' as 'add', not 'append' */ |
849 | /* It probably means that it is using "first match" rule */ | 852 | /* It probably means that it is using "first match" rule */ |
850 | if (*argv) { | 853 | command_num = index_in_substrings(ip_route_commands, *argv); |
851 | command_num = index_in_substrings(ip_route_commands, *argv); | 854 | |
852 | } | ||
853 | switch (command_num) { | 855 | switch (command_num) { |
854 | case 0: /* add */ | 856 | case 0: /* add */ |
855 | flags = NLM_F_CREATE|NLM_F_EXCL; | 857 | flags = NLM_F_CREATE|NLM_F_EXCL; |
diff --git a/networking/nameif.c b/networking/nameif.c index 66376a500..c92b352da 100644 --- a/networking/nameif.c +++ b/networking/nameif.c | |||
@@ -50,18 +50,18 @@ typedef struct ethtable_s { | |||
50 | #define ETHTOOL_BUSINFO_LEN 32 | 50 | #define ETHTOOL_BUSINFO_LEN 32 |
51 | /* these strings are set to whatever the driver author decides... */ | 51 | /* these strings are set to whatever the driver author decides... */ |
52 | struct ethtool_drvinfo { | 52 | struct ethtool_drvinfo { |
53 | __u32 cmd; | 53 | uint32_t cmd; |
54 | char driver[32]; /* driver short name, "tulip", "eepro100" */ | 54 | char driver[32]; /* driver short name, "tulip", "eepro100" */ |
55 | char version[32]; /* driver version string */ | 55 | char version[32]; /* driver version string */ |
56 | char fw_version[32]; /* firmware version string, if applicable */ | 56 | char fw_version[32]; /* firmware version string, if applicable */ |
57 | char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ | 57 | char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ |
58 | /* For PCI devices, use pci_dev->slot_name. */ | 58 | /* For PCI devices, use pci_dev->slot_name. */ |
59 | char reserved1[32]; | 59 | char reserved1[32]; |
60 | char reserved2[16]; | 60 | char reserved2[16]; |
61 | __u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */ | 61 | uint32_t n_stats; /* number of u64's from ETHTOOL_GSTATS */ |
62 | __u32 testinfo_len; | 62 | uint32_t testinfo_len; |
63 | __u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ | 63 | uint32_t eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ |
64 | __u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ | 64 | uint32_t regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ |
65 | }; | 65 | }; |
66 | #define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ | 66 | #define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ |
67 | #endif | 67 | #endif |
diff --git a/networking/zcip.c b/networking/zcip.c index ef9aa2186..8ffed8593 100644 --- a/networking/zcip.c +++ b/networking/zcip.c | |||
@@ -180,7 +180,7 @@ int zcip_main(int argc, char **argv) | |||
180 | char *r_opt; | 180 | char *r_opt; |
181 | unsigned opts; | 181 | unsigned opts; |
182 | 182 | ||
183 | /* Ugly trick, but I want these zeroed in one go */ | 183 | // ugly trick, but I want these zeroed in one go |
184 | struct { | 184 | struct { |
185 | const struct in_addr null_ip; | 185 | const struct in_addr null_ip; |
186 | const struct ether_addr null_addr; | 186 | const struct ether_addr null_addr; |
@@ -214,8 +214,17 @@ int zcip_main(int argc, char **argv) | |||
214 | // exactly 2 args; -v accumulates and implies -f | 214 | // exactly 2 args; -v accumulates and implies -f |
215 | opt_complementary = "=2:vv:vf"; | 215 | opt_complementary = "=2:vv:vf"; |
216 | opts = getopt32(argv, "fqr:v", &r_opt, &verbose); | 216 | opts = getopt32(argv, "fqr:v", &r_opt, &verbose); |
217 | #if !BB_MMU | ||
218 | // on NOMMU reexec early (or else we will rerun things twice) | ||
219 | if (!FOREGROUND) | ||
220 | bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); | ||
221 | #endif | ||
222 | // open an ARP socket | ||
223 | // (need to do it before openlog to prevent openlog from taking | ||
224 | // fd 3 (sock_fd==3)) | ||
225 | xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd); | ||
217 | if (!FOREGROUND) { | 226 | if (!FOREGROUND) { |
218 | /* Do it early, before all bb_xx_msg calls */ | 227 | // do it before all bb_xx_msg calls |
219 | openlog(applet_name, 0, LOG_DAEMON); | 228 | openlog(applet_name, 0, LOG_DAEMON); |
220 | logmode |= LOGMODE_SYSLOG; | 229 | logmode |= LOGMODE_SYSLOG; |
221 | } | 230 | } |
@@ -226,11 +235,6 @@ int zcip_main(int argc, char **argv) | |||
226 | bb_error_msg_and_die("invalid link address"); | 235 | bb_error_msg_and_die("invalid link address"); |
227 | } | 236 | } |
228 | } | 237 | } |
229 | // On NOMMU reexec early (or else we will rerun things twice) | ||
230 | #if !BB_MMU | ||
231 | if (!FOREGROUND) | ||
232 | bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); | ||
233 | #endif | ||
234 | argc -= optind; | 238 | argc -= optind; |
235 | argv += optind; | 239 | argv += optind; |
236 | 240 | ||
@@ -249,8 +253,6 @@ int zcip_main(int argc, char **argv) | |||
249 | //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?! | 253 | //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?! |
250 | safe_strncpy(saddr.sa_data, intf, sizeof(saddr.sa_data)); | 254 | safe_strncpy(saddr.sa_data, intf, sizeof(saddr.sa_data)); |
251 | 255 | ||
252 | // open an ARP socket | ||
253 | xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd); | ||
254 | // bind to the interface's ARP socket | 256 | // bind to the interface's ARP socket |
255 | xbind(sock_fd, &saddr, sizeof(saddr)); | 257 | xbind(sock_fd, &saddr, sizeof(saddr)); |
256 | 258 | ||
@@ -290,7 +292,7 @@ int zcip_main(int argc, char **argv) | |||
290 | // restarting after address conflicts: | 292 | // restarting after address conflicts: |
291 | // - start with some address we want to try | 293 | // - start with some address we want to try |
292 | // - short random delay | 294 | // - short random delay |
293 | // - arp probes to see if another host else uses it | 295 | // - arp probes to see if another host uses it |
294 | // - arp announcements that we're claiming it | 296 | // - arp announcements that we're claiming it |
295 | // - use it | 297 | // - use it |
296 | // - defend it, within limits | 298 | // - defend it, within limits |
@@ -321,7 +323,7 @@ int zcip_main(int argc, char **argv) | |||
321 | switch (safe_poll(fds, 1, timeout_ms)) { | 323 | switch (safe_poll(fds, 1, timeout_ms)) { |
322 | 324 | ||
323 | default: | 325 | default: |
324 | /*bb_perror_msg("poll"); - done in safe_poll */ | 326 | //bb_perror_msg("poll"); - done in safe_poll |
325 | return EXIT_FAILURE; | 327 | return EXIT_FAILURE; |
326 | 328 | ||
327 | // timeout | 329 | // timeout |
diff --git a/shell/hush.c b/shell/hush.c index cb2c3e98e..c01af5f38 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -80,18 +80,28 @@ | |||
80 | #include <glob.h> /* glob, of course */ | 80 | #include <glob.h> /* glob, of course */ |
81 | #include <getopt.h> /* should be pretty obvious */ | 81 | #include <getopt.h> /* should be pretty obvious */ |
82 | /* #include <dmalloc.h> */ | 82 | /* #include <dmalloc.h> */ |
83 | extern char **environ; | ||
84 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ | ||
83 | 85 | ||
84 | extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */ | ||
85 | 86 | ||
86 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ | 87 | #if !BB_MMU && ENABLE_HUSH_TICK |
88 | //#undef ENABLE_HUSH_TICK | ||
89 | //#define ENABLE_HUSH_TICK 0 | ||
90 | #warning On NOMMU, hush command substitution is dangerous. | ||
91 | #warning Dont use it for commands which produce lots of output. | ||
92 | #warning For more info see shell/hush.c, generate_stream_from_list(). | ||
93 | #endif | ||
87 | 94 | ||
95 | #if !BB_MMU && ENABLE_HUSH_JOB | ||
96 | #undef ENABLE_HUSH_JOB | ||
97 | #define ENABLE_HUSH_JOB 0 | ||
98 | #endif | ||
88 | 99 | ||
89 | #if !BB_MMU | 100 | #if !ENABLE_HUSH_INTERACTIVE |
90 | /* A bit drastic. Can allow some simpler commands | 101 | #undef ENABLE_FEATURE_EDITING |
91 | * by analysing command in generate_stream_from_list() | 102 | #define ENABLE_FEATURE_EDITING 0 |
92 | */ | 103 | #undef ENABLE_FEATURE_EDITING_FANCY_PROMPT |
93 | #undef ENABLE_HUSH_TICK | 104 | #define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0 |
94 | #define ENABLE_HUSH_TICK 0 | ||
95 | #endif | 105 | #endif |
96 | 106 | ||
97 | 107 | ||
@@ -178,13 +188,6 @@ void xxfree(void *ptr) | |||
178 | #endif | 188 | #endif |
179 | 189 | ||
180 | 190 | ||
181 | #if !ENABLE_HUSH_INTERACTIVE | ||
182 | #undef ENABLE_FEATURE_EDITING | ||
183 | #define ENABLE_FEATURE_EDITING 0 | ||
184 | #undef ENABLE_FEATURE_EDITING_FANCY_PROMPT | ||
185 | #define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0 | ||
186 | #endif | ||
187 | |||
188 | #define SPECIAL_VAR_SYMBOL 3 | 191 | #define SPECIAL_VAR_SYMBOL 3 |
189 | 192 | ||
190 | #define PARSEFLAG_EXIT_FROM_LOOP 1 | 193 | #define PARSEFLAG_EXIT_FROM_LOOP 1 |
@@ -510,10 +513,10 @@ static int free_pipe_list(struct pipe *head, int indent); | |||
510 | static int free_pipe(struct pipe *pi, int indent); | 513 | static int free_pipe(struct pipe *pi, int indent); |
511 | /* really run the final data structures: */ | 514 | /* really run the final data structures: */ |
512 | static int setup_redirects(struct child_prog *prog, int squirrel[]); | 515 | static int setup_redirects(struct child_prog *prog, int squirrel[]); |
513 | static int run_list_real(struct pipe *pi); | 516 | static int run_list(struct pipe *pi); |
514 | static void pseudo_exec_argv(char **argv) ATTRIBUTE_NORETURN; | 517 | static void pseudo_exec_argv(char **argv) ATTRIBUTE_NORETURN; |
515 | static void pseudo_exec(struct child_prog *child) ATTRIBUTE_NORETURN; | 518 | static void pseudo_exec(struct child_prog *child) ATTRIBUTE_NORETURN; |
516 | static int run_pipe_real(struct pipe *pi); | 519 | static int run_pipe(struct pipe *pi); |
517 | /* extended glob support: */ | 520 | /* extended glob support: */ |
518 | static char **globhack(const char *src, char **strings); | 521 | static char **globhack(const char *src, char **strings); |
519 | static int glob_needed(const char *s); | 522 | static int glob_needed(const char *s); |
@@ -1418,7 +1421,7 @@ static void restore_redirects(int squirrel[]) | |||
1418 | } | 1421 | } |
1419 | } | 1422 | } |
1420 | 1423 | ||
1421 | /* Called after [v]fork() in run_pipe_real(), or from builtin_exec(). | 1424 | /* Called after [v]fork() in run_pipe(), or from builtin_exec(). |
1422 | * Never returns. | 1425 | * Never returns. |
1423 | * XXX no exit() here. If you don't exec, use _exit instead. | 1426 | * XXX no exit() here. If you don't exec, use _exit instead. |
1424 | * The at_exit handlers apparently confuse the calling process, | 1427 | * The at_exit handlers apparently confuse the calling process, |
@@ -1440,9 +1443,8 @@ static void pseudo_exec_argv(char **argv) | |||
1440 | /* If a variable is assigned in a forest, and nobody listens, | 1443 | /* If a variable is assigned in a forest, and nobody listens, |
1441 | * was it ever really set? | 1444 | * was it ever really set? |
1442 | */ | 1445 | */ |
1443 | if (argv[0] == NULL) { | 1446 | if (!argv[0]) |
1444 | _exit(EXIT_SUCCESS); | 1447 | _exit(EXIT_SUCCESS); |
1445 | } | ||
1446 | 1448 | ||
1447 | argv = expand_strvec_to_strvec(argv); | 1449 | argv = expand_strvec_to_strvec(argv); |
1448 | 1450 | ||
@@ -1486,15 +1488,15 @@ static void pseudo_exec_argv(char **argv) | |||
1486 | _exit(1); | 1488 | _exit(1); |
1487 | } | 1489 | } |
1488 | 1490 | ||
1489 | /* Called after [v]fork() in run_pipe_real() | 1491 | /* Called after [v]fork() in run_pipe() |
1490 | */ | 1492 | */ |
1491 | static void pseudo_exec(struct child_prog *child) | 1493 | static void pseudo_exec(struct child_prog *child) |
1492 | { | 1494 | { |
1493 | // FIXME: buggy wrt NOMMU! Must not modify any global data | 1495 | // FIXME: buggy wrt NOMMU! Must not modify any global data |
1494 | // until it does exec/_exit, but currently it does. | 1496 | // until it does exec/_exit, but currently it does |
1495 | if (child->argv) { | 1497 | // (puts malloc'ed stuff into environment) |
1498 | if (child->argv) | ||
1496 | pseudo_exec_argv(child->argv); | 1499 | pseudo_exec_argv(child->argv); |
1497 | } | ||
1498 | 1500 | ||
1499 | if (child->group) { | 1501 | if (child->group) { |
1500 | #if !BB_MMU | 1502 | #if !BB_MMU |
@@ -1503,11 +1505,12 @@ static void pseudo_exec(struct child_prog *child) | |||
1503 | int rcode; | 1505 | int rcode; |
1504 | 1506 | ||
1505 | #if ENABLE_HUSH_INTERACTIVE | 1507 | #if ENABLE_HUSH_INTERACTIVE |
1506 | debug_printf_exec("pseudo_exec: setting interactive_fd=0\n"); | 1508 | // run_list_level now takes care of it? |
1507 | interactive_fd = 0; /* crucial!!!! */ | 1509 | // debug_printf_exec("pseudo_exec: setting interactive_fd=0\n"); |
1510 | // interactive_fd = 0; /* crucial!!!! */ | ||
1508 | #endif | 1511 | #endif |
1509 | debug_printf_exec("pseudo_exec: run_list_real\n"); | 1512 | debug_printf_exec("pseudo_exec: run_list\n"); |
1510 | rcode = run_list_real(child->group); | 1513 | rcode = run_list(child->group); |
1511 | /* OK to leak memory by not calling free_pipe_list, | 1514 | /* OK to leak memory by not calling free_pipe_list, |
1512 | * since this process is about to exit */ | 1515 | * since this process is about to exit */ |
1513 | _exit(rcode); | 1516 | _exit(rcode); |
@@ -1649,6 +1652,7 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1649 | // + killall -STOP cat | 1652 | // + killall -STOP cat |
1650 | 1653 | ||
1651 | wait_more: | 1654 | wait_more: |
1655 | // TODO: safe_waitpid? | ||
1652 | while ((childpid = waitpid(-1, &status, attributes)) > 0) { | 1656 | while ((childpid = waitpid(-1, &status, attributes)) > 0) { |
1653 | const int dead = WIFEXITED(status) || WIFSIGNALED(status); | 1657 | const int dead = WIFEXITED(status) || WIFSIGNALED(status); |
1654 | 1658 | ||
@@ -1673,7 +1677,7 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1673 | if (dead) { | 1677 | if (dead) { |
1674 | fg_pipe->progs[i].pid = 0; | 1678 | fg_pipe->progs[i].pid = 0; |
1675 | fg_pipe->running_progs--; | 1679 | fg_pipe->running_progs--; |
1676 | if (i == fg_pipe->num_progs-1) | 1680 | if (i == fg_pipe->num_progs - 1) |
1677 | /* last process gives overall exitstatus */ | 1681 | /* last process gives overall exitstatus */ |
1678 | rcode = WEXITSTATUS(status); | 1682 | rcode = WEXITSTATUS(status); |
1679 | } else { | 1683 | } else { |
@@ -1754,13 +1758,13 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe) | |||
1754 | } | 1758 | } |
1755 | #endif | 1759 | #endif |
1756 | 1760 | ||
1757 | /* run_pipe_real() starts all the jobs, but doesn't wait for anything | 1761 | /* run_pipe() starts all the jobs, but doesn't wait for anything |
1758 | * to finish. See checkjobs(). | 1762 | * to finish. See checkjobs(). |
1759 | * | 1763 | * |
1760 | * return code is normally -1, when the caller has to wait for children | 1764 | * return code is normally -1, when the caller has to wait for children |
1761 | * to finish to determine the exit status of the pipe. If the pipe | 1765 | * to finish to determine the exit status of the pipe. If the pipe |
1762 | * is a simple builtin command, however, the action is done by the | 1766 | * is a simple builtin command, however, the action is done by the |
1763 | * time run_pipe_real returns, and the exit code is provided as the | 1767 | * time run_pipe returns, and the exit code is provided as the |
1764 | * return value. | 1768 | * return value. |
1765 | * | 1769 | * |
1766 | * The input of the pipe is always stdin, the output is always | 1770 | * The input of the pipe is always stdin, the output is always |
@@ -1773,11 +1777,11 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe) | |||
1773 | * Returns -1 only if started some children. IOW: we have to | 1777 | * Returns -1 only if started some children. IOW: we have to |
1774 | * mask out retvals of builtins etc with 0xff! | 1778 | * mask out retvals of builtins etc with 0xff! |
1775 | */ | 1779 | */ |
1776 | static int run_pipe_real(struct pipe *pi) | 1780 | static int run_pipe(struct pipe *pi) |
1777 | { | 1781 | { |
1778 | int i; | 1782 | int i; |
1779 | int nextin, nextout; | 1783 | int nextin; |
1780 | int pipefds[2]; /* pipefds[0] is for reading */ | 1784 | int pipefds[2]; /* pipefds[0] is for reading */ |
1781 | struct child_prog *child; | 1785 | struct child_prog *child; |
1782 | const struct built_in_command *x; | 1786 | const struct built_in_command *x; |
1783 | char *p; | 1787 | char *p; |
@@ -1786,9 +1790,8 @@ static int run_pipe_real(struct pipe *pi) | |||
1786 | int rcode; | 1790 | int rcode; |
1787 | const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG); | 1791 | const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG); |
1788 | 1792 | ||
1789 | debug_printf_exec("run_pipe_real start: single_fg=%d\n", single_fg); | 1793 | debug_printf_exec("run_pipe start: single_fg=%d\n", single_fg); |
1790 | 1794 | ||
1791 | nextin = 0; | ||
1792 | #if ENABLE_HUSH_JOB | 1795 | #if ENABLE_HUSH_JOB |
1793 | pi->pgrp = -1; | 1796 | pi->pgrp = -1; |
1794 | #endif | 1797 | #endif |
@@ -1803,11 +1806,11 @@ static int run_pipe_real(struct pipe *pi) | |||
1803 | if (single_fg && child->group && child->subshell == 0) { | 1806 | if (single_fg && child->group && child->subshell == 0) { |
1804 | debug_printf("non-subshell grouping\n"); | 1807 | debug_printf("non-subshell grouping\n"); |
1805 | setup_redirects(child, squirrel); | 1808 | setup_redirects(child, squirrel); |
1806 | debug_printf_exec(": run_list_real\n"); | 1809 | debug_printf_exec(": run_list\n"); |
1807 | rcode = run_list_real(child->group); | 1810 | rcode = run_list(child->group) & 0xff; |
1808 | restore_redirects(squirrel); | 1811 | restore_redirects(squirrel); |
1809 | debug_printf_exec("run_pipe_real return %d\n", rcode); | 1812 | debug_printf_exec("run_pipe return %d\n", rcode); |
1810 | return rcode; // do we need to add '... & 0xff' ? | 1813 | return rcode; |
1811 | } | 1814 | } |
1812 | 1815 | ||
1813 | if (single_fg && child->argv != NULL) { | 1816 | if (single_fg && child->argv != NULL) { |
@@ -1849,7 +1852,7 @@ static int run_pipe_real(struct pipe *pi) | |||
1849 | rcode = x->function(argv_expanded) & 0xff; | 1852 | rcode = x->function(argv_expanded) & 0xff; |
1850 | free(argv_expanded); | 1853 | free(argv_expanded); |
1851 | restore_redirects(squirrel); | 1854 | restore_redirects(squirrel); |
1852 | debug_printf_exec("run_pipe_real return %d\n", rcode); | 1855 | debug_printf_exec("run_pipe return %d\n", rcode); |
1853 | return rcode; | 1856 | return rcode; |
1854 | } | 1857 | } |
1855 | } | 1858 | } |
@@ -1866,20 +1869,21 @@ static int run_pipe_real(struct pipe *pi) | |||
1866 | rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded) & 0xff; | 1869 | rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded) & 0xff; |
1867 | free(argv_expanded); | 1870 | free(argv_expanded); |
1868 | restore_redirects(squirrel); | 1871 | restore_redirects(squirrel); |
1869 | debug_printf_exec("run_pipe_real return %d\n", rcode); | 1872 | debug_printf_exec("run_pipe return %d\n", rcode); |
1870 | return rcode; | 1873 | return rcode; |
1871 | } | 1874 | } |
1872 | } | 1875 | } |
1873 | #endif | 1876 | #endif |
1874 | } | 1877 | } |
1875 | 1878 | ||
1876 | /* Going to fork a child per each pipe member */ | ||
1877 | pi->running_progs = 0; | ||
1878 | |||
1879 | /* Disable job control signals for shell (parent) and | 1879 | /* Disable job control signals for shell (parent) and |
1880 | * for initial child code after fork */ | 1880 | * for initial child code after fork */ |
1881 | set_jobctrl_sighandler(SIG_IGN); | 1881 | set_jobctrl_sighandler(SIG_IGN); |
1882 | 1882 | ||
1883 | /* Going to fork a child per each pipe member */ | ||
1884 | pi->running_progs = 0; | ||
1885 | nextin = 0; | ||
1886 | |||
1883 | for (i = 0; i < pi->num_progs; i++) { | 1887 | for (i = 0; i < pi->num_progs; i++) { |
1884 | child = &(pi->progs[i]); | 1888 | child = &(pi->progs[i]); |
1885 | if (child->argv) | 1889 | if (child->argv) |
@@ -1888,42 +1892,34 @@ static int run_pipe_real(struct pipe *pi) | |||
1888 | debug_printf_exec(": pipe member with no argv\n"); | 1892 | debug_printf_exec(": pipe member with no argv\n"); |
1889 | 1893 | ||
1890 | /* pipes are inserted between pairs of commands */ | 1894 | /* pipes are inserted between pairs of commands */ |
1891 | if ((i + 1) < pi->num_progs) { | 1895 | pipefds[0] = 0; |
1892 | pipe(pipefds); | 1896 | pipefds[1] = 1; |
1893 | nextout = pipefds[1]; | 1897 | if ((i + 1) < pi->num_progs) |
1894 | } else { | 1898 | xpipe(pipefds); |
1895 | nextout = 1; | ||
1896 | pipefds[0] = -1; | ||
1897 | } | ||
1898 | 1899 | ||
1899 | /* XXX test for failed fork()? */ | 1900 | child->pid = BB_MMU ? fork() : vfork(); |
1900 | #if BB_MMU | ||
1901 | child->pid = fork(); | ||
1902 | #else | ||
1903 | child->pid = vfork(); | ||
1904 | #endif | ||
1905 | if (!child->pid) { /* child */ | 1901 | if (!child->pid) { /* child */ |
1906 | /* Every child adds itself to new process group | ||
1907 | * with pgid == pid of first child in pipe */ | ||
1908 | #if ENABLE_HUSH_JOB | 1902 | #if ENABLE_HUSH_JOB |
1903 | /* Every child adds itself to new process group | ||
1904 | * with pgid == pid_of_first_child_in_pipe */ | ||
1909 | if (run_list_level == 1 && interactive_fd) { | 1905 | if (run_list_level == 1 && interactive_fd) { |
1906 | pid_t pgrp; | ||
1910 | /* Don't do pgrp restore anymore on fatal signals */ | 1907 | /* Don't do pgrp restore anymore on fatal signals */ |
1911 | set_fatal_sighandler(SIG_DFL); | 1908 | set_fatal_sighandler(SIG_DFL); |
1912 | if (pi->pgrp < 0) /* true for 1st process only */ | 1909 | pgrp = pi->pgrp; |
1913 | pi->pgrp = getpid(); | 1910 | if (pgrp < 0) /* true for 1st process only */ |
1914 | if (setpgid(0, pi->pgrp) == 0 && pi->followup != PIPE_BG) { | 1911 | pgrp = getpid(); |
1912 | if (setpgid(0, pgrp) == 0 && pi->followup != PIPE_BG) { | ||
1915 | /* We do it in *every* child, not just first, | 1913 | /* We do it in *every* child, not just first, |
1916 | * to avoid races */ | 1914 | * to avoid races */ |
1917 | tcsetpgrp(interactive_fd, pi->pgrp); | 1915 | tcsetpgrp(interactive_fd, pgrp); |
1918 | } | 1916 | } |
1919 | } | 1917 | } |
1920 | #endif | 1918 | #endif |
1921 | /* in non-interactive case fatal sigs are already SIG_DFL */ | ||
1922 | xmove_fd(nextin, 0); | 1919 | xmove_fd(nextin, 0); |
1923 | xmove_fd(nextout, 1); | 1920 | xmove_fd(pipefds[1], 1); /* write end */ |
1924 | if (pipefds[0] != -1) { | 1921 | if (pipefds[0] > 1) |
1925 | close(pipefds[0]); /* opposite end of our output pipe */ | 1922 | close(pipefds[0]); /* read end */ |
1926 | } | ||
1927 | /* Like bash, explicit redirects override pipes, | 1923 | /* Like bash, explicit redirects override pipes, |
1928 | * and the pipe fd is available for dup'ing. */ | 1924 | * and the pipe fd is available for dup'ing. */ |
1929 | setup_redirects(child, NULL); | 1925 | setup_redirects(child, NULL); |
@@ -1932,26 +1928,35 @@ static int run_pipe_real(struct pipe *pi) | |||
1932 | set_jobctrl_sighandler(SIG_DFL); | 1928 | set_jobctrl_sighandler(SIG_DFL); |
1933 | set_misc_sighandler(SIG_DFL); | 1929 | set_misc_sighandler(SIG_DFL); |
1934 | signal(SIGCHLD, SIG_DFL); | 1930 | signal(SIGCHLD, SIG_DFL); |
1935 | pseudo_exec(child); | 1931 | pseudo_exec(child); /* does not return */ |
1936 | } | 1932 | } |
1937 | 1933 | ||
1938 | pi->running_progs++; | 1934 | if (child->pid < 0) { /* [v]fork failed */ |
1939 | 1935 | /* Clearly indicate, was it fork or vfork */ | |
1936 | bb_perror_msg(BB_MMU ? "fork" : "vfork"); | ||
1937 | } else { | ||
1938 | pi->running_progs++; | ||
1940 | #if ENABLE_HUSH_JOB | 1939 | #if ENABLE_HUSH_JOB |
1941 | /* Second and next children need to know pid of first one */ | 1940 | /* Second and next children need to know pid of first one */ |
1942 | if (pi->pgrp < 0) | 1941 | if (pi->pgrp < 0) |
1943 | pi->pgrp = child->pid; | 1942 | pi->pgrp = child->pid; |
1944 | #endif | 1943 | #endif |
1945 | if (nextin != 0) | 1944 | } |
1946 | close(nextin); | ||
1947 | if (nextout != 1) | ||
1948 | close(nextout); | ||
1949 | 1945 | ||
1950 | /* If there isn't another process, nextin is garbage | 1946 | if (i) |
1951 | but it doesn't matter */ | 1947 | close(nextin); |
1948 | if ((i + 1) < pi->num_progs) | ||
1949 | close(pipefds[1]); /* write end */ | ||
1950 | /* Pass read (output) pipe end to next iteration */ | ||
1952 | nextin = pipefds[0]; | 1951 | nextin = pipefds[0]; |
1953 | } | 1952 | } |
1954 | debug_printf_exec("run_pipe_real return -1\n"); | 1953 | |
1954 | if (!pi->running_progs) { | ||
1955 | debug_printf_exec("run_pipe return 1 (all forks failed, no children)\n"); | ||
1956 | return 1; | ||
1957 | } | ||
1958 | |||
1959 | debug_printf_exec("run_pipe return -1 (%u children started)\n", pi->running_progs); | ||
1955 | return -1; | 1960 | return -1; |
1956 | } | 1961 | } |
1957 | 1962 | ||
@@ -2020,7 +2025,7 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
2020 | 2025 | ||
2021 | /* NB: called by pseudo_exec, and therefore must not modify any | 2026 | /* NB: called by pseudo_exec, and therefore must not modify any |
2022 | * global data until exec/_exit (we can be a child after vfork!) */ | 2027 | * global data until exec/_exit (we can be a child after vfork!) */ |
2023 | static int run_list_real(struct pipe *pi) | 2028 | static int run_list(struct pipe *pi) |
2024 | { | 2029 | { |
2025 | struct pipe *rpipe; | 2030 | struct pipe *rpipe; |
2026 | #if ENABLE_HUSH_LOOPS | 2031 | #if ENABLE_HUSH_LOOPS |
@@ -2029,7 +2034,6 @@ static int run_list_real(struct pipe *pi) | |||
2029 | char **for_list = NULL; | 2034 | char **for_list = NULL; |
2030 | int flag_rep = 0; | 2035 | int flag_rep = 0; |
2031 | #endif | 2036 | #endif |
2032 | int save_num_progs; | ||
2033 | int flag_skip = 1; | 2037 | int flag_skip = 1; |
2034 | int rcode = 0; /* probably for gcc only */ | 2038 | int rcode = 0; /* probably for gcc only */ |
2035 | int flag_restore = 0; | 2039 | int flag_restore = 0; |
@@ -2041,7 +2045,7 @@ static int run_list_real(struct pipe *pi) | |||
2041 | reserved_style rword; | 2045 | reserved_style rword; |
2042 | reserved_style skip_more_for_this_rword = RES_XXXX; | 2046 | reserved_style skip_more_for_this_rword = RES_XXXX; |
2043 | 2047 | ||
2044 | debug_printf_exec("run_list_real start lvl %d\n", run_list_level + 1); | 2048 | debug_printf_exec("run_list start lvl %d\n", run_list_level + 1); |
2045 | 2049 | ||
2046 | #if ENABLE_HUSH_LOOPS | 2050 | #if ENABLE_HUSH_LOOPS |
2047 | /* check syntax for "for" */ | 2051 | /* check syntax for "for" */ |
@@ -2050,7 +2054,7 @@ static int run_list_real(struct pipe *pi) | |||
2050 | && (rpipe->next == NULL) | 2054 | && (rpipe->next == NULL) |
2051 | ) { | 2055 | ) { |
2052 | syntax("malformed for"); /* no IN or no commands after IN */ | 2056 | syntax("malformed for"); /* no IN or no commands after IN */ |
2053 | debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level); | 2057 | debug_printf_exec("run_list lvl %d return 1\n", run_list_level); |
2054 | return 1; | 2058 | return 1; |
2055 | } | 2059 | } |
2056 | if ((rpipe->res_word == RES_IN && rpipe->next->res_word == RES_IN && rpipe->next->progs[0].argv != NULL) | 2060 | if ((rpipe->res_word == RES_IN && rpipe->next->res_word == RES_IN && rpipe->next->progs[0].argv != NULL) |
@@ -2058,7 +2062,7 @@ static int run_list_real(struct pipe *pi) | |||
2058 | ) { | 2062 | ) { |
2059 | /* TODO: what is tested in the first condition? */ | 2063 | /* TODO: what is tested in the first condition? */ |
2060 | syntax("malformed for"); /* 2nd condition: not followed by IN */ | 2064 | syntax("malformed for"); /* 2nd condition: not followed by IN */ |
2061 | debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level); | 2065 | debug_printf_exec("run_list lvl %d return 1\n", run_list_level); |
2062 | return 1; | 2066 | return 1; |
2063 | } | 2067 | } |
2064 | } | 2068 | } |
@@ -2106,9 +2110,10 @@ static int run_list_real(struct pipe *pi) | |||
2106 | signal_SA_RESTART(SIGTSTP, handler_ctrl_z); | 2110 | signal_SA_RESTART(SIGTSTP, handler_ctrl_z); |
2107 | signal(SIGINT, handler_ctrl_c); | 2111 | signal(SIGINT, handler_ctrl_c); |
2108 | } | 2112 | } |
2109 | #endif | 2113 | #endif /* JOB */ |
2110 | 2114 | ||
2111 | for (; pi; pi = flag_restore ? rpipe : pi->next) { | 2115 | for (; pi; pi = flag_restore ? rpipe : pi->next) { |
2116 | //why? int save_num_progs; | ||
2112 | rword = pi->res_word; | 2117 | rword = pi->res_word; |
2113 | #if ENABLE_HUSH_LOOPS | 2118 | #if ENABLE_HUSH_LOOPS |
2114 | if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) { | 2119 | if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) { |
@@ -2181,12 +2186,12 @@ static int run_list_real(struct pipe *pi) | |||
2181 | #endif | 2186 | #endif |
2182 | if (pi->num_progs == 0) | 2187 | if (pi->num_progs == 0) |
2183 | continue; | 2188 | continue; |
2184 | save_num_progs = pi->num_progs; /* save number of programs */ | 2189 | //why? save_num_progs = pi->num_progs; |
2185 | debug_printf_exec(": run_pipe_real with %d members\n", pi->num_progs); | 2190 | debug_printf_exec(": run_pipe with %d members\n", pi->num_progs); |
2186 | rcode = run_pipe_real(pi); | 2191 | rcode = run_pipe(pi); |
2187 | if (rcode != -1) { | 2192 | if (rcode != -1) { |
2188 | /* We only ran a builtin: rcode was set by the return value | 2193 | /* We only ran a builtin: rcode was set by the return value |
2189 | * of run_pipe_real(), and we don't need to wait for anything. */ | 2194 | * of run_pipe(), and we don't need to wait for anything. */ |
2190 | } else if (pi->followup == PIPE_BG) { | 2195 | } else if (pi->followup == PIPE_BG) { |
2191 | /* What does bash do with attempts to background builtins? */ | 2196 | /* What does bash do with attempts to background builtins? */ |
2192 | /* Even bash 3.2 doesn't do that well with nested bg: | 2197 | /* Even bash 3.2 doesn't do that well with nested bg: |
@@ -2199,7 +2204,6 @@ static int run_list_real(struct pipe *pi) | |||
2199 | rcode = EXIT_SUCCESS; | 2204 | rcode = EXIT_SUCCESS; |
2200 | } else { | 2205 | } else { |
2201 | #if ENABLE_HUSH_JOB | 2206 | #if ENABLE_HUSH_JOB |
2202 | /* Paranoia, just "interactive_fd" should be enough? */ | ||
2203 | if (run_list_level == 1 && interactive_fd) { | 2207 | if (run_list_level == 1 && interactive_fd) { |
2204 | /* waits for completion, then fg's main shell */ | 2208 | /* waits for completion, then fg's main shell */ |
2205 | rcode = checkjobs_and_fg_shell(pi); | 2209 | rcode = checkjobs_and_fg_shell(pi); |
@@ -2213,7 +2217,7 @@ static int run_list_real(struct pipe *pi) | |||
2213 | } | 2217 | } |
2214 | debug_printf_exec(": setting last_return_code=%d\n", rcode); | 2218 | debug_printf_exec(": setting last_return_code=%d\n", rcode); |
2215 | last_return_code = rcode; | 2219 | last_return_code = rcode; |
2216 | pi->num_progs = save_num_progs; /* restore number of programs */ | 2220 | //why? pi->num_progs = save_num_progs; |
2217 | #if ENABLE_HUSH_IF | 2221 | #if ENABLE_HUSH_IF |
2218 | if (rword == RES_IF || rword == RES_ELIF) | 2222 | if (rword == RES_IF || rword == RES_ELIF) |
2219 | next_if_code = rcode; /* can be overwritten a number of times */ | 2223 | next_if_code = rcode; /* can be overwritten a number of times */ |
@@ -2244,7 +2248,7 @@ static int run_list_real(struct pipe *pi) | |||
2244 | signal(SIGINT, SIG_IGN); | 2248 | signal(SIGINT, SIG_IGN); |
2245 | } | 2249 | } |
2246 | #endif | 2250 | #endif |
2247 | debug_printf_exec("run_list_real lvl %d return %d\n", run_list_level + 1, rcode); | 2251 | debug_printf_exec("run_list lvl %d return %d\n", run_list_level + 1, rcode); |
2248 | return rcode; | 2252 | return rcode; |
2249 | } | 2253 | } |
2250 | 2254 | ||
@@ -2318,19 +2322,19 @@ static int free_pipe_list(struct pipe *head, int indent) | |||
2318 | } | 2322 | } |
2319 | 2323 | ||
2320 | /* Select which version we will use */ | 2324 | /* Select which version we will use */ |
2321 | static int run_list(struct pipe *pi) | 2325 | static int run_and_free_list(struct pipe *pi) |
2322 | { | 2326 | { |
2323 | int rcode = 0; | 2327 | int rcode = 0; |
2324 | debug_printf_exec("run_list entered\n"); | 2328 | debug_printf_exec("run_and_free_list entered\n"); |
2325 | if (fake_mode == 0) { | 2329 | if (!fake_mode) { |
2326 | debug_printf_exec(": run_list_real with %d members\n", pi->num_progs); | 2330 | debug_printf_exec(": run_list with %d members\n", pi->num_progs); |
2327 | rcode = run_list_real(pi); | 2331 | rcode = run_list(pi); |
2328 | } | 2332 | } |
2329 | /* free_pipe_list has the side effect of clearing memory. | 2333 | /* free_pipe_list has the side effect of clearing memory. |
2330 | * In the long run that function can be merged with run_list_real, | 2334 | * In the long run that function can be merged with run_list, |
2331 | * but doing that now would hobble the debugging effort. */ | 2335 | * but doing that now would hobble the debugging effort. */ |
2332 | free_pipe_list(pi, 0); | 2336 | free_pipe_list(pi, /* indent: */ 0); |
2333 | debug_printf_exec("run_list return %d\n", rcode); | 2337 | debug_printf_exec("run_nad_free_list return %d\n", rcode); |
2334 | return rcode; | 2338 | return rcode; |
2335 | } | 2339 | } |
2336 | 2340 | ||
@@ -3224,15 +3228,17 @@ static FILE *generate_stream_from_list(struct pipe *head) | |||
3224 | int pid, channel[2]; | 3228 | int pid, channel[2]; |
3225 | 3229 | ||
3226 | xpipe(channel); | 3230 | xpipe(channel); |
3227 | pid = fork(); | 3231 | /* *** NOMMU WARNING *** */ |
3228 | if (pid < 0) { | 3232 | /* By using vfork here, we suspend parent till child exits or execs. |
3229 | bb_perror_msg_and_die("fork"); | 3233 | * If child will not do it before it fills the pipe, it can block forever |
3230 | } else if (pid == 0) { | 3234 | * in write(STDOUT_FILENO), and parent (shell) will be also stuck. |
3235 | */ | ||
3236 | pid = BB_MMU ? fork() : vfork(); | ||
3237 | if (pid < 0) | ||
3238 | bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork"); | ||
3239 | if (pid == 0) { /* child */ | ||
3231 | close(channel[0]); | 3240 | close(channel[0]); |
3232 | if (channel[1] != 1) { | 3241 | xmove_fd(channel[1], 1); |
3233 | dup2(channel[1], 1); | ||
3234 | close(channel[1]); | ||
3235 | } | ||
3236 | /* Prevent it from trying to handle ctrl-z etc */ | 3242 | /* Prevent it from trying to handle ctrl-z etc */ |
3237 | #if ENABLE_HUSH_JOB | 3243 | #if ENABLE_HUSH_JOB |
3238 | run_list_level = 1; | 3244 | run_list_level = 1; |
@@ -3244,11 +3250,12 @@ static FILE *generate_stream_from_list(struct pipe *head) | |||
3244 | * everywhere outside actual command execution. */ | 3250 | * everywhere outside actual command execution. */ |
3245 | /*set_jobctrl_sighandler(SIG_IGN);*/ | 3251 | /*set_jobctrl_sighandler(SIG_IGN);*/ |
3246 | set_misc_sighandler(SIG_DFL); | 3252 | set_misc_sighandler(SIG_DFL); |
3247 | _exit(run_list_real(head)); /* leaks memory */ | 3253 | _exit(run_list(head)); /* leaks memory */ |
3248 | } | 3254 | } |
3249 | close(channel[1]); | 3255 | close(channel[1]); |
3250 | pf = fdopen(channel[0], "r"); | 3256 | pf = fdopen(channel[0], "r"); |
3251 | return pf; | 3257 | return pf; |
3258 | /* head is freed by the caller */ | ||
3252 | } | 3259 | } |
3253 | 3260 | ||
3254 | /* Return code is exit status of the process that is run. */ | 3261 | /* Return code is exit status of the process that is run. */ |
@@ -3272,7 +3279,8 @@ static int process_command_subs(o_string *dest, struct p_context *ctx, | |||
3272 | b_free(&result); | 3279 | b_free(&result); |
3273 | 3280 | ||
3274 | p = generate_stream_from_list(inner.list_head); | 3281 | p = generate_stream_from_list(inner.list_head); |
3275 | if (p == NULL) return 1; | 3282 | if (p == NULL) |
3283 | return 1; | ||
3276 | close_on_exec_on(fileno(p)); | 3284 | close_on_exec_on(fileno(p)); |
3277 | setup_file_in_str(&pipe_str, p); | 3285 | setup_file_in_str(&pipe_str, p); |
3278 | 3286 | ||
@@ -3297,7 +3305,7 @@ static int process_command_subs(o_string *dest, struct p_context *ctx, | |||
3297 | * at the same time. That would be a lot of work, and contrary | 3305 | * at the same time. That would be a lot of work, and contrary |
3298 | * to the KISS philosophy of this program. */ | 3306 | * to the KISS philosophy of this program. */ |
3299 | retcode = fclose(p); | 3307 | retcode = fclose(p); |
3300 | free_pipe_list(inner.list_head, 0); | 3308 | free_pipe_list(inner.list_head, /* indent: */ 0); |
3301 | debug_printf("closed FILE from child, retcode=%d\n", retcode); | 3309 | debug_printf("closed FILE from child, retcode=%d\n", retcode); |
3302 | return retcode; | 3310 | return retcode; |
3303 | } | 3311 | } |
@@ -3677,8 +3685,8 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) | |||
3677 | done_word(&temp, &ctx); | 3685 | done_word(&temp, &ctx); |
3678 | done_pipe(&ctx, PIPE_SEQ); | 3686 | done_pipe(&ctx, PIPE_SEQ); |
3679 | debug_print_tree(ctx.list_head, 0); | 3687 | debug_print_tree(ctx.list_head, 0); |
3680 | debug_printf_exec("parse_stream_outer: run_list\n"); | 3688 | debug_printf_exec("parse_stream_outer: run_and_free_list\n"); |
3681 | run_list(ctx.list_head); | 3689 | run_and_free_list(ctx.list_head); |
3682 | } else { | 3690 | } else { |
3683 | if (ctx.old_flag != 0) { | 3691 | if (ctx.old_flag != 0) { |
3684 | free(ctx.stack); | 3692 | free(ctx.stack); |
@@ -3687,7 +3695,7 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) | |||
3687 | temp.nonnull = 0; | 3695 | temp.nonnull = 0; |
3688 | temp.o_quote = 0; | 3696 | temp.o_quote = 0; |
3689 | inp->p = NULL; | 3697 | inp->p = NULL; |
3690 | free_pipe_list(ctx.list_head, 0); | 3698 | free_pipe_list(ctx.list_head, /* indent: */ 0); |
3691 | } | 3699 | } |
3692 | b_free(&temp); | 3700 | b_free(&temp); |
3693 | } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */ | 3701 | } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */ |
@@ -3901,15 +3909,15 @@ int hush_main(int argc, char **argv) | |||
3901 | 3909 | ||
3902 | if (argv[optind] == NULL) { | 3910 | if (argv[optind] == NULL) { |
3903 | opt = parse_and_run_file(stdin); | 3911 | opt = parse_and_run_file(stdin); |
3904 | goto final_return; | 3912 | } else { |
3913 | debug_printf("\nrunning script '%s'\n", argv[optind]); | ||
3914 | global_argv = argv + optind; | ||
3915 | global_argc = argc - optind; | ||
3916 | input = xfopen(argv[optind], "r"); | ||
3917 | fcntl(fileno(input), F_SETFD, FD_CLOEXEC); | ||
3918 | opt = parse_and_run_file(input); | ||
3905 | } | 3919 | } |
3906 | 3920 | ||
3907 | debug_printf("\nrunning script '%s'\n", argv[optind]); | ||
3908 | global_argv = argv + optind; | ||
3909 | global_argc = argc - optind; | ||
3910 | input = xfopen(argv[optind], "r"); | ||
3911 | opt = parse_and_run_file(input); | ||
3912 | |||
3913 | final_return: | 3921 | final_return: |
3914 | 3922 | ||
3915 | #if ENABLE_FEATURE_CLEAN_UP | 3923 | #if ENABLE_FEATURE_CLEAN_UP |
diff --git a/shell/msh.c b/shell/msh.c index 9edf793ab..7a6ab2416 100644 --- a/shell/msh.c +++ b/shell/msh.c | |||
@@ -2825,11 +2825,13 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) | |||
2825 | 2825 | ||
2826 | if (pin != NULL) { | 2826 | if (pin != NULL) { |
2827 | xmove_fd(pin[0], 0); | 2827 | xmove_fd(pin[0], 0); |
2828 | if (pin[1] != 0) close(pin[1]); | 2828 | if (pin[1] != 0) |
2829 | close(pin[1]); | ||
2829 | } | 2830 | } |
2830 | if (pout != NULL) { | 2831 | if (pout != NULL) { |
2831 | xmove_fd(pout[1], 1); | 2832 | xmove_fd(pout[1], 1); |
2832 | if (pout[1] != 1) close(pout[0]); | 2833 | if (pout[1] != 1) |
2834 | close(pout[0]); | ||
2833 | } | 2835 | } |
2834 | 2836 | ||
2835 | iopp = t->ioact; | 2837 | iopp = t->ioact; |
@@ -4162,7 +4164,7 @@ static int grave(int quoted) | |||
4162 | return 0; | 4164 | return 0; |
4163 | } | 4165 | } |
4164 | if (i != 0) { | 4166 | if (i != 0) { |
4165 | waitpid(i, NULL, 0); | 4167 | waitpid(i, NULL, 0); // safe_waitpid? |
4166 | global_env.iop->argp->aword = ++cp; | 4168 | global_env.iop->argp->aword = ++cp; |
4167 | close(pf[1]); | 4169 | close(pf[1]); |
4168 | PUSHIO(afile, remap(pf[0]), | 4170 | PUSHIO(afile, remap(pf[0]), |
@@ -4181,7 +4183,8 @@ static int grave(int quoted) | |||
4181 | * echo "$files" >zz | 4183 | * echo "$files" >zz |
4182 | */ | 4184 | */ |
4183 | xmove_fd(pf[1], 1); | 4185 | xmove_fd(pf[1], 1); |
4184 | if (pf[0] != 1) close(pf[0]); | 4186 | if (pf[0] != 1) |
4187 | close(pf[0]); | ||
4185 | 4188 | ||
4186 | argument_list[0] = (char *) DEFAULT_SHELL; | 4189 | argument_list[0] = (char *) DEFAULT_SHELL; |
4187 | argument_list[1] = (char *) "-c"; | 4190 | argument_list[1] = (char *) "-c"; |
@@ -4834,9 +4837,11 @@ static int filechar(struct ioarg *ap) | |||
4834 | static int position = 0, size = 0; | 4837 | static int position = 0, size = 0; |
4835 | 4838 | ||
4836 | while (size == 0 || position >= size) { | 4839 | while (size == 0 || position >= size) { |
4837 | read_line_input(current_prompt, filechar_cmdbuf, BUFSIZ, line_input_state); | 4840 | size = read_line_input(current_prompt, filechar_cmdbuf, BUFSIZ, line_input_state); |
4838 | size = strlen(filechar_cmdbuf); | 4841 | if (size < 0) /* Error/EOF */ |
4842 | exit(0); | ||
4839 | position = 0; | 4843 | position = 0; |
4844 | /* if Ctrl-C, size == 0 and loop will repeat */ | ||
4840 | } | 4845 | } |
4841 | c = filechar_cmdbuf[position]; | 4846 | c = filechar_cmdbuf[position]; |
4842 | position++; | 4847 | position++; |
diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c index 8e1fbc384..f14f6df50 100644 --- a/util-linux/mkswap.c +++ b/util-linux/mkswap.c | |||
@@ -64,9 +64,10 @@ int mkswap_main(int argc, char **argv) | |||
64 | // Figure out how big the device is and announce our intentions. | 64 | // Figure out how big the device is and announce our intentions. |
65 | 65 | ||
66 | fd = xopen(argv[1], O_RDWR); | 66 | fd = xopen(argv[1], O_RDWR); |
67 | len = fdlength(fd); | 67 | len = lseek(fd, 0, SEEK_END); |
68 | lseek(fd, 0, SEEK_SET); | ||
68 | pagesize = getpagesize(); | 69 | pagesize = getpagesize(); |
69 | printf("Setting up swapspace version 1, size = %"OFF_FMT"d bytes\n", | 70 | printf("Setting up swapspace version 1, size = %"OFF_FMT"u bytes\n", |
70 | len - pagesize); | 71 | len - pagesize); |
71 | mkswap_selinux_setcontext(fd, argv[1]); | 72 | mkswap_selinux_setcontext(fd, argv[1]); |
72 | 73 | ||