aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-02-12 17:12:28 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-02-12 17:12:28 +0000
commita68cb75a2e72303ef4a609cab28d25ccc789d685 (patch)
treec9f1fd8ef0c1d50341c4377ce467c94ec6944881
parent0b18cd3d04b17acec73af3d2cafd00c59a3f807f (diff)
downloadbusybox-w32-a68cb75a2e72303ef4a609cab28d25ccc789d685.tar.gz
busybox-w32-a68cb75a2e72303ef4a609cab28d25ccc789d685.tar.bz2
busybox-w32-a68cb75a2e72303ef4a609cab28d25ccc789d685.zip
Applied post 1.9.0 fixes
-rw-r--r--Makefile.help1
-rw-r--r--applets/applet_tables.c2
-rw-r--r--coreutils/stty.c24
-rw-r--r--coreutils/test.c49
-rw-r--r--e2fsprogs/fsck.c6
-rw-r--r--include/libbb.h8
-rw-r--r--libbb/lineedit.c4
-rw-r--r--networking/libiproute/iproute.c10
-rw-r--r--networking/nameif.c22
-rw-r--r--networking/zcip.c24
-rw-r--r--shell/hush.c256
-rw-r--r--shell/msh.c17
-rw-r--r--util-linux/mkswap.c5
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
781static const struct mode_info *find_mode(const char *name) 781static 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
795static const struct control_info *find_control(const char *name) 787static 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
809enum { 793enum {
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};
951line_input_t *new_line_input_t(int flags); 954line_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 */
958int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state); 960int 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 */
1322int read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st) 1322int 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... */
52struct ethtool_drvinfo { 52struct 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> */
83extern char **environ;
84#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
83 85
84extern 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);
510static int free_pipe(struct pipe *pi, int indent); 513static int free_pipe(struct pipe *pi, int indent);
511/* really run the final data structures: */ 514/* really run the final data structures: */
512static int setup_redirects(struct child_prog *prog, int squirrel[]); 515static int setup_redirects(struct child_prog *prog, int squirrel[]);
513static int run_list_real(struct pipe *pi); 516static int run_list(struct pipe *pi);
514static void pseudo_exec_argv(char **argv) ATTRIBUTE_NORETURN; 517static void pseudo_exec_argv(char **argv) ATTRIBUTE_NORETURN;
515static void pseudo_exec(struct child_prog *child) ATTRIBUTE_NORETURN; 518static void pseudo_exec(struct child_prog *child) ATTRIBUTE_NORETURN;
516static int run_pipe_real(struct pipe *pi); 519static int run_pipe(struct pipe *pi);
517/* extended glob support: */ 520/* extended glob support: */
518static char **globhack(const char *src, char **strings); 521static char **globhack(const char *src, char **strings);
519static int glob_needed(const char *s); 522static 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 */
1491static void pseudo_exec(struct child_prog *child) 1493static 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 */
1776static int run_pipe_real(struct pipe *pi) 1780static 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!) */
2023static int run_list_real(struct pipe *pi) 2028static 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 */
2321static int run_list(struct pipe *pi) 2325static 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